Udostępnij za pośrednictwem


Praca z kalendarzami

Chociaż wartość daty i godziny reprezentuje moment w czasie, jego reprezentacja ciągu jest wrażliwa na kulturę i zależy zarówno od konwencji używanych do wyświetlania wartości daty i godziny przez określoną kulturę, jak i kalendarza używanego przez tę kulturę. W tym temacie omówiono obsługę kalendarzy na platformie .NET i omówiono korzystanie z klas kalendarza podczas pracy z wartościami dat.

Kalendarze na platformie .NET

Wszystkie kalendarze na platformie .NET pochodzą z klasy System.Globalization.Calendar, która zapewnia implementację kalendarza podstawowego. Jedną z klas dziedzicujących z klasy Calendar jest klasa EastAsianLunisolarCalendar, która jest klasą bazową dla wszystkich kalendarzy lunisolarnych. Platforma .NET obejmuje następujące implementacje kalendarza:

Kalendarz może być używany na jeden z dwóch sposobów:

  • Jako kalendarz używany przez określoną kulturę. Każdy obiekt CultureInfo ma bieżący kalendarz, który jest kalendarzem używanym obecnie przez obiekt. Reprezentacje ciągu wszystkich wartości daty i godziny automatycznie odzwierciedlają bieżącą kulturę i bieżący kalendarz. Zazwyczaj bieżący kalendarz jest domyślnym kalendarzem kultury. CultureInfo obiekty mają również opcjonalne kalendarze, które obejmują dodatkowe kalendarze, których może używać kultura.

  • Jako autonomiczny kalendarz niezależny od określonej kultury. W tym przypadku metody Calendar są używane do wyrażania dat jako wartości odzwierciedlających kalendarz.

Należy pamiętać, że sześć klas kalendarza — ChineseLunisolarCalendar, JapaneseLunisolarCalendar, JulianCalendar, KoreanLunisolarCalendar, PersianCalendari TaiwanLunisolarCalendar — może być używanych tylko jako autonomiczne kalendarze. Nie są one używane przez żadną kulturę jako kalendarz domyślny lub jako kalendarz opcjonalny.

Kalendarze i kultury

Każda kultura ma domyślny kalendarz, który jest definiowany przez właściwość CultureInfo.Calendar. Właściwość CultureInfo.OptionalCalendars zwraca tablicę obiektów Calendar, która określa wszystkie kalendarze obsługiwane przez określoną kulturę, w tym domyślny kalendarz tej kultury.

Poniższy przykład ilustruje właściwości CultureInfo.Calendar i CultureInfo.OptionalCalendars. Tworzy obiekt CultureInfo dla kultury tajskiej (Tajlandia) i japońskiej (Japonia) oraz wyświetla domyślne i opcjonalne kalendarze. Zwróć uwagę, że w obu przypadkach domyślny kalendarz kultury jest również uwzględniony w kolekcji CultureInfo.OptionalCalendars.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      // Create a CultureInfo for Thai in Thailand.
      CultureInfo th = CultureInfo.CreateSpecificCulture("th-TH");
      DisplayCalendars(th);

      // Create a CultureInfo for Japanese in Japan.
      CultureInfo ja = CultureInfo.CreateSpecificCulture("ja-JP");
      DisplayCalendars(ja);
   }

   static void DisplayCalendars(CultureInfo ci)
   {
      Console.WriteLine($"Calendars for the {ci.Name} culture:");

      // Get the culture's default calendar.
      Calendar defaultCalendar = ci.Calendar;
      Console.Write("   Default Calendar: {0}", GetCalendarName(defaultCalendar));

      if (defaultCalendar is GregorianCalendar)
         Console.WriteLine(" ({0})",
                           ((GregorianCalendar) defaultCalendar).CalendarType);
      else
         Console.WriteLine();

      // Get the culture's optional calendars.
      Console.WriteLine("   Optional Calendars:");
      foreach (var optionalCalendar in ci.OptionalCalendars) {
         Console.Write("{0,6}{1}", "", GetCalendarName(optionalCalendar));
         if (optionalCalendar is GregorianCalendar)
            Console.Write(" ({0})",
                          ((GregorianCalendar) optionalCalendar).CalendarType);

         Console.WriteLine();
      }
      Console.WriteLine();
   }

   static string GetCalendarName(Calendar cal)
   {
      return cal.ToString().Replace("System.Globalization.", "");
   }
}
// The example displays the following output:
//       Calendars for the th-TH culture:
//          Default Calendar: ThaiBuddhistCalendar
//          Optional Calendars:
//             ThaiBuddhistCalendar
//             GregorianCalendar (Localized)
//
//       Calendars for the ja-JP culture:
//          Default Calendar: GregorianCalendar (Localized)
//          Optional Calendars:
//             GregorianCalendar (Localized)
//             JapaneseCalendar
//             GregorianCalendar (USEnglish)
Imports System.Globalization

Public Module Example
    Public Sub Main()
        ' Create a CultureInfo for Thai in Thailand.
        Dim th As CultureInfo = CultureInfo.CreateSpecificCulture("th-TH")
        DisplayCalendars(th)

        ' Create a CultureInfo for Japanese in Japan.
        Dim ja As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        DisplayCalendars(ja)
    End Sub

    Sub DisplayCalendars(ci As CultureInfo)
        Console.WriteLine("Calendars for the {0} culture:", ci.Name)

        ' Get the culture's default calendar.
        Dim defaultCalendar As Calendar = ci.Calendar
        Console.Write("   Default Calendar: {0}", GetCalendarName(defaultCalendar))

        If TypeOf defaultCalendar Is GregorianCalendar Then
            Console.WriteLine(" ({0})",
                              CType(defaultCalendar, GregorianCalendar).CalendarType)
        Else
            Console.WriteLine()
        End If

        ' Get the culture's optional calendars.
        Console.WriteLine("   Optional Calendars:")
        For Each optionalCalendar In ci.OptionalCalendars
            Console.Write("{0,6}{1}", "", GetCalendarName(optionalCalendar))
            If TypeOf optionalCalendar Is GregorianCalendar Then
                Console.Write(" ({0})",
                              CType(optionalCalendar, GregorianCalendar).CalendarType)
            End If
            Console.WriteLine()
        Next
        Console.WriteLine()
    End Sub

    Function GetCalendarName(cal As Calendar) As String
        Return cal.ToString().Replace("System.Globalization.", "")
    End Function
End Module
' The example displays the following output:
'       Calendars for the th-TH culture:
'          Default Calendar: ThaiBuddhistCalendar
'          Optional Calendars:
'             ThaiBuddhistCalendar
'             GregorianCalendar (Localized)
'       
'       Calendars for the ja-JP culture:
'          Default Calendar: GregorianCalendar (Localized)
'          Optional Calendars:
'             GregorianCalendar (Localized)
'             JapaneseCalendar
'             GregorianCalendar (USEnglish)

Kalendarz używany obecnie przez określony obiekt CultureInfo jest definiowany przez właściwość DateTimeFormatInfo.Calendar kultury. Obiekt kultury DateTimeFormatInfo jest zwracany przez właściwość CultureInfo.DateTimeFormat. Po utworzeniu kultury jej wartość domyślna jest taka sama jak wartość właściwości CultureInfo.Calendar. Można jednak zmienić bieżący kalendarz kultury na dowolny kalendarz zawarty w tablicy zwróconej przez właściwość CultureInfo.OptionalCalendars. Jeśli spróbujesz ustawić bieżący kalendarz na taki, który nie jest zawarty w wartości właściwości CultureInfo.OptionalCalendars, zostanie zgłoszony ArgumentException.

Poniższy przykład zmienia kalendarz używany przez kulturę Arabskiej (Arabii Saudyjskiej). Najpierw tworzy instancję wartości oznaczonej jako DateTime i wyświetla ją, korzystając z ustawień bieżącej kultury — w tym przypadku angielskiego (Stany Zjednoczone) — oraz kalendarza używanego przez tę kulturę (w tym wypadku kalendarza gregoriańskiego). Następnie zmienia bieżącą kulturę na arabski (Arabia Saudyjska) i wyświetla datę przy użyciu domyślnego kalendarza Um Al-Qura. Następnie wywołuje metodę CalendarExists, aby ustalić, czy kalendarz Hidżri jest wspierany przez kulturę arabską (Arabię Saudyjską). Ponieważ kalendarz jest obsługiwany, zmienia bieżący kalendarz na Hidżri i ponownie wyświetla datę. Należy pamiętać, że w każdym przypadku data jest wyświetlana przy użyciu bieżącego kalendarza bieżącej kultury.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2011, 6, 20);

      DisplayCurrentInfo();
      // Display the date using the current culture and calendar.
      Console.WriteLine(date1.ToString("d"));
      Console.WriteLine();

      CultureInfo arSA = CultureInfo.CreateSpecificCulture("ar-SA");

      // Change the current culture to Arabic (Saudi Arabia).
      Thread.CurrentThread.CurrentCulture = arSA;
      // Display date and information about the current culture.
      DisplayCurrentInfo();
      Console.WriteLine(date1.ToString("d"));
      Console.WriteLine();

      // Change the calendar to Hijri.
      Calendar hijri = new HijriCalendar();
      if (CalendarExists(arSA, hijri)) {
         arSA.DateTimeFormat.Calendar = hijri;
         // Display date and information about the current culture.
         DisplayCurrentInfo();
         Console.WriteLine(date1.ToString("d"));
      }
   }

   private static void DisplayCurrentInfo()
   {
      Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.Name}");
      Console.WriteLine($"Current Calendar: {DateTimeFormatInfo.CurrentInfo.Calendar}");
   }

   private static bool CalendarExists(CultureInfo culture, Calendar cal)
   {
      foreach (Calendar optionalCalendar in culture.OptionalCalendars)
         if (cal.ToString().Equals(optionalCalendar.ToString()))
            return true;

      return false;
   }
}
// The example displays the following output:
//    Current Culture: en-US
//    Current Calendar: System.Globalization.GregorianCalendar
//    6/20/2011
//
//    Current Culture: ar-SA
//    Current Calendar: System.Globalization.UmAlQuraCalendar
//    18/07/32
//
//    Current Culture: ar-SA
//    Current Calendar: System.Globalization.HijriCalendar
//    19/07/32
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        Dim date1 As Date = #6/20/2011#

        DisplayCurrentInfo()
        ' Display the date using the current culture and calendar.
        Console.WriteLine(date1.ToString("d"))
        Console.WriteLine()

        Dim arSA As CultureInfo = CultureInfo.CreateSpecificCulture("ar-SA")

        ' Change the current culture to Arabic (Saudi Arabia).
        Thread.CurrentThread.CurrentCulture = arSA
        ' Display date and information about the current culture.
        DisplayCurrentInfo()
        Console.WriteLine(date1.ToString("d"))
        Console.WriteLine()

        ' Change the calendar to Hijri.
        Dim hijri As Calendar = New HijriCalendar()
        If CalendarExists(arSA, hijri) Then
            arSA.DateTimeFormat.Calendar = hijri
            ' Display date and information about the current culture.
            DisplayCurrentInfo()
            Console.WriteLine(date1.ToString("d"))
        End If
    End Sub

    Private Sub DisplayCurrentInfo()
        Console.WriteLine("Current Culture: {0}",
                          CultureInfo.CurrentCulture.Name)
        Console.WriteLine("Current Calendar: {0}",
                          DateTimeFormatInfo.CurrentInfo.Calendar)
    End Sub

    Private Function CalendarExists(ByVal culture As CultureInfo,
                                    cal As Calendar) As Boolean
        For Each optionalCalendar As Calendar In culture.OptionalCalendars
            If cal.ToString().Equals(optionalCalendar.ToString()) Then Return True
        Next
        Return False
    End Function
End Module
' The example displays the following output:
'    Current Culture: en-US
'    Current Calendar: System.Globalization.GregorianCalendar
'    6/20/2011
'    
'    Current Culture: ar-SA
'    Current Calendar: System.Globalization.UmAlQuraCalendar
'    18/07/32
'    
'    Current Culture: ar-SA
'    Current Calendar: System.Globalization.HijriCalendar
'    19/07/32

Daty i kalendarze

Z wyjątkiem konstruktorów, które zawierają parametr typu Calendar i pozwalają, aby elementy daty (czyli miesiąc, dzień i rok) odzwierciedlały wartości w określonym kalendarzu, wartości zarówno DateTime, jak i DateTimeOffset zawsze są oparte na kalendarzu gregoriańskim. Oznacza to na przykład, że właściwość DateTime.Year zwraca rok w kalendarzu gregoriańskim, a właściwość DateTime.Day zwraca dzień miesiąca w kalendarzu gregoriańskim.

Ważne

Należy pamiętać, że istnieje różnica między wartością daty a jej reprezentacją ciągu. Pierwszy jest oparty na kalendarzu gregoriańskim; ten ostatni jest oparty na bieżącym kalendarzu określonej kultury.

Poniższy przykład ilustruje tę różnicę między właściwościami DateTime a odpowiednimi metodami Calendar. W tym przykładzie bieżąca kultura to arabska (Egipt), a bieżący kalendarz to Um Al Qura. Wartość DateTime jest ustawiona na piętnasty dzień siódmego miesiąca 2011 roku. Jest jasne, że jest to interpretowane jako data gregoriańska, ponieważ te same wartości są zwracane przez metodę DateTime.ToString(String, IFormatProvider), gdy używa konwencji niezmiennej kultury. Reprezentacja łańcucha znaków daty sformatowanej przy użyciu konwencji bieżącej kultury to 14/08/32, czyli równoważna data w kalendarzu Um Al Qura. Następnie elementy DateTime i Calendar są wykorzystywane do zwracania dnia, miesiąca i roku wartości DateTime. W każdym przypadku wartości zwracane przez DateTime członków odzwierciedlają wartości w kalendarzu gregoriańskim, natomiast wartości zwracane przez UmAlQuraCalendar członków odzwierciedlają wartości w kalendarzu Uum al-Qura.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Make Arabic (Egypt) the current culture
      // and Umm al-Qura calendar the current calendar.
      CultureInfo arEG = CultureInfo.CreateSpecificCulture("ar-EG");
      Calendar cal = new UmAlQuraCalendar();
      arEG.DateTimeFormat.Calendar = cal;
      Thread.CurrentThread.CurrentCulture = arEG;

      // Display information on current culture and calendar.
      DisplayCurrentInfo();

      // Instantiate a date object.
      DateTime date1 = new DateTime(2011, 7, 15);

      // Display the string representation of the date.
      Console.WriteLine($"Date: {date1:d}");
      Console.WriteLine("Date in the Invariant Culture: {0}",
                        date1.ToString("d", CultureInfo.InvariantCulture));
      Console.WriteLine();

      // Compare DateTime properties and Calendar methods.
      Console.WriteLine($"DateTime.Month property: {date1.Month}");
      Console.WriteLine("UmAlQura.GetMonth: {0}",
                        cal.GetMonth(date1));
      Console.WriteLine();

      Console.WriteLine($"DateTime.Day property: {date1.Day}");
      Console.WriteLine("UmAlQura.GetDayOfMonth: {0}",
                        cal.GetDayOfMonth(date1));
      Console.WriteLine();

      Console.WriteLine($"DateTime.Year property: {date1.Year:D4}");
      Console.WriteLine("UmAlQura.GetYear: {0}",
                        cal.GetYear(date1));
      Console.WriteLine();
   }

   private static void DisplayCurrentInfo()
   {
      Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.Name}");
      Console.WriteLine($"Current Calendar: {DateTimeFormatInfo.CurrentInfo.Calendar}");
   }
}
// The example displays the following output:
//    Current Culture: ar-EG
//    Current Calendar: System.Globalization.UmAlQuraCalendar
//    Date: 14/08/32
//    Date in the Invariant Culture: 07/15/2011
//
//    DateTime.Month property: 7
//    UmAlQura.GetMonth: 8
//
//    DateTime.Day property: 15
//    UmAlQura.GetDayOfMonth: 14
//
//    DateTime.Year property: 2011
//    UmAlQura.GetYear: 1432
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        ' Make Arabic (Egypt) the current culture 
        ' and Umm al-Qura calendar the current calendar. 
        Dim arEG As CultureInfo = CultureInfo.CreateSpecificCulture("ar-EG")
        Dim cal As Calendar = New UmAlQuraCalendar()
        arEG.DateTimeFormat.Calendar = cal
        Thread.CurrentThread.CurrentCulture = arEG

        ' Display information on current culture and calendar.
        DisplayCurrentInfo()

        ' Instantiate a date object.
        Dim date1 As Date = #07/15/2011#

        ' Display the string representation of the date.
        Console.WriteLine("Date: {0:d}", date1)
        Console.WriteLine("Date in the Invariant Culture: {0}",
                          date1.ToString("d", CultureInfo.InvariantCulture))
        Console.WriteLine()

        ' Compare DateTime properties and Calendar methods.
        Console.WriteLine("DateTime.Month property: {0}", date1.Month)
        Console.WriteLine("UmAlQura.GetMonth: {0}",
                          cal.GetMonth(date1))
        Console.WriteLine()

        Console.WriteLine("DateTime.Day property: {0}", date1.Day)
        Console.WriteLine("UmAlQura.GetDayOfMonth: {0}",
                          cal.GetDayOfMonth(date1))
        Console.WriteLine()

        Console.WriteLine("DateTime.Year property: {0:D4}", date1.Year)
        Console.WriteLine("UmAlQura.GetYear: {0}",
                          cal.GetYear(date1))
        Console.WriteLine()
    End Sub

    Private Sub DisplayCurrentInfo()
        Console.WriteLine("Current Culture: {0}",
                          CultureInfo.CurrentCulture.Name)
        Console.WriteLine("Current Calendar: {0}",
                          DateTimeFormatInfo.CurrentInfo.Calendar)
    End Sub
End Module
' The example displays the following output:
'    Current Culture: ar-EG
'    Current Calendar: System.Globalization.UmAlQuraCalendar
'    Date: 14/08/32
'    Date in the Invariant Culture: 07/15/2011
'    
'    DateTime.Month property: 7
'    UmAlQura.GetMonth: 8
'    
'    DateTime.Day property: 15
'    UmAlQura.GetDayOfMonth: 14
'    
'    DateTime.Year property: 2011
'    UmAlQura.GetYear: 1432

Inicjalizuj daty na podstawie kalendarza

Ponieważ wartości DateTime i DateTimeOffset są oparte na kalendarzu gregoriańskim, należy wywołać przeciążony konstruktor zawierający parametr typu Calendar, aby utworzyć instancję wartości daty, jeśli chcesz użyć wartości dnia, miesiąca lub roku z innego kalendarza. Można również wywołać jedno z przeciążeń metody Calendar.ToDateTime konkretnego kalendarza, aby utworzyć obiekt DateTime na podstawie wartości danego kalendarza.

Poniższy przykład tworzy wystąpienie jednej wartości DateTime, przekazując obiekt HebrewCalendar do konstruktora DateTime i tworzy wystąpienie drugiej wartości DateTime przez wywołanie metody HebrewCalendar.ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32). Ponieważ dwie wartości są tworzone z identycznymi wartościami z kalendarza hebrajskiego, wywołanie metody DateTime.Equals pokazuje, że dwie wartości DateTime są równe.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      HebrewCalendar hc = new HebrewCalendar();

      DateTime date1 = new DateTime(5771, 6, 1, hc);
      DateTime date2 = hc.ToDateTime(5771, 6, 1, 0, 0, 0, 0);

      Console.WriteLine("{0:d} (Gregorian) = {1:d2}/{2:d2}/{3:d4} ({4}): {5}",
                        date1,
                        hc.GetMonth(date2),
                        hc.GetDayOfMonth(date2),
                        hc.GetYear(date2),
                        GetCalendarName(hc),
                        date1.Equals(date2));
   }

   private static string GetCalendarName(Calendar cal)
   {
      return cal.ToString().Replace("System.Globalization.", "").
                            Replace("Calendar", "");
   }
}
// The example displays the following output:
//    2/5/2011 (Gregorian) = 06/01/5771 (Hebrew): True
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim hc As New HebrewCalendar()

        Dim date1 As New Date(5771, 6, 1, hc)
        Dim date2 As Date = hc.ToDateTime(5771, 6, 1, 0, 0, 0, 0)

        Console.WriteLine("{0:d} (Gregorian) = {1:d2}/{2:d2}/{3:d4} ({4}): {5}",
                          date1,
                          hc.GetMonth(date2),
                          hc.GetDayOfMonth(date2),
                          hc.GetYear(date2),
                          GetCalendarName(hc),
                          date1.Equals(date2))
    End Sub

    Private Function GetCalendarName(cal As Calendar) As String
        Return cal.ToString().Replace("System.Globalization.", "").
                              Replace("Calendar", "")
    End Function
End Module
' The example displays the following output:
'   2/5/2011 (Gregorian) = 06/01/5771 (Hebrew): True

Przedstawiaj daty w bieżącym kalendarzu

Metody formatowania daty i godziny zawsze używają bieżącego kalendarza podczas konwertowania dat na ciągi. Oznacza to, że ciąg reprezentujący rok, miesiąc i dzień miesiąca odzwierciedlają bieżący kalendarz i niekoniecznie odzwierciedlają kalendarz gregoriański.

W poniższym przykładzie pokazano, jak bieżący kalendarz wpływa na reprezentację ciągu daty. Zmienia bieżącą kulturę na chińską (tradycyjną, Tajwan) i inicjuje wartość daty. Następnie wyświetla bieżący kalendarz i datę, zmienia bieżący kalendarz na TaiwanCalendari wyświetla bieżący kalendarz i datę po raz kolejny. Gdy data jest wyświetlana po raz pierwszy, jest reprezentowana jako data w kalendarzu gregoriańskim. Za drugim razem, gdy jest wyświetlany, jest przedstawiany jako data w kalendarium tajwańskim.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Change the current culture to zh-TW.
      CultureInfo zhTW = CultureInfo.CreateSpecificCulture("zh-TW");
      Thread.CurrentThread.CurrentCulture = zhTW;
      // Define a date.
      DateTime date1 = new DateTime(2011, 1, 16);

      // Display the date using the default (Gregorian) calendar.
      Console.WriteLine($"Current calendar: {zhTW.DateTimeFormat.Calendar}");
      Console.WriteLine(date1.ToString("d"));

      // Change the current calendar and display the date.
      zhTW.DateTimeFormat.Calendar = new TaiwanCalendar();
      Console.WriteLine($"Current calendar: {zhTW.DateTimeFormat.Calendar}");
      Console.WriteLine(date1.ToString("d"));
   }
}
// The example displays the following output:
//    Current calendar: System.Globalization.GregorianCalendar
//    2011/1/16
//    Current calendar: System.Globalization.TaiwanCalendar
//    100/1/16
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        ' Change the current culture to zh-TW.
        Dim zhTW As CultureInfo = CultureInfo.CreateSpecificCulture("zh-TW")
        Thread.CurrentThread.CurrentCulture = zhTW
        ' Define a date.
        Dim date1 As Date = #1/16/2011#

        ' Display the date using the default (Gregorian) calendar.
        Console.WriteLine("Current calendar: {0}",
                          zhTW.DateTimeFormat.Calendar)
        Console.WriteLine(date1.ToString("d"))

        ' Change the current calendar and display the date.
        zhTW.DateTimeFormat.Calendar = New TaiwanCalendar()
        Console.WriteLine("Current calendar: {0}",
                          zhTW.DateTimeFormat.Calendar)
        Console.WriteLine(date1.ToString("d"))
    End Sub
End Module
' The example displays the following output:
'    Current calendar: System.Globalization.GregorianCalendar
'    2011/1/16
'    Current calendar: System.Globalization.TaiwanCalendar
'    100/1/16

Reprezentowanie dat w kalendarzu nienależącym do bieżącego

Aby reprezentować datę przy użyciu kalendarza, który nie jest bieżącym kalendarzem określonej kultury, należy wywołać metody tego obiektu Calendar. Na przykład metody Calendar.GetYear, Calendar.GetMonthi Calendar.GetDayOfMonth konwertują rok, miesiąc i dzień na wartości odzwierciedlające określony kalendarz.

Ostrzeżenie

Ponieważ niektóre kalendarze nie są opcjonalnymi kalendarzami żadnej kultury, reprezentowanie dat w tych kalendarzach zawsze wymaga wywoływania metod kalendarza. Dotyczy to wszystkich kalendarzy, które pochodzą z klas EastAsianLunisolarCalendar, JulianCalendari PersianCalendar.

W poniższym przykładzie użyto obiektu JulianCalendar do utworzenia daty 9 stycznia 1905 roku w kalendarzu juliańskim. Gdy ta data jest wyświetlana przy użyciu kalendarza domyślnego (Gregoriańskiego), jest reprezentowana jako 22 stycznia 1905. Wywołania poszczególnych metod JulianCalendar umożliwiają przedstawienie daty w kalendarzu Julian.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      JulianCalendar julian = new JulianCalendar();
      DateTime date1 = new DateTime(1905, 1, 9, julian);

      Console.WriteLine("Date ({0}): {1:d}",
                        CultureInfo.CurrentCulture.Calendar,
                        date1);
      Console.WriteLine("Date in Julian calendar: {0:d2}/{1:d2}/{2:d4}",
                        julian.GetMonth(date1),
                        julian.GetDayOfMonth(date1),
                        julian.GetYear(date1));
   }
}
// The example displays the following output:
//    Date (System.Globalization.GregorianCalendar): 1/22/1905
//    Date in Julian calendar: 01/09/1905
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim julian As New JulianCalendar()
        Dim date1 As New Date(1905, 1, 9, julian)

        Console.WriteLine("Date ({0}): {1:d}",
                          CultureInfo.CurrentCulture.Calendar,
                          date1)
        Console.WriteLine("Date in Julian calendar: {0:d2}/{1:d2}/{2:d4}",
                          julian.GetMonth(date1),
                          julian.GetDayOfMonth(date1),
                          julian.GetYear(date1))
    End Sub
End Module
' The example displays the following output:
'    Date (System.Globalization.GregorianCalendar): 1/22/1905
'    Date in Julian calendar: 01/09/1905

Kalendarze i zakresy dat

Najwcześniejsza data obsługiwana przez kalendarz jest wskazywana przez właściwość Calendar.MinSupportedDateTime tego kalendarza. Dla klasy GregorianCalendar data to 1 stycznia 0001 n.e. Większość innych kalendarzy na platformie .NET obsługuje późniejszą datę. Próba pracy z wartością daty i godziny, która poprzedza najwcześniejszą obsługiwaną datę kalendarza, zgłasza wyjątek ArgumentOutOfRangeException.

Istnieje jednak jeden ważny wyjątek. Domyślna (niezainicjowana) wartość obiektu DateTime oraz obiektu DateTimeOffset są równe wartości GregorianCalendar.MinSupportedDateTime. Jeśli spróbujesz sformatować tę datę w kalendarzu, który nie obsługuje 1 stycznia 0001 C.E. i nie podajesz specyfikatora formatu, metoda formatowania używa specyfikatora formatu "s" (sortowalnego wzorca daty/godziny) zamiast specyfikatora formatu "G" (ogólny wzorzec daty/godziny). W związku z tym operacja formatowania nie zgłasza wyjątku ArgumentOutOfRangeException. Zamiast tego zwraca nieobsługiwaną datę. Jest to pokazane w poniższym przykładzie, który wyświetla wartość DateTime.MinValue, gdy bieżąca kultura jest ustawiona na japoński (Japonia) z kalendarzem japońskim i arabskim (Egipt) z kalendarzem Um Al Qura. Ustawia również bieżącą kulturę na angielski (Stany Zjednoczone) i wywołuje metodę DateTime.ToString(IFormatProvider) z każdym z tych obiektów CultureInfo. W każdym przypadku data jest wyświetlana przy użyciu wzorca daty/czasu umożliwiającego sortowanie.

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      DateTime dat = DateTime.MinValue;

      // Change the current culture to ja-JP with the Japanese Calendar.
      CultureInfo jaJP = CultureInfo.CreateSpecificCulture("ja-JP");
      jaJP.DateTimeFormat.Calendar = new JapaneseCalendar();
      Thread.CurrentThread.CurrentCulture = jaJP;
      Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                        jaJP.DateTimeFormat.Calendar.MinSupportedDateTime,
                        GetCalendarName(jaJP));
      // Attempt to display the date.
      Console.WriteLine(dat.ToString());
      Console.WriteLine();

      // Change the current culture to ar-EG with the Um Al Qura calendar.
      CultureInfo arEG = CultureInfo.CreateSpecificCulture("ar-EG");
      arEG.DateTimeFormat.Calendar = new UmAlQuraCalendar();
      Thread.CurrentThread.CurrentCulture = arEG;
      Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                        arEG.DateTimeFormat.Calendar.MinSupportedDateTime,
                        GetCalendarName(arEG));
      // Attempt to display the date.
      Console.WriteLine(dat.ToString());
      Console.WriteLine();

      // Change the current culture to en-US.
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
      Console.WriteLine(dat.ToString(jaJP));
      Console.WriteLine(dat.ToString(arEG));
      Console.WriteLine(dat.ToString("d"));
   }

   private static string GetCalendarName(CultureInfo culture)
   {
      Calendar cal = culture.DateTimeFormat.Calendar;
      return cal.GetType().Name.Replace("System.Globalization.", "").Replace("Calendar", "");
   }
}
// The example displays the following output:
//       Earliest supported date by Japanese calendar: 明治 1/9/8
//       0001-01-01T00:00:00
//
//       Earliest supported date by UmAlQura calendar: 01/01/18
//       0001-01-01T00:00:00
//
//       0001-01-01T00:00:00
//       0001-01-01T00:00:00
//       1/1/0001
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        Dim dat As Date = DateTime.MinValue

        ' Change the current culture to ja-JP with the Japanese Calendar.
        Dim jaJP As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        jaJP.DateTimeFormat.Calendar = New JapaneseCalendar()
        Thread.CurrentThread.CurrentCulture = jaJP
        Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                          jaJP.DateTimeFormat.Calendar.MinSupportedDateTime,
                          GetCalendarName(jaJP))
        ' Attempt to display the date.
        Console.WriteLine(dat.ToString())
        Console.WriteLine()

        ' Change the current culture to ar-EG with the Um Al Qura calendar.
        Dim arEG As CultureInfo = CultureInfo.CreateSpecificCulture("ar-EG")
        arEG.DateTimeFormat.Calendar = New UmAlQuraCalendar()
        Thread.CurrentThread.CurrentCulture = arEG
        Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                          arEG.DateTimeFormat.Calendar.MinSupportedDateTime,
                          GetCalendarName(arEG))
        ' Attempt to display the date.
        Console.WRiteLine(dat.ToString())
        Console.WRiteLine()

        ' Change the current culture to en-US.
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
        Console.WriteLine(dat.ToString(jaJP))
        Console.WriteLine(dat.ToString(arEG))
        Console.WriteLine(dat.ToString("d"))
    End Sub

    Private Function GetCalendarName(culture As CultureInfo) As String
        Dim cal As Calendar = culture.DateTimeFormat.Calendar
        Return cal.GetType().Name.Replace("System.Globalization.", "").Replace("Calendar", "")
    End Function
End Module
' The example displays the following output:
'       Earliest supported date by Japanese calendar: 明治 1/9/8
'       0001-01-01T00:00:00
'       
'       Earliest supported date by UmAlQura calendar: 01/01/18
'       0001-01-01T00:00:00
'       
'       0001-01-01T00:00:00
'       0001-01-01T00:00:00
'       1/1/0001

Praca z erami

Kalendarze zwykle dzielą daty na epoki. Jednak klasy Calendar na platformie .NET nie obsługują każdej ery zdefiniowanej przez kalendarz, a większość klas Calendar obsługuje tylko jedną erę. Tylko klasy JapaneseCalendar i JapaneseLunisolarCalendar obsługują wiele epok.

Ważne

Era Reiwa, nowa era w JapaneseCalendar i JapaneseLunisolarCalendar, rozpoczyna się 1 maja 2019 roku. Ta zmiana dotyczy wszystkich aplikacji korzystających z tych kalendarzy. Aby uzyskać więcej informacji, zobacz następujące artykuły:

Era w większości kalendarzy oznacza niezwykle długi okres. Na przykład w kalendarzu gregoriańskim obecna era obejmuje ponad dwa tysiąclecia. W przypadku JapaneseCalendar i JapaneseLunisolarCalendar, dwa kalendarze, które obsługują wiele epok, to nie ma miejsca. Era odpowiada okresowi panowania cesarza. Obsługa wielu epok, szczególnie wtedy, gdy górna granica obecnej ery jest nieznana, stanowi szczególne wyzwania.

Ery i nazwy er

Na platformie .NET liczby całkowite reprezentujące epoki obsługiwane przez określoną implementację kalendarza są przechowywane w odwrotnej kolejności w tablicy Calendar.Eras. Bieżąca era (czyli era z najnowszym zakresem czasu) wynosi zero indeksu, a w przypadku klas Calendar obsługujących wiele epok każdy kolejny indeks odzwierciedla poprzednią erę. Właściwość statyczna Calendar.CurrentEra definiuje indeks bieżącej ery w tablicy Calendar.Eras; jest to stała, której wartość jest zawsze równa zero. Poszczególne klasy Calendar obejmują również pola statyczne, które zwracają wartość bieżącej ery. Są one wymienione w poniższej tabeli.

Klasa kalendarza Bieżące pole ery
ChineseLunisolarCalendar ChineseEra
GregorianCalendar ADEra
HebrewCalendar HebrewEra
HijriCalendar HijriEra
JapaneseLunisolarCalendar JapaneseEra
JulianCalendar JulianEra
KoreanCalendar KoreanEra
KoreanLunisolarCalendar GregorianEra
PersianCalendar PersianEra
ThaiBuddhistCalendar ThaiBuddhistEra
UmAlQuraCalendar UmAlQuraEra

Nazwę odpowiadającą danemu numerowi ery można pobrać, przekazując numer ery do metody DateTimeFormatInfo.GetEraName lub DateTimeFormatInfo.GetAbbreviatedEraName. Poniższy przykład wywołuje te metody w celu pobrania informacji o obsłudze ery w klasie GregorianCalendar. Wyświetla gregoriańską datę kalendarza odpowiadającą 1 stycznia drugiego roku bieżącej ery, a także datę kalendarza gregoriańskiego odpowiadającą 1 stycznia drugiego roku każdej obsługiwanej ery kalendarza japońskiego.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      int year = 2;
      int month = 1;
      int day = 1;
      Calendar cal = new JapaneseCalendar();

      Console.WriteLine("\nDate instantiated without an era:");
      DateTime date1 = new DateTime(year, month, day, 0, 0, 0, 0, cal);
      Console.WriteLine("{0}/{1}/{2} in Japanese Calendar -> {3:d} in Gregorian",
                        cal.GetMonth(date1), cal.GetDayOfMonth(date1),
                        cal.GetYear(date1), date1);

      Console.WriteLine("\nDates instantiated with eras:");
      foreach (int era in cal.Eras) {
         DateTime date2 = cal.ToDateTime(year, month, day, 0, 0, 0, 0, era);
         Console.WriteLine("{0}/{1}/{2} era {3} in Japanese Calendar -> {4:d} in Gregorian",
                           cal.GetMonth(date2), cal.GetDayOfMonth(date2),
                           cal.GetYear(date2), cal.GetEra(date2), date2);
      }
   }
}
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim year As Integer = 2
        Dim month As Integer = 1
        Dim day As Integer = 1
        Dim cal As New JapaneseCalendar()

        Console.WriteLine("Date instantiated without an era:")
        Dim date1 As New Date(year, month, day, 0, 0, 0, 0, cal)
        Console.WriteLine("{0}/{1}/{2} in Japanese Calendar -> {3:d} in Gregorian",
                          cal.GetMonth(date1), cal.GetDayOfMonth(date1),
                          cal.GetYear(date1), date1)
        Console.WriteLine()

        Console.WriteLine("Dates instantiated with eras:")
        For Each era As Integer In cal.Eras
            Dim date2 As Date = cal.ToDateTime(year, month, day, 0, 0, 0, 0, era)
            Console.WriteLine("{0}/{1}/{2} era {3} in Japanese Calendar -> {4:d} in Gregorian",
                              cal.GetMonth(date2), cal.GetDayOfMonth(date2),
                              cal.GetYear(date2), cal.GetEra(date2), date2)
        Next
    End Sub
End Module

Ponadto ciąg formatu daty i godziny "g" zawiera nazwę ery kalendarza w ciągu reprezentującym datę i godzinę. Aby uzyskać więcej informacji, zobacz Niestandardowe ciągi formatu daty i czasu.

Tworzenie instancji daty z epoką

W przypadku dwóch klas Calendar, które obsługują wiele epok, data składająca się z określonego roku, miesiąca i dnia wartości miesiąca może być niejednoznaczna. Na przykład wszystkie era obsługiwane przez JapaneseCalendar mają lata, których liczba wynosi 1. Zwykle, jeśli era nie jest określona, metody daty i godziny i kalendarza zakładają, że wartości należą do bieżącej ery. Dotyczy to konstruktorów DateTime i DateTimeOffset zawierających parametry typu Calendar, a także metod JapaneseCalendar.ToDateTime i JapaneseLunisolarCalendar.ToDateTime. Poniższy przykład tworzy wystąpienie daty reprezentującej 1 stycznia drugiego roku nieokreślonej ery. Jeśli wykonasz przykład, gdy era Reiwa jest bieżącą erą, data jest interpretowana jako drugi rok ery Reiwa. Era, 令和, poprzedza datę w ciągu zwróconym przez metodę DateTime.ToString(String, IFormatProvider) i odpowiada 1 stycznia 2020 r. w kalendarzu gregoriańskim. (Era Reiwa rozpoczyna się w roku 2019 kalendarza gregoriańskiego).

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
        var japaneseCal = new JapaneseCalendar();
        var jaJp = new CultureInfo("ja-JP");
        jaJp.DateTimeFormat.Calendar = japaneseCal;

        var date = new DateTime(2, 1, 1, japaneseCal);
        Console.WriteLine($"Gregorian calendar date: {date:d}");
        Console.WriteLine($"Japanese calendar date: {date.ToString("d", jaJp)}");
    }
}
Imports System.Globalization

Public Module Example
    Public Sub Main()
        Dim japaneseCal = New JapaneseCalendar()
        Dim jaJp = New CultureInfo("ja-JP")
        jaJp.DateTimeFormat.Calendar = japaneseCal

        Dim dat = New DateTime(2, 1, 1, japaneseCal)
        Console.WriteLine($"Gregorian calendar dat: {dat:d}")
        Console.WriteLine($"Japanese calendar dat: {dat.ToString("d", jaJp)}")
    End Sub
End Module

Jeśli jednak era ulegnie zmianie, intencja tego kodu stanie się niejednoznaczna. Czy data ta ma reprezentować drugi rok obecnej ery, czy ma reprezentować drugi rok ery Heisei? Istnieją dwa sposoby uniknięcia tej niejednoznaczności:

  • Utwórz instancję wartości daty i godziny przy użyciu domyślnej klasy GregorianCalendar. Następnie możesz użyć kalendarza japońskiego lub japońskiego kalendarza Lunisolar dla ciągu reprezentacji dat, jak pokazano w poniższym przykładzie.

    using System;
    using System.Globalization;
    
    public class Example
    {
        public static void Main()
        {
            var japaneseCal = new JapaneseCalendar();
            var jaJp = new CultureInfo("ja-JP");
            jaJp.DateTimeFormat.Calendar = japaneseCal;
    
            var date = new DateTime(1905, 2, 12);
            Console.WriteLine($"Gregorian calendar date: {date:d}");
    
            // Call the ToString(IFormatProvider) method.
            Console.WriteLine($"Japanese calendar date: {date.ToString("d", jaJp)}");
    
            // Use a FormattableString object.
            FormattableString fmt = $"{date:d}";
            Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}");
    
            // Use the JapaneseCalendar object.
            Console.WriteLine($"Japanese calendar date: {jaJp.DateTimeFormat.GetEraName(japaneseCal.GetEra(date))}" +
                              $"{japaneseCal.GetYear(date)}/{japaneseCal.GetMonth(date)}/{japaneseCal.GetDayOfMonth(date)}");
    
            // Use the current culture.
            CultureInfo.CurrentCulture = jaJp;
            Console.WriteLine($"Japanese calendar date: {date:d}");
        }
    }
    // The example displays the following output:
    //   Gregorian calendar date: 2/12/1905
    //   Japanese calendar date: 明治38/2/12
    //   Japanese calendar date: 明治38/2/12
    //   Japanese calendar date: 明治38/2/12
    //   Japanese calendar date: 明治38/2/12
    
    Imports System.Globalization
    
    Public Module Example
        Public Sub Main()
            Dim japaneseCal = New JapaneseCalendar()
            Dim jaJp = New CultureInfo("ja-JP")
            jaJp.DateTimeFormat.Calendar = japaneseCal
    
            Dim dat = New DateTime(1905, 2, 12)
            Console.WriteLine($"Gregorian calendar date: {dat:d}")
    
            ' Call the ToString(IFormatProvider) method.
            Console.WriteLine($"Japanese calendar date: {dat.ToString("d", jaJp)}")
    
            ' Use a FormattableString object.
            Dim fmt As FormattableString = $"{dat:d}"
            Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}")
    
            ' Use the JapaneseCalendar object.
            Console.WriteLine($"Japanese calendar date: {jaJp.DateTimeFormat.GetEraName(japaneseCal.GetEra(dat))}" +
                              $"{japaneseCal.GetYear(dat)}/{japaneseCal.GetMonth(dat)}/{japaneseCal.GetDayOfMonth(dat)}")
    
            ' Use the current culture.
            CultureInfo.CurrentCulture = jaJp
            Console.WriteLine($"Japanese calendar date: {dat:d}")
        End Sub
    End Module
    ' The example displays the following output:
    '   Gregorian calendar date: 2/12/1905
    '   Japanese calendar date: 明治38/2/12
    '   Japanese calendar date: 明治38/2/12
    '   Japanese calendar date: 明治38/2/12
    '   Japanese calendar date: 明治38/2/12
    
    
    
  • Wywołaj metodę daty i godziny, która jawnie określa erę. Obejmuje to następujące metody:

    W poniższym przykładzie skorzystano z trzech z tych metod, aby utworzyć datę i godzinę w erze Meiji, która rozpoczęła się 8 września 1868 r. i zakończyła się 29 lipca 1912 r.

    using System;
    using System.Globalization;
    
    public class Example
    {
        public static void Main()
        {
            var japaneseCal = new JapaneseCalendar();
            var jaJp = new CultureInfo("ja-JP");
            jaJp.DateTimeFormat.Calendar = japaneseCal;
    
            // We can get the era index by calling DateTimeFormatInfo.GetEraName.
            int eraIndex = 0;
    
            for (int ctr = 0; ctr < jaJp.DateTimeFormat.Calendar.Eras.Length; ctr++)
               if (jaJp.DateTimeFormat.GetEraName(ctr) == "明治")
                  eraIndex = ctr;
            var date1 = japaneseCal.ToDateTime(23, 9, 8, 0, 0, 0, 0, eraIndex);
            Console.WriteLine($"{date1.ToString("d", jaJp)} (Gregorian {date1:d})");
    
            try {
                var date2 = DateTime.Parse("明治23/9/8", jaJp);
                Console.WriteLine($"{date2.ToString("d", jaJp)} (Gregorian {date2:d})");
            }
            catch (FormatException)
            {
                Console.WriteLine("The parsing operation failed.");
            }
    
            try {
                var date3 = DateTime.ParseExact("明治23/9/8", "gyy/M/d", jaJp);
                Console.WriteLine($"{date3.ToString("d", jaJp)} (Gregorian {date3:d})");
            }
            catch (FormatException)
            {
                Console.WriteLine("The parsing operation failed.");
            }
        }
    }
    // The example displays the following output:
    //   明治23/9/8 (Gregorian 9/8/1890)
    //   明治23/9/8 (Gregorian 9/8/1890)
    //   明治23/9/8 (Gregorian 9/8/1890)
    
    Imports System.Globalization
    
    Public Module Example
        Public Sub Main()
            Dim japaneseCal = New JapaneseCalendar()
            Dim jaJp = New CultureInfo("ja-JP")
            jaJp.DateTimeFormat.Calendar = japaneseCal
    
            ' We can get the era index by calling DateTimeFormatInfo.GetEraName.
            Dim eraIndex As Integer = 0
    
            For ctr As Integer = 0 To jaJp.DateTimeFormat.Calendar.Eras.Length - 1
                If jaJp.DateTimeFormat.GetEraName(ctr) = "明治" Then eraIndex = ctr
            Next
            Dim date1 = japaneseCal.ToDateTime(23, 9, 8, 0, 0, 0, 0, eraIndex)
            Console.WriteLine($"{date1.ToString("d", jaJp)} (Gregorian {date1:d})")
    
            Try
                Dim date2 = DateTime.Parse("明治23/9/8", jaJp)
                Console.WriteLine($"{date2.ToString("d", jaJp)} (Gregorian {date2:d})")
            Catch e As FormatException
                Console.WriteLine("The parsing operation failed.")
            End Try
    
            Try
                Dim date3 = DateTime.ParseExact("明治23/9/8", "gyy/M/d", jaJp)
                Console.WriteLine($"{date3.ToString("d", jaJp)} (Gregorian {date3:d})")
            Catch e As FormatException
                Console.WriteLine("The parsing operation failed.")
            End Try
        End Sub
    End Module
    ' The example displays the following output:
    '   明治23/9/8 (Gregorian 9/8/1890)
    '   明治23/9/8 (Gregorian 9/8/1890)
    '   明治23/9/8 (Gregorian 9/8/1890)
    

Wskazówka

Podczas pracy z kalendarzami, które obsługują wiele epok, zawsze używaj daty gregoriańskiej do utworzenia daty lub określ erę podczas ustalania daty i godziny na podstawie tego kalendarza.

Określając erę do metody ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32), należy podać indeks ery we właściwości Eras kalendarza. Jednak w przypadku kalendarzy, których era podlega zmianie, indeksy te nie są wartościami stałymi; bieżąca era wynosi indeks 0, a najstarsza era jest w indeksie Eras.Length - 1. Po dodaniu nowej ery do kalendarza indeksy poprzednich epok zwiększają się o jedną. Odpowiedni indeks ery można podać w następujący sposób:

Kalendarze, ery i zakresy dat: Luźniejsze sprawdzanie zakresów

Bardzo podobnie jak poszczególne kalendarze mają obsługiwane zakresy dat, epoki w klasach JapaneseCalendar i JapaneseLunisolarCalendar mają również obsługiwane zakresy. Wcześniej platforma .NET używała rygorystycznych kontroli zakresu ery, aby upewnić się, że data specyficzna dla epoki mieściła się w zakresie tej epoki. Oznacza to, że jeśli data znajduje się poza zakresem określonej ery, metoda zgłasza ArgumentOutOfRangeException. Obecnie platforma .NET domyślnie używa łagodnego sprawdzania zakresu. Aktualizacje wszystkich wersji platformy .NET zaktualizowały kontrole zakresu epoki; podjęcie próby utworzenia specyficznej dla epoki daty znajdującej się poza zakresem określonej ery przenosi się do następującej ery i nie jest zgłaszany żaden wyjątek.

Poniższy przykład próbuje zainicjować datę w 65 roku ery Showa, która rozpoczęła się 25 grudnia 1926 roku i zakończyła się 7 stycznia 1989 roku. Ta data odpowiada 9 stycznia 1990 r., który znajduje się poza zakresem ery Showa w JapaneseCalendar. Jak pokazano w danych wyjściowych z przykładu, data wyświetlana w przykładzie to 9 stycznia 1990 r. w drugim roku ery Heisei.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var jaJp = new CultureInfo("ja-JP");
      var cal = new JapaneseCalendar();
      jaJp.DateTimeFormat.Calendar = cal;
      string showaEra = "昭和";

      var dt = cal.ToDateTime(65, 1, 9, 15, 0, 0, 0, GetEraIndex(showaEra));
      FormattableString fmt = $"{dt:d}";

      Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}");
      Console.WriteLine($"Gregorian calendar date: {fmt}");

      int GetEraIndex(string eraName)
      {
         foreach (var ctr in cal.Eras)
            if (jaJp.DateTimeFormat.GetEraName(ctr) == eraName)
               return ctr;

         return 0;
      }
   }
}
// The example displays the following output:
//   Japanese calendar date: 平成2/1/9
//   Gregorian calendar date: 1/9/1990
Imports System.Globalization

Public Module Example
    Dim jaJp As CultureInfo
    Dim cal As Calendar

    Public Sub Main()
        jaJp = New CultureInfo("ja-JP")
        cal = New JapaneseCalendar()
        jaJp.DateTimeFormat.Calendar = cal
        Dim showaEra = "昭和"

        Dim dt = cal.ToDateTime(65, 1, 9, 15, 0, 0, 0, GetEraIndex(showaEra))
        Dim fmt As FormattableString = $"{dt:d}"
        Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}")
        Console.WriteLine($"Gregorian calendar date: {fmt}")
    End Sub

    Private Function GetEraIndex(eraName As String) As Integer
        For Each ctr As Integer In cal.Eras
            If jaJp.DateTimeFormat.GetEraName(ctr) = eraName Then Return ctr
        Next
        Return 0
    End Function
End Module
' The example displays the following output:
'   Japanese calendar date: 平成2/1/9
'   Gregorian calendar date: 1/9/1990

Jeśli złagodzone kontrole zakresu są niepożądane, możesz przywrócić ścisłe kontrole zakresu na wiele sposobów, w zależności od wersji platformy .NET, na której działa aplikacja:

  • .NET Core: Dodaj następujące elementy do pliku konfiguracji .netcore.runtime.json:

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceJapaneseEraYearRanges": true
      }
    }
    
  • .NET Framework 4.6 lub nowsza wersja: Ustaw następujący przełącznik AppContext w pliku app.config:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.EnforceJapaneseEraYearRanges=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 lub starszej wersji: Ustaw następującą wartość rejestru:

    Wartość
    klucz HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    Entry Przełącznik.System.Globalization.WymuśZakresyLatJapońskiejEry
    Typ REG_SZ
    Wartość prawda

W przypadku włączenia ścisłego sprawdzania zakresu poprzedni przykład zgłasza błąd ArgumentOutOfRangeException i wyświetla następujące dane wyjściowe:

Unhandled Exception: System.ArgumentOutOfRangeException: Valid values are between 1 and 64, inclusive.
Parameter name: year
   at System.Globalization.GregorianCalendarHelper.GetYearOffset(Int32 year, Int32 era, Boolean throwOnError)
   at System.Globalization.GregorianCalendarHelper.ToDateTime(Int32 year, Int32 month, Int32 day, Int32 hour, Int32 minute, Int32 second, Int32 millisecond, Int32 era)
   at Example.Main()

Reprezentacja dat w kalendarzach z wieloma erami

Jeśli obiekt Calendar obsługuje ery i jest bieżącym kalendarzem obiektu CultureInfo, era jest uwzględniona w ciągu tekstowym reprezentującym wartość daty i godziny dla wzorców pełnej daty i godziny, daty długiej i daty krótkiej. Poniższy przykład przedstawia te wzorce dat, gdy bieżąca kultura to Japonia (japoński), a bieżący kalendarz to kalendarz japoński.

using System;
using System.Globalization;
using System.IO;
using System.Threading;

public class Example
{
   public static void Main()
   {
      StreamWriter sw = new StreamWriter(@".\eras.txt");
      DateTime dt = new DateTime(2012, 5, 1);

      CultureInfo culture = CultureInfo.CreateSpecificCulture("ja-JP");
      DateTimeFormatInfo dtfi = culture.DateTimeFormat;
      dtfi.Calendar = new JapaneseCalendar();
      Thread.CurrentThread.CurrentCulture = culture;

      sw.WriteLine("\n{0,-43} {1}", "Full Date and Time Pattern:", dtfi.FullDateTimePattern);
      sw.WriteLine(dt.ToString("F"));
      sw.WriteLine();

      sw.WriteLine("\n{0,-43} {1}", "Long Date Pattern:", dtfi.LongDatePattern);
      sw.WriteLine(dt.ToString("D"));

      sw.WriteLine("\n{0,-43} {1}", "Short Date Pattern:", dtfi.ShortDatePattern);
      sw.WriteLine(dt.ToString("d"));
      sw.Close();
    }
}
// The example writes the following output to a file:
//    Full Date and Time Pattern:                 gg y'年'M'月'd'日' H:mm:ss
//    平成 24年5月1日 0:00:00
//
//    Long Date Pattern:                          gg y'年'M'月'd'日'
//    平成 24年5月1日
//
//    Short Date Pattern:                         gg y/M/d
//    平成 24/5/1
Imports System.Globalization
Imports System.IO
Imports System.Threading

Module Example
    Public Sub Main()
        Dim sw As New StreamWriter(".\eras.txt")
        Dim dt As Date = #05/01/2012#

        Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        Dim dtfi As DateTimeFormatInfo = culture.DateTimeFormat
        dtfi.Calendar = New JapaneseCalendar()
        Thread.CurrentThread.CurrentCulture = culture

        sw.WriteLine("{0,-43} {1}", "Full Date and Time Pattern:", dtfi.FullDateTimePattern)
        sw.WriteLine(dt.ToString("F"))
        sw.WriteLine()

        sw.WriteLine("{0,-43} {1}", "Long Date Pattern:", dtfi.LongDatePattern)
        sw.WriteLine(dt.ToString("D"))
        sw.WriteLine()

        sw.WriteLine("{0,-43} {1}", "Short Date Pattern:", dtfi.ShortDatePattern)
        sw.WriteLine(dt.ToString("d"))
        sw.WriteLine()
        sw.Close()
    End Sub
End Module
' The example writes the following output to a file:
'    Full Date and Time Pattern:                 gg y'年'M'月'd'日' H:mm:ss
'    平成 24年5月1日 0:00:00
'    
'    Long Date Pattern:                          gg y'年'M'月'd'日'
'    平成 24年5月1日
'    
'    Short Date Pattern:                         gg y/M/d
'    平成 24/5/1 

Ostrzeżenie

Klasa JapaneseCalendar jest jedyną klasą kalendarza na platformie .NET, która obsługuje daty w więcej niż jednej erze i może być bieżącym kalendarzem obiektu CultureInfo — w szczególności obiektu CultureInfo reprezentującego kulturę japońską (Japonia).

Dla wszystkich kalendarzy specyfikator formatu niestandardowego "g" zawiera erę w ciągu wynikowym. W poniższym przykładzie użyto niestandardowego ciągu formatu "MM-dd-yyyy g", aby uwzględnić epokę w ciągu wynikowym, gdy bieżący kalendarz jest kalendarzem gregoriańskim.

   DateTime dat = new DateTime(2012, 5, 1);
   Console.WriteLine($"{dat:MM-dd-yyyy g}");
// The example displays the following output:
//     05-01-2012 A.D.
Dim dat As Date = #05/01/2012#
Console.WriteLine("{0:MM-dd-yyyy g}", dat)
' The example displays the following output:
'     05-01-2012 A.D.      

W przypadkach, gdy reprezentacja ciągu daty jest wyrażona w kalendarzu, który nie jest bieżącym kalendarzem, klasa Calendar zawiera metodę Calendar.GetEra, która może być używana wraz z Calendar.GetYear, Calendar.GetMonthi Calendar.GetDayOfMonth metod, aby jednoznacznie wskazać datę, a także erę, do której należy. W poniższym przykładzie użyto klasy JapaneseLunisolarCalendar do udostępnienia ilustracji. Należy jednak pamiętać, że aby dołączyć znaczącą nazwę lub skrót zamiast liczby całkowitej w ciągu wynikowym, konieczne jest utworzenie instancji obiektu DateTimeFormatInfo oraz ustawienie JapaneseCalendar jako jego bieżącego kalendarza. (Kalendarz JapaneseLunisolarCalendar nie może być bieżącym kalendarzem żadnej kultury, ale w tym przypadku dwa kalendarze mają te same epoki).

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2011, 8, 28);
      Calendar cal = new JapaneseLunisolarCalendar();

      Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                        cal.GetEra(date1),
                        cal.GetYear(date1),
                        cal.GetMonth(date1),
                        cal.GetDayOfMonth(date1));

      // Display eras
      CultureInfo culture = CultureInfo.CreateSpecificCulture("ja-JP");
      DateTimeFormatInfo dtfi = culture.DateTimeFormat;
      dtfi.Calendar = new JapaneseCalendar();

      Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                        dtfi.GetAbbreviatedEraName(cal.GetEra(date1)),
                        cal.GetYear(date1),
                        cal.GetMonth(date1),
                        cal.GetDayOfMonth(date1));
   }
}
// The example displays the following output:
//       4 0023/07/29
//       平 0023/07/29
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim date1 As Date = #8/28/2011#
        Dim cal As New JapaneseLunisolarCalendar()
        Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                          cal.GetEra(date1),
                          cal.GetYear(date1),
                          cal.GetMonth(date1),
                          cal.GetDayOfMonth(date1))

        ' Display eras
        Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        Dim dtfi As DateTimeFormatInfo = culture.DateTimeFormat
        dtfi.Calendar = New JapaneseCalendar()

        Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                          dtfi.GetAbbreviatedEraName(cal.GetEra(date1)),
                          cal.GetYear(date1),
                          cal.GetMonth(date1),
                          cal.GetDayOfMonth(date1))
    End Sub
End Module
' The example displays the following output:
'       4 0023/07/29
'       平 0023/07/29

W japońskich kalendarzach pierwszy rok ery nosi nazwę Gannen (元年). Na przykład, zamiast Heisei 1, pierwszy rok ery Heisei można opisać jako Heisei Gannen. Platforma .NET stosuje tę konwencję do formatowania dat i godzin z użyciem standardowych lub niestandardowych wzorców daty i godziny, gdy są one używane z obiektem CultureInfo reprezentującym kulturę Japanese-Japan ("ja-JP") za pomocą klasy JapaneseCalendar:

Na przykład poniższy przykład przedstawia datę w pierwszym roku ery Heisei w JapaneseCalendar.

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
         var enUs = new CultureInfo("en-US");
        var japaneseCal = new JapaneseCalendar();
        var jaJp = new CultureInfo("ja-JP");
        jaJp.DateTimeFormat.Calendar = japaneseCal;
        string heiseiEra = "平成";

        var date = japaneseCal.ToDateTime(1, 8, 18, 0, 0, 0, 0, GetEraIndex(heiseiEra));
        FormattableString fmt = $"{date:D}";
        Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)} (Gregorian: {fmt.ToString(enUs)})");

        int GetEraIndex(string eraName)
        {
           foreach (var ctr in japaneseCal.Eras)
              if (jaJp.DateTimeFormat.GetEraName(ctr) == eraName)
                 return ctr;

           return 0;
        }
    }
}
// The example displays the following output:
//    Japanese calendar date: 平成元年8月18日 (Gregorian: Friday, August 18, 1989)
Imports System.Globalization

Module Program
    Dim jaJp As CultureInfo
    Dim japaneseCal As Calendar

    Sub Main()
        Dim enUs = New CultureInfo("en-US")
        japaneseCal = New JapaneseCalendar()
        jaJp = New CultureInfo("ja-JP")
        jaJp.DateTimeFormat.Calendar = japaneseCal
        Dim heiseiEra = "平成"

        Dim dat = japaneseCal.ToDateTime(1, 8, 18, 0, 0, 0, 0, GetEraIndex(heiseiEra))
        Dim fmt As FormattableString = $"{dat:D}"
        Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)} (Gregorian: {fmt.ToString(enUs)})")
    End Sub

    Private Function GetEraIndex(eraName As String) As Integer
        For Each ctr In japaneseCal.Eras
            If jaJp.DateTimeFormat.GetEraName(ctr) = eraName Then
                Return ctr
            End If
        Next
        Return 0
    End Function
End Module
' The example displays the following output:
'    Japanese calendar date: 平成元年8月18日 (Gregorian: Friday, August 18, 1989)

Jeśli to zachowanie jest niepożądane w operacjach formatowania, można przywrócić poprzednie zachowanie, które zawsze reprezentuje pierwszy rok ery jako "1", a nie "Gannen", wykonując następujące czynności w zależności od wersji platformy .NET:

  • .NET Core: Dodaj następujące elementy do pliku konfiguracji .netcore.runtime.json:

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.FormatJapaneseFirstYearAsANumber": true
      }
    }
    
  • .NET Framework 4.6 lub nowsza wersja: Ustaw następujący przełącznik AppContext w pliku app.config:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.FormatJapaneseFirstYearAsANumber=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 lub starszej wersji: Ustaw następującą wartość rejestru:

    Wartość
    klucz HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    Wejście Przełącznik.System.Globalization.FormatowaćJapońskiPierwszyRokJakoLiczbę
    Typ REG_SZ
    Wartość prawda

Po wyłączeniu wsparcia gannen w operacjach formatowania, poprzedni przykład wyświetla następujący wynik:

Japanese calendar date: 平成1年8月18日 (Gregorian: Friday, August 18, 1989)

Platforma .NET została również zaktualizowana, aby operacje analizowania daty i godziny obsługiwały ciągi zawierające rok reprezentowany jako "1" lub Gannen. Chociaż nie należy tego robić, można przywrócić poprzednie zachowanie, aby rozpoznać tylko "1" jako pierwszy rok ery. Można to zrobić w następujący sposób, w zależności od wersji platformy .NET:

  • .NET Core: Dodaj następujące elementy do pliku konfiguracji .netcore.runtime.json:

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceLegacyJapaneseDateParsing": true
      }
    }
    
  • .NET Framework 4.6 lub nowsza wersja: Ustaw następujący przełącznik AppContext w pliku app.config:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.EnforceLegacyJapaneseDateParsing=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 lub starszej wersji: Ustaw następującą wartość rejestru:

    Wartość
    klucz HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    Wejście Przełącznik.System.Globalization.WymuszanieDziedzicznegoJapońskiegoParsowaniaDaty
    Typ REG_SZ
    Wartość prawda

Zobacz też