Arbeiten mit Kalendern

Obwohl ein Datums- und Uhrzeitwert eine universale zeitliche Angabe darstellt, ist die Zeichenfolgendarstellung eines solchen Werts kulturabhängig. Sie wird sowohl durch die Anzeigekonventionen für Datums- und Uhrzeitwerte einer bestimmten Kultur als auch durch den Kalender bestimmt, der in der jeweiligen Kultur verwendet wird. Dieses Thema behandelt die Unterstützung für Kalender in .NET und erläutert die Verwendung der Kalenderklassen beim Arbeiten mit Datumswerten.

Kalender in .NET

Alle Kalender in .NET sind von der System.Globalization.Calendar-Klasse abgeleitet, die die Basisimplementierung für Kalender bereitstellt. Eine der Klassen, die von der Calendar-Klasse erbt, ist die EastAsianLunisolarCalendar-Klasse. Dies ist die Basisklasse für alle Mond-Sonne-Kalender. .NET enthält die folgenden Kalenderimplementierungen:

Ein Kalender kann auf zwei Arten verwendet werden:

  • Als Kalender, der von einer bestimmten Kultur verwendet wird. Jedes CultureInfo-Objekt verfügt über einen aktuellen Kalender. Dies ist der Kalender, den das Objekt gegenwärtig verwendet. Die Zeichenfolgendarstellungen aller Datums- und Uhrzeitwerte entsprechen automatisch der aktuellen Kultur und dem aktuellen Kalender. In der Regel ist als aktueller Kalender der Standardkalender der Kultur angegeben. CultureInfo-Objekte können auch über optionale Kalender verfügen, welche die zusätzlichen Kalender angeben, die die Kultur verwenden kann.

  • Als eigenständiger Kalender, unabhängig von einer bestimmten Kultur. In diesem Fall werden Calendar-Methoden verwendet, um Datumsangaben in Werten auszudrücken, die dem betreffenden Kalender entsprechen.

Beachten Sie, dass die folgenden sechs Kalenderklassen nur als eigenständige Kalender verwendet werden können: ChineseLunisolarCalendar, JapaneseLunisolarCalendar, JulianCalendar, KoreanLunisolarCalendar, PersianCalendar und TaiwanLunisolarCalendar. Sie werden von keiner Kultur verwendet, weder als Standardkalender noch als optionaler Kalender.

Kalender und Kulturen

Jede Kultur verfügt über einen Standardkalender, der von der CultureInfo.Calendar-Eigenschaft definiert wird. Die CultureInfo.OptionalCalendars-Eigenschaft gibt ein Array von Calendar-Objekten zurück, das alle von einer bestimmten Kultur unterstützten Kalender angibt, einschließlich des Standardkalenders der Kultur.

Im folgenden Beispiel werden die CultureInfo.Calendar-Eigenschaft und die CultureInfo.OptionalCalendars-Eigenschaft veranschaulicht. Im Beispiel werden CultureInfo-Objekte für die Kulturen Thai (Thailand) und Japanisch (Japan) erstellt und die Standardkalender sowie die optionalen Kalender für diese Kulturen angezeigt. Beachten Sie, dass in beiden Fällen auch der Standardkalender in der CultureInfo.OptionalCalendars-Auflistung enthalten ist.

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 {0} culture:", ci.Name);

      // 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)

Der derzeit von einem bestimmten CultureInfo-Objekt verwendete Kalender wird von der DateTimeFormatInfo.Calendar-Eigenschaft der Kultur definiert. Das DateTimeFormatInfo-Objekt einer Kultur wird mit der CultureInfo.DateTimeFormat-Eigenschaft zurückgegeben. Beim Erstellen einer Kultur wird ihr Standardwert auf den Wert der CultureInfo.Calendar-Eigenschaft festgelegt. Sie können den Standardwert jedoch ändern und als aktuellen Kalender für eine Kultur jeden Kalender angeben, der in dem von der CultureInfo.OptionalCalendars-Eigenschaft zurückgegebenen Array enthalten ist. Wenn Sie versuchen, den aktuellen Kalender auf einen Kalender festzulegen, der nicht in der CultureInfo.OptionalCalendars-Eigenschaft enthalten ist, wird ArgumentException ausgelöst.

Im folgenden Beispiel wird der Kalender geändert, der von der Kultur Arabisch (Saudi-Arabien) verwendet wird. Zuerst wird ein DateTime-Wert instanziiert und unter Verwendung der aktuellen Kultur (in diesem Fall Englisch (USA)) sowie des aktuellen Kalenders der Kultur (gregorianischer Kalender) angezeigt. Anschließend wird die aktuelle Kultur in Arabisch (Saudi-Arabien) geändert und das Datum mit dem Standardkalender dieser Kultur, dem Umm al-Qura-Kalender angezeigt. Anschließend wird die CalendarExists-Methode aufgerufen, um zu bestimmen, ob der Hijri-Kalender von der Kultur Arabisch (Saudi-Arabien) unterstützt wird. Da der Kalender unterstützt wird, wird Hijri als aktueller Kalender festgelegt und das Datum erneut angezeigt. Beachten Sie, dass das Datum in allen Fällen mit dem aktuellen Kalender der aktuellen Kultur angezeigt wird.

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: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("Current Calendar: {0}",
                        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

Datumsangaben und Kalender

Mit Ausnahme der Konstruktoren, die einen Parameter des Typs Calendar beinhalten und die es gestatten, die Elemente eines Datums (d. h. Monat, Tag und Jahr) in den Werten eines bestimmten Kalenders anzuzeigen, basieren die Werte DateTime und DateTimeOffset immer auf dem gregorianischen Kalender. Dies bedeutet, dass die DateTime.Year-Eigenschaft immer das Jahr und die DateTime.Day-Eigenschaft immer den Monat im gregorianischen Kalender zurückgibt.

Wichtig

Es ist wichtig zu beachten, dass zwischen dem Datumswert und der entsprechenden Zeichenfolgendarstellung ein Unterschied besteht. Der erste Wert basiert auf dem gregorianischen Kalender, während der zweite Wert auf dem aktuellen Kalender einer bestimmten Kultur basiert.

Das folgende Beispiel veranschaulicht diesen Unterschied zwischen den DateTime-Eigenschaften und den entsprechenden Calendar-Methoden. Im Beispiel ist die aktuelle Kultur Arabisch (Ägypten), und der aktuelle Kalender ist Umm al-Qura. Ein DateTime-Wert wird auf den 15. Tag im 7. Monat des Jahres 2011 festgelegt. Es ist klar, dass diese Werte als gregorianisches Datum interpretiert werden, da die DateTime.ToString(String, IFormatProvider)-Methode die gleichen Werte zurückgibt, wenn die Konventionen der invarianten Kultur verwendet werden. Die Zeichenfolgendarstellung des Datums, die gemäß den Konventionen der aktuellen Kultur formatiert wird, ist 14/08/32. Dies ist das entsprechende Datum im Umm al-Qura-Kalender. Anschließend werden Member von DateTime und Calendar verwendet, um den Tag, den Monat und das Jahr des DateTime-Werts zurückzugeben. In allen Fällen entsprechen die von DateTime-Membern zurückgegebenen Werte den Werten im gregorianischen Kalender, während die von UmAlQuraCalendar-Membern zurückgegebenen Werte dem Umm al-Qura-Kalender entsprechen.

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: {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();
   }

   private static void DisplayCurrentInfo()
   {
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("Current Calendar: {0}",
                        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

Instanziieren von Datumsangaben basierend auf einem Kalender

Da DateTime-Werte und DateTimeOffset-Werte auf dem gregorianischen Kalender basieren, müssen Sie einen überladenen Konstruktor aufrufen, der einen Parameter vom Typ Calendar beinhaltet, wenn Sie einen Datumswert instanziieren möchten, der Tag, Monat und Jahr eines anderen Kalenders verwenden soll. Sie können auch eine der Überladungen der Calendar.ToDateTime-Methode eines bestimmten Kalenders aufrufen, um ein DateTime-Objekt auf Grundlage der Werte eines bestimmten Kalender zu instanziieren.

Im folgenden Codebeispiel wird ein DateTime-Wert instanziiert, indem ein HebrewCalendar-Objekt an einen DateTime Konstruktor übergeben wird. Anschließend wird ein zweiter DateTime-Wert durch Aufrufen der HebrewCalendar.ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32)-Methode instanziiert. Da die beiden Werte mit identischen Werten aus dem hebräischen Kalender erstellt wurden, zeigt ein Aufruf der DateTime.Equals-Methode, dass beide DateTime-Werte gleich sind.

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

Darstellen von Datumsangaben im aktuellen Kalender

Formatierungsmethoden für Datum und Uhrzeit verwenden immer den aktuellen Kalender, wenn Datumsangaben in Zeichenfolgen konvertiert werden sollen. Das heißt, dass die Zeichenfolgendarstellungen für Jahr, Monat und Tag des Monats denen des aktuellen Kalenders entsprechen und nicht notwendigerweise dem gregorianischen Kalender folgen.

Im folgenden Beispiel wird gezeigt, welchen Einfluss der aktuelle Kalender auf die Zeichenfolgendarstellung eines Datums hat. Im Beispiel wird die aktuelle Kultur auf Chinesisch (traditionell, Taiwan) festgelegt und ein Datumswert instanziiert. Anschließend werden der aktuelle Kalender und das Datum angezeigt, der aktuelle Kalender wird in TaiwanCalendar geändert, und Kalender und Datum werden erneut angezeigt. Der erste angezeigte Datumswert verwendet die Darstellung des gregorianischen Kalenders. Der zweite Datumswert wird im Format des taiwanesischen Kalenders dargestellt.

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: {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"));
   }
}
// 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

Darstellen von Datumsangaben in einem nicht aktuellen Kalender

Um ein Datum unter Verwendung eines anderen als des aktuellen Kalenders einer bestimmten Kultur darzustellen, müssen Sie Methoden des gewünschten Calendar-Objekts aufrufen. Zum Beispiel konvertieren die Methoden Calendar.GetYear, Calendar.GetMonth und Calendar.GetDayOfMonth das Jahr, den Monat und den Tag in die Darstellung eines bestimmten Kalenders.

Warnung

Da einige Kalender nicht als optionale Kalender für eine Kultur definiert sind, erfordert die Darstellung von Datumsangaben mit diesen Kalendern stets einen Aufruf der Methoden des entsprechenden Kalenders. Dies gilt für alle Kalender, die von den Klassen EastAsianLunisolarCalendar, JulianCalendar und PersianCalendar abgeleitet sind.

Im folgenden Beispiel wird ein JulianCalendar-Objekt verwendet, um ein Datum (9. Januar 1905) im julianischen Kalender zu instanziieren. Wenn dieses Datum mit dem gregorianischen Standardkalender dargestellt wird, wird es als 22. Januar 1905 angezeigt. Aufrufe einzelner JulianCalendar-Methoden ermöglichen eine Darstellung des Datums mit dem julianischen Kalender.

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

Kalender und Datumsbereiche

Das früheste Datum, das von einem Kalender unterstützt wird, wird durch die Calendar.MinSupportedDateTime-Eigenschaft dieses Kalenders angegeben. Für die GregorianCalendar-Klasse ist dieses Datum der 1. Januar 0001 n. Chr. Die meisten anderen Kalender in .NET unterstützen ein späteres Datum. Der Versuch, mit einem Datums- und Zeitwert zu arbeiten, der vor dem frühesten unterstützten Datum eines Kalenders liegt, löst eine ArgumentOutOfRangeException Ausnahme aus.

Es gibt jedoch eine wichtige Ausnahme. Der (nicht initialisierte) Standardwert eines DateTime-Objekts und eines DateTimeOffset-Objekts ist gleich dem GregorianCalendar.MinSupportedDateTime-Wert. Wenn Sie versuchen, das Datum in einem Kalender zu formatieren, der nicht den 1. Januar 0001 unserer Zeitrechnung unterstützt, und Sie keinen Formatbezeichner angeben, verwendet die Formatierungsmethode den Formatbezeichner "s" (sortierbares Datum-/Zeitmuster) anstelle des Formatbezeichners "G" (allgemeines Datums-/Zeitmuster). In der Folge löst der Formatierungsvorgang keine ArgumentOutOfRangeException-Ausnahme aus. Stattdessen wird das nicht unterstützte Datum zurückgegeben. Dies wird im folgenden Beispiel veranschaulicht. Der Wert von DateTime.MinValue wird anzeigt, wenn die aktuelle Kultur auf Japanisch (Japan) mit dem japanischen Kalender und in Arabisch (Ägypten) mit dem Um Al Qura-Kalender festgelegt wird. Außerdem wird die aktuelle Kultur auf Englisch (USA) festgelegt die DateTime.ToString(IFormatProvider)-Methode mit jedem dieser CultureInfo-Objekte aufgerufen. In jedem Fall wird das Datum mithilfe des sortierbaren Datums-/Zeitmusters angezeigt.

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

Arbeiten mit Zeiträumen

Kalender unterteilen Datumsangaben in der Regel in Zeiträume. Die Calendar-Klassen in .NET unterstützen jedoch nicht alle Zeiträume, die durch einen Kalender definiert werden, und die meisten Calendar-Klassen unterstützen nur einen einzigen Zeitraum. Nur die Klassen JapaneseCalendar und JapaneseLunisolarCalendar unterstützen mehrere Zeiträume.

Wichtig

Am 1. Mai 2019 beginnt ein neuer Zeitraum in JapaneseCalendar und JapaneseLunisolarCalendar: der Reiwa-Zeitraum. Diese Änderung betrifft alle Anwendungen, die diese Kalender verwenden. Weitere Informationen finden Sie in den folgenden Artikeln:

Ein Zeitraum bezeichnet in den meisten Kalendern eine extrem lange Zeitspanne. Im gregorianischen Kalender umfasst der aktuelle Zeitraum beispielsweise mehr als zwei Jahrtausende. Für JapaneseCalendar und JapaneseLunisolarCalendar, die beiden Kalender, die mehrere Zeiträume unterstützen, ist dies nicht der Fall. Ein Zeitraum entspricht der Zeitspanne der Herrschaft eines Kaisers. Unterstützung mehrerer Zeiträume, insbesondere wenn die Obergrenze des aktuellen Zeitraums unbekannt ist, stellt besondere Herausforderungen dar.

Zeiträume und Namen von Zeiträumen

In .NET werden Integerwerte, die die Zeiträume darstellen, die von einer bestimmten Kalenderimplementierung unterstützt werden, in umgekehrter Reihenfolge im Calendar.Eras-Array gespeichert. Der aktuelle Zeitraum (der Zeitraum mit dem neuesten Zeitbereich) besitzt den Index null, und bei Calendar-Klassen, die mehrere Zeiträume unterstützen, entspricht jeder nachfolgende Index dem jeweils vorherigen Zeitraum. Die statische Calendar.CurrentEra-Eigenschaft definiert den Index des aktuellen Zeitraums im Calendar.Eras-Array. Dies ist eine Konstante, die stets den Wert 0 (null) hat. Einzelne Calendar-Klassen beinhalten darüber hinaus auch statische Felder, die den Wert des aktuellen Zeitraums zurückgeben. Sie sind in der folgenden Tabelle aufgeführt.

Kalenderklasse Feld für den aktuellen Zeitraum
ChineseLunisolarCalendar ChineseEra
GregorianCalendar ADEra
HebrewCalendar HebrewEra
HijriCalendar HijriEra
JapaneseLunisolarCalendar JapaneseEra
JulianCalendar JulianEra
KoreanCalendar KoreanEra
KoreanLunisolarCalendar GregorianEra
PersianCalendar PersianEra
ThaiBuddhistCalendar ThaiBuddhistEra
UmAlQuraCalendar UmAlQuraEra

Der Name, der dem Zeitraum mit einer bestimmten Nummer entspricht, kann durch Übergeben der Nummer an die DateTimeFormatInfo.GetEraName-Methode oder an die DateTimeFormatInfo.GetAbbreviatedEraName-Methode abgerufen werden. Im folgenden Beispiel werden diese Methoden aufgerufen, um Informationen über die Unterstützung von Zeiträumen in der GregorianCalendar-Klasse abzurufen. Es wird das gregorianische Kalenderdatum angezeigt, das dem 1. Januar des zweiten Jahres des aktuellen Zeitraums entspricht, sowie das gregorianische Kalenderdatum, das dem 1. Januar des zweiten Jahres jedes unterstützten japanischen Kalenderzeitraums entspricht.

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

Darüber hinaus enthält die benutzerdefinierte Formatzeichenfolge "g" für Datum und Uhrzeit den Namen des Zeitraums eines Kalenders in der Zeichenfolgendarstellung eines Datums- und Uhrzeitwerts. Weitere Informationen finden Sie unter Benutzerdefinierte Datums- und Uhrzeit-Formatzeichenfolgen.

Instanziieren einer Datumsangabe mit einem Zeitraum

Bei den beiden Calendar-Klassen, die mehrere Zeiträume unterstützen, kann ein Datum mit einem bestimmten Jahr, Monat und Tag des Monats mehrdeutig sein. Beispielsweise verwenden alle von JapaneseCalendar unterstützten Zeiträume Jahre, deren Zahl 1 ist. Wenn kein Zeitraum angegeben ist, wird daher bei Datums-, Uhrzeit- und Klassenmethoden immer davon ausgegangen, dass die Werte zum aktuellen Zeitraum gehören. Dies gilt für die DateTime- und DateTimeOffset-Konstruktoren, die Parameter des Typs Calendar enthalten, sowie die JapaneseCalendar.ToDateTime- und JapaneseLunisolarCalendar.ToDateTime-Methoden. Im folgenden Beispiel wird ein Datum instanziiert, das den 1. Januar des zweiten Jahres eines nicht angegebenen Zeitraums darstellt. Wenn Sie das Beispiel ausführen, wenn der Reiwa-Zeitraum der aktuelle Zeitraum ist, wird das Datum als das zweite Jahr des Reiwa-Zeitraums interpretiert. Der Zeitraum (令和) geht dem Jahr in der von der DateTime.ToString(String, IFormatProvider)-Methode zurückgegebenen Zeichenfolge voraus und entspricht dem 1. Januar 2020 im gregorianischen Kalender. (Der Reiwa-Zeitraum beginnt im Jahr 2019 des gregorianischen Kalenders.)

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

Wenn sich der Zeitraum jedoch ändert, wird die Absicht dieses Codes mehrdeutig. Soll das Datum das zweite Jahr des aktuellen Zeitraums oder das zweite Jahr des Heisei-Zeitraums darstellen? Es gibt zwei Möglichkeiten, diese Zweideutigkeit zu vermeiden:

  • Instanziieren Sie den Datums- und Uhrzeitwert mithilfe der Standardklasse GregorianCalendar. Anschließend können Sie den japanischen Kalender oder den japanischen Lunisolarkalender für die Zeichenfolgendarstellung von Datumsangaben verwenden, wie das folgende Beispiel zeigt.

    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
    
    
    
  • Rufen Sie eine Datums- und Uhrzeitmethode auf, die explizit einen Zeitraum angibt. Dazu gehören folgende Methoden:

    Im folgenden Beispiel werden drei dieser Methoden verwendet, um ein Datum und eine Uhrzeit im Meiji-Zeitraum zu instanziieren, der am 8. September 1868 begann und am 29. Juli 1912 endete.

    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)
    

Tipp

Wenn Sie mit Kalendern arbeiten, die mehrere Zeiträume unterstützen, verwenden Sie immer das gregorianische Datum, um ein Datum zu instanziieren, oder geben Sie den Zeitraum an, wenn Sie ein Datum und eine Uhrzeit basierend auf diesem Kalender instanziieren.

Wenn Sie einen Zeitraum für die ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32)-Methode angeben, geben Sie den Index des Zeitraums in der Eras-Eigenschaft des Kalenders an. Für Kalender, deren Zeiträume sich ändern können, sind diese Indizes jedoch keine konstanten Werte. Der aktuelle Zeitraum liegt bei Index 0, der älteste Zeitraum bei Index Eras.Length - 1. Wenn einem Kalender ein neuer Zeitraum hinzugefügt wird, erhöhen sich die Indizes der vorherigen Zeiträume um eins. Sie können den entsprechenden Zeitraumindex wie folgt angeben:

  • Verwenden Sie für Datumsangaben im aktuellen Zeitraum immer die CurrentEra-Eigenschaft des Kalenders.

  • Verwenden Sie für Datumsangaben in einem angegebenen Zeitraum die DateTimeFormatInfo.GetEraName-Methode, um den Index abzurufen, der einem angegebenen Zeitraumnamen entspricht. Dafür ist es erforderlich, dass JapaneseCalendar der aktuelle Kalender des CultureInfo-Objekts ist, das die Kultur „ja-JP“ darstellt. (Diese Technik funktioniert auch für JapaneseLunisolarCalendar, da dieser die gleichen Zeiträume wie JapaneseCalendar unterstützt.) Im vorherigen Beispiel wird dieser Ansatz veranschaulicht.

Kalender, Zeiträume und Datumsbereiche: Gelockerte Bereichsüberprüfungen

Ähnlich wie einzelne Kalender Datumsbereiche unterstützt haben, verfügen auch die Zeiträume in den JapaneseCalendar- und JapaneseLunisolarCalendar-Klassen über unterstützte Bereiche. Zuvor hat .NET strenge Überprüfungen des Zeitraumbereichs verwendet, um sicherzustellen, dass sich ein zeitraumspezifisches Datum innerhalb des Bereichs dieses Zeitraums befand. Das heißt, wenn ein Datum außerhalb des Bereichs des angegebenen Zeitraums liegt, löst die Methode eine ArgumentOutOfRangeException aus. Derzeit verwendet .NET standardmäßig gelockerte Bereichsprüfung. Mit Updates für alle Versionen von .NET wurde gelockerte Überprüfung des Zeitbereichs eingeführt. Beim Versuch, ein zeitraumspezifisches Datum zu instanziieren, das außerhalb des Bereichs des angegebenen Zeitraums liegt, erfolgt ein Überlauf in den folgenden Zeitraum, und es wird keine Ausnahme ausgelöst.

Im folgenden Beispiel wird versucht, ein Datum im 65. Jahr des Showa-Zeitraums zu instanziieren, der am 25. Dezember 1926 begann und am 7. Januar 1989 endete. Dieses Datum entspricht dem 9. Januar 1990, das außerhalb des Bereichs des Showa-Zeitraums in JapaneseCalendar liegt. Wie die Ausgabe des Beispiels veranschaulicht, ist das im Beispiel angezeigte Datum der 9. Januar 1990, im zweiten Jahr des Heisei-Zeitraums.

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

Wenn gelockerte Überprüfungen des Bereichs nicht erwünscht sind, können Sie abhängig von der Version von .NET, mit der Ihre Anwendung ausgeführt wird, strenge Bereichsüberprüfungen auf verschiedene Arten vorsehen:

  • .NET Core: Fügen Sie der Konfigurationsdatei .netcore.runtime.json Folgendes hinzu:

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceJapaneseEraYearRanges": true
      }
    }
    
  • .NET Framework 4.6 oder höher: Legen Sie den folgenden AppContext-Schalter in der Datei app.config fest:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.EnforceJapaneseEraYearRanges=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 oder früher: Legen Sie den folgenden Registrierungswert fest:

    Wert
    Schlüssel HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    Eingabe Switch.System.Globalization.EnforceJapaneseEraYearRanges
    Typ REG_SZ
    Wert true

Wenn strenge Bereichsprüfungen aktiviert sind, löst das vorherige Beispiel eine ArgumentOutOfRangeException aus und zeigt die folgende Ausgabe an:

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()

Darstellen von Daten in Kalendern mit mehreren Zeiträumen

Wenn ein Calendar-Objekt Zeiträume unterstützt und es sich um den aktuellen Kalender eines CultureInfo-Objekts handelt, beinhalten die Zeichenfolgendarstellungen für die Muster vollständiges Datum und Uhrzeit, langes Datum und kurzes Datum auch den Zeitraum des Datums- und Uhrzeitwerts. Das folgende Beispiel zeigt diese Datumsmuster, wenn die aktuelle Kultur auf Japan (japanisch) festgelegt und als aktueller Kalender der japanische Kalender angegeben ist.

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 

Warnung

Die JapaneseCalendar-Klasse ist die einzige Kalenderklasse in .NET, die Datumsangaben in mehreren Zeiträumen unterstützt und der aktuelle Kalender eines CultureInfo-Objekts sein kann – genauer gesagt, eines CultureInfo-Objekts, das die Kultur Japanisch (Japan) darstellt.

Bei allen Kalendern enthält der benutzerdefinierte Formatbezeichner "g" auch den Zeitraum in der Ergebniszeichenfolge. Das folgende Beispiel verwendet die benutzerdefinierte Formatzeichenfolge "MM-DD-yyyy g", um den Zeitraum in der Ergebniszeichenfolge anzuzeigen, wenn als aktueller Kalender der gregorianische Kalender festgelegt ist.

   DateTime dat = new DateTime(2012, 5, 1);
   Console.WriteLine("{0:MM-dd-yyyy g}", dat);
// 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.      

In Fällen, in denen die Zeichenfolgendarstellung eines Datums in einem Kalender ausgedrückt wird, der nicht der aktuelle Kalender ist, beinhaltet die Calendar-Klasse eine Calendar.GetEra-Methode, die zusammen mit den Methoden Calendar.GetYear, Calendar.GetMonth und Calendar.GetDayOfMonth verwendet werden kann, um ein Datum eindeutig zusammen mit dem Zeitraum anzugeben, zu dem es gehört. Im folgenden Beispiel wird dies anhand der JapaneseLunisolarCalendar-Klasse veranschaulicht. Beachten Sie jedoch, dass Sie ein DateTimeFormatInfo-Objekt instanziieren und JapaneseCalendar als dessen aktuellen Kalender festlegen müssen, wenn Sie in der Ergebniszeichenfolge anstelle einer Zahl einen aussagekräftigen Namen oder eine Abkürzung für den Zeitraum anzeigen möchten. (Der JapaneseLunisolarCalendar-Kalender kann nicht als aktueller Kalender einer Kultur festgelegt werden, in diesem Fall teilen sich aber zwei Kalender dieselben Zeiträume.

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

In den japanischen Kalendern wird das erste Jahr eines Zeitraums als „Gannen“ (元年) bezeichnet. Anstelle von Heisei 1 kann beispielsweise das erste Jahr des Heisei-Zeitraums als „Heisei Gannen“ bezeichnet werden. .NET übernimmt diese Konvention in Formatierungsvorgängen für Datums- und Uhrzeitangaben, die mit den folgenden Standard- oder benutzerdefinierten Datums- und Uhrzeit-Formatzeichenfolgen formatiert sind, wenn sie mit einem CultureInfo-Objekt verwendet werden, das die Kultur Japanisch-Japan („ja-JP“) mit der JapaneseCalendar-Klasse darstellt:

Im folgenden Beispiel wird beispielsweise ein Datum im ersten Jahr des Heisei-Zeitraums in JapaneseCalendar angezeigt.

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)

Wenn dieses Verhalten bei Formatierungsvorgängen nicht erwünscht ist, können Sie das vorherige Verhalten wiederherstellen, das das erste Jahr eines Zeitraums immer als „1“ und nicht als "Gannen" darstellt, indem Sie je nach .NET-Version wie folgt vorgehen:

  • .NET Core: Fügen Sie der Konfigurationsdatei .netcore.runtime.json Folgendes hinzu:

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.FormatJapaneseFirstYearAsANumber": true
      }
    }
    
  • .NET Framework 4.6 oder höher: Legen Sie den folgenden AppContext-Schalter in der Datei app.config fest:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.FormatJapaneseFirstYearAsANumber=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 oder früher: Legen Sie den folgenden Registrierungswert fest:

    Wert
    Schlüssel HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    Eingabe Switch.System.Globalization.FormatJapaneseFirstYearAsANumber
    Typ REG_SZ
    Wert true

Wenn Gannen-Unterstützung für Formatierungsvorgänge deaktiviert ist, zeigt das vorherige Beispiel die folgende Ausgabe an:

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

.NET wurde ebenfalls aktualisiert, sodass Datums- und Uhrzeitanalysevorgänge Zeichenfolgen unterstützen, die das Jahr enthalten, das als „1“ oder „Gannen“ dargestellt wird. Obwohl dies nicht erforderlich sein sollte, können Sie das vorherige Verhalten wiederherstellen, um nur „1“ als erstes Jahr eines Zeitraums zu erkennen. Abhängig von der .NET-Version können Sie dies wie folgt erreichen:

  • .NET Core: Fügen Sie der Konfigurationsdatei .netcore.runtime.json Folgendes hinzu:

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceLegacyJapaneseDateParsing": true
      }
    }
    
  • .NET Framework 4.6 oder höher: Legen Sie den folgenden AppContext-Schalter in der Datei app.config fest:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.EnforceLegacyJapaneseDateParsing=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 oder früher: Legen Sie den folgenden Registrierungswert fest:

    Wert
    Schlüssel HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    Eingabe Switch.System.Globalization.EnforceLegacyJapaneseDateParsing
    Typ REG_SZ
    Wert true

Weitere Informationen