Arbeta med kalendrar

Även om ett datum- och tidsvärde representerar ett ögonblick i tiden är dess strängrepresentation kulturkänslig och beror både på de konventioner som används för att visa datum- och tidsvärden av en specifik kultur och på kalendern som används av den kulturen. Det här avsnittet utforskar stödet för kalendrar i .NET och diskuterar användningen av kalenderklasserna när du arbetar med datumvärden.

Kalendrar i .NET

Alla kalendrar i .NET härleds från System.Globalization.Calendar klassen, som tillhandahåller baskalenderimplementeringen. En av klasserna som ärver från Calendar klassen är EastAsianLunisolarCalendar klassen, som är basklassen för alla lunisolarkalendrar. .NET innehåller följande kalenderimplementeringar:

En kalender kan användas på något av två sätt:

  • Som den kalender som används av en specifik kultur. Varje CultureInfo objekt har en aktuell kalender, som är den kalender som objektet för närvarande använder. Strängrepresentationerna av alla datum- och tidsvärden återspeglar automatiskt den aktuella kulturen och dess aktuella kalender. Normalt är den aktuella kalendern kulturens standardkalender. CultureInfo objekt har också valfria kalendrar, som innehåller ytterligare kalendrar som kulturen kan använda.

  • Som en fristående kalender oberoende av en specifik kultur. I det här fallet Calendar används metoder för att uttrycka datum som värden som återspeglar kalendern.

Observera att sex kalenderklasser – ChineseLunisolarCalendar, JapaneseLunisolarCalendar, JulianCalendar, KoreanLunisolarCalendar, PersianCalendaroch TaiwanLunisolarCalendar – endast kan användas som fristående kalendrar. De används inte av någon kultur som antingen standardkalender eller som en valfri kalender.

Kalendrar och kulturer

Varje kultur har en standardkalender som definieras av egenskapen CultureInfo.Calendar . Egenskapen CultureInfo.OptionalCalendars returnerar en matris med Calendar objekt som anger alla kalendrar som stöds av en viss kultur, inklusive den kulturens standardkalender.

I följande exempel visas CultureInfo.Calendar egenskaperna och CultureInfo.OptionalCalendars . Den skapar CultureInfo objekt för den thailändska (Thailand) och japanska (Japan) kulturer och visar deras standard och valfria kalendrar. Observera att i båda fallen ingår även kulturens standardkalender i CultureInfo.OptionalCalendars samlingen.

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)

Kalendern som för närvarande används av ett visst CultureInfo objekt definieras av kulturens DateTimeFormatInfo.Calendar egenskap. En kulturs objekt returneras DateTimeFormatInfo av egenskapen CultureInfo.DateTimeFormat . När en kultur skapas är dess standardvärde detsamma som värdet för CultureInfo.Calendar egenskapen. Du kan dock ändra kulturens aktuella kalender till valfri kalender som finns i matrisen som returneras av CultureInfo.OptionalCalendars egenskapen. Om du försöker ange den aktuella kalendern till en kalender som inte ingår i egenskapsvärdet CultureInfo.OptionalCalendars genereras en ArgumentException .

I följande exempel ändras kalendern som används av den arabiska kulturen (Saudiarabien). Det instansierar först ett DateTime värde och visar det med hjälp av den aktuella kulturen - som i det här fallet är engelska (USA) - och den aktuella kulturens kalender (som i det här fallet är den gregorianska kalendern). Därefter ändrar den den aktuella kulturen till arabiska (Saudiarabien) och visar datumet med sin standardkalender för Um Al-Qura. Den anropar CalendarExists sedan metoden för att avgöra om Hijri-kalendern stöds av den arabiska kulturen (Saudiarabien). Eftersom kalendern stöds ändras den aktuella kalendern till Hijri och datumet visas igen. Observera att i varje enskilt fall visas datumet med den aktuella kulturens aktuella kalender.

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

Datum och kalendrar

Med undantag för konstruktorerna som innehåller en parameter av typen Calendar och tillåter att elementen i ett datum (det vill: månaden, dagen och året) återspeglar värden i en angiven kalender baseras både DateTime och DateTimeOffset värden alltid på den gregorianska kalendern. Det innebär till exempel att DateTime.Year egenskapen returnerar året i den gregorianska kalendern, och DateTime.Day egenskapen returnerar dagen i månaden i den gregorianska kalendern.

Viktigt!

Det är viktigt att komma ihåg att det finns en skillnad mellan ett datumvärde och dess strängrepresentation. Den förra är baserad på den gregorianska kalendern; den senare baseras på den aktuella kalendern för en specifik kultur.

I följande exempel visas den här skillnaden mellan DateTime egenskaper och deras motsvarande Calendar metoder. I exemplet är den aktuella kulturen arabiska (Egypten) och den aktuella kalendern är Um Al Qura. Ett DateTime värde anges till den femtonde dagen i den sjunde månaden 2011. Det är uppenbart att detta tolkas som ett gregorianskt datum, eftersom samma värden returneras av DateTime.ToString(String, IFormatProvider) metoden när den använder konventionerna i den invarianta kulturen. Strängrepresentationen av det datum som formateras med hjälp av konventionerna i den aktuella kulturen är 14/08/32, vilket är motsvarande datum i Um Al Qura-kalendern. Därefter används medlemmar i DateTime och Calendar för att returnera dagen, månaden och värdets DateTime år. I varje fall återspeglar värdena som returneras av DateTime medlemmar värden i den gregorianska kalendern, medan värden som returneras av UmAlQuraCalendar medlemmar återspeglar värden i Uum al-Qura-kalendern.

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

Instansiera datum baserat på en kalender

Eftersom DateTime värdena och DateTimeOffset baseras på den gregorianska kalendern måste du anropa en överbelastad konstruktor som innehåller en parameter av typen Calendar för att instansiera ett datumvärde om du vill använda värdena för dag, månad eller år från en annan kalender. Du kan också anropa en av överlagringarna för en viss kalenders Calendar.ToDateTime metod för att instansiera ett DateTime objekt baserat på värdena i en viss kalender.

I följande exempel instansierar ett DateTime värde genom att skicka ett HebrewCalendar objekt till en DateTime konstruktor och instansierar ett andra DateTime värde genom att anropa HebrewCalendar.ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) metoden. Eftersom de två värdena skapas med identiska värden från den hebreiska kalendern visar anropet DateTime.Equals till metoden att de två DateTime värdena är lika.

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

Representera datum i den aktuella kalendern

Formateringsmetoder för datum och tid använder alltid den aktuella kalendern när datum konverteras till strängar. Det innebär att strängrepresentationen av året, månaden och dagen i månaden återspeglar den aktuella kalendern och inte nödvändigtvis återspeglar den gregorianska kalendern.

I följande exempel visas hur den aktuella kalendern påverkar strängrepresentationen av ett datum. Den ändrar den aktuella kulturen till kinesiska (traditionell, Taiwan) och instansierar ett datumvärde. Den visar sedan den aktuella kalendern och datumet, ändrar den aktuella kalendern till TaiwanCalendaroch visar den aktuella kalendern och datumet igen. Första gången datumet visas visas det som ett datum i den gregorianska kalendern. Den andra gången den visas visas den som ett datum i Taiwan-kalendern.

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

Representera datum i en icke-aktuell kalender

Om du vill representera ett datum med en kalender som inte är den aktuella kalendern för en viss kultur måste du anropa metoderna för objektet Calendar . Metoderna , Calendar.GetMonthoch Calendar.GetDayOfMonth konverterar till exempel Calendar.GetYearår, månad och dag till värden som återspeglar en viss kalender.

Varning

Eftersom vissa kalendrar inte är valfria kalendrar i någon kultur, kräver det alltid att du anropar kalendermetoder för att representera datum i dessa kalendrar. Detta gäller för alla kalendrar som härleds från klasserna EastAsianLunisolarCalendar, JulianCalendaroch PersianCalendar .

I följande exempel används ett JulianCalendar objekt för att instansiera ett datum, 9 januari 1905, i den julianska kalendern. När det här datumet visas med standardkalendern (gregoriansk) representeras det som 22 januari 1905. Anrop till enskilda JulianCalendar metoder gör det möjligt att representera datumet i den julianske kalendern.

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

Kalendrar och datumintervall

Det tidigaste datum som stöds av en kalender anges av den kalenderns Calendar.MinSupportedDateTime egenskap. GregorianCalendar För klassen är det datumet den 1 januari 0001. De flesta andra kalendrar i .NET stöder ett senare datum. När du försöker arbeta med ett datum- och tidsvärde som föregår en kalenders tidigaste datum som stöds genereras ett ArgumentOutOfRangeException undantag.

Det finns dock ett viktigt undantag. Standardvärdet (onitialiserat) för ett DateTime objekt och ett DateTimeOffset objekt är lika GregorianCalendar.MinSupportedDateTime med värdet. Om du försöker formatera det här datumet i en kalender som inte stöder 1 januari 0001 C.E. och du inte anger någon formatspecificerare använder formateringsmetoden formatspecificeraren "s" (sorterbart datum/tid-mönster) i stället för formatspecificeraren "G" (allmänt datum/tid). Därför utlöser inte formateringsåtgärden något ArgumentOutOfRangeException undantag. I stället returneras datumet som inte stöds. Detta illustreras i följande exempel, som visar värdet för DateTime.MinValue när den aktuella kulturen är inställd på japanska (Japan) med den japanska kalendern och till arabiska (Egypten) med Um Al Qura-kalendern. Den ställer också in den aktuella kulturen på engelska (USA) och anropar DateTime.ToString(IFormatProvider) metoden med vart och ett av dessa CultureInfo objekt. I varje fall visas datumet med hjälp av det sorterbara datum-/tidsmönstret.

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

Arbeta med epoker

Kalendrar delar vanligtvis in datum i epoker. Klasserna Calendar i .NET stöder dock inte varje era som definieras av en kalender, och de flesta klasser Calendar stöder bara en enda era. Endast klasserna JapaneseCalendar och JapaneseLunisolarCalendar stöder flera epoker.

Viktigt!

Reiwa-eran, en ny era i och JapaneseLunisolarCalendar, börjar den JapaneseCalendar 1 maj 2019. Den här ändringen påverkar alla program som använder dessa kalendrar. Mer information finns i följande artiklar:

En era i de flesta kalendrar anger en extremt lång tidsperiod. I den gregorianska kalendern sträcker sig till exempel den aktuella eran över mer än två årtusenden. JapaneseCalendar För och JapaneseLunisolarCalendar, de två kalendrar som stöder flera epoker är detta inte fallet. En era motsvarar perioden av en kejsare regeringstid. Stöd för flera epoker, särskilt när den övre gränsen för den nuvarande eran är okänd, innebär särskilda utmaningar.

Raderings- och eranamn

I .NET lagras heltal som representerar de rader som stöds av en viss kalenderimplementering i omvänd ordning i matrisen Calendar.Eras . Den aktuella eran (som är eran med det senaste tidsintervallet) är på index noll, och för Calendar klasser som stöder flera epoker återspeglar varje efterföljande index föregående era. Den statiska Calendar.CurrentEra egenskapen definierar indexet för den aktuella eran i matrisen Calendar.Eras . Det är en konstant vars värde alltid är noll. Enskilda Calendar klasser innehåller även statiska fält som returnerar värdet för den aktuella eran. De visas i följande tabell.

Kalenderklass Aktuellt era-fält
ChineseLunisolarCalendar ChineseEra
GregorianCalendar ADEra
HebrewCalendar HebrewEra
HijriCalendar HijriEra
JapaneseLunisolarCalendar JapaneseEra
JulianCalendar JulianEra
KoreanCalendar KoreanEra
KoreanLunisolarCalendar GregorianEra
PersianCalendar PersianEra
ThaiBuddhistCalendar ThaiBuddhistEra
UmAlQuraCalendar UmAlQuraEra

Namnet som motsvarar ett visst era-nummer kan hämtas genom att era-talet skickas till DateTimeFormatInfo.GetEraName metoden eller DateTimeFormatInfo.GetAbbreviatedEraName . I följande exempel anropas dessa metoder för att hämta information om era-stöd i GregorianCalendar klassen. Det visar det gregorianska kalenderdatumet som motsvarar den 1 januari det andra året i den aktuella eran, samt det gregorianska kalenderdatumet som motsvarar den 1 januari det andra året för varje japansk kalendertid som stöds.

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

Dessutom innehåller den anpassade datum- och tidsformatsträngen "g" en kalenders eranamn i strängrepresentationen av ett datum och en tid. Mer information finns i Anpassade datum- och tidsformatsträngar.

Instansiera ett datum med en era

För de två Calendar klasser som stöder flera epoker kan ett datum som består av ett visst värde för år, månad och dag i månaden vara tvetydigt. Till exempel har alla epoker som stöds av JapaneseCalendar åren vars tal är 1. Normalt, om en era inte har angetts, förutsätter både datum- och tids- och kalendermetoder att värden tillhör den aktuella eran. Detta gäller för konstruktorerna DateTime och DateTimeOffset som innehåller parametrar av typen Calendar, samt metoderna JapaneseCalendar.ToDateTime och JapaneseLunisolarCalendar.ToDateTime . I följande exempel instansieras ett datum som representerar 1 januari det andra året av en ospecificerad era. Om du kör exemplet när Reiwa-eran är den aktuella eran tolkas datumet som det andra året i Reiwa-eran. Eran, 令和, föregår året i strängen DateTime.ToString(String, IFormatProvider) som returneras av metoden och motsvarar den 1 januari 2020 i den gregorianska kalendern. (Reiwa-eran börjar år 2019 i den gregorianska kalendern.)

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

Men om eran ändras blir avsikten med den här koden tvetydig. Är datumet avsett att representera det andra året i den nuvarande eran, eller är det avsett att representera det andra året av Heisei-eran? Det finns två sätt att undvika den här tvetydigheten:

  • Instansiera datum- och tidsvärdet med hjälp av standardklassen GregorianCalendar . Du kan sedan använda den japanska kalendern eller den japanska Lunisolar-kalendern för strängrepresentationen av datum, som i följande exempel visas.

    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
    
    
    
  • Anropa en datum- och tidsmetod som uttryckligen anger en era. Detta omfattar följande metoder:

    I följande exempel används tre av dessa metoder för att instansiera ett datum och en tid i Meiji-eran, som började den 8 september 1868 och avslutades den 29 juli 1912.

    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)
    

Dricks

När du arbetar med kalendrar som stöder flera epoker använder du alltid det gregorianska datumet för att instansiera ett datum eller anger den tid då du instansierar ett datum och en tid baserat på den kalendern.

När du anger en era för ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) metoden anger du indexet för eran i kalenderns Eras egenskap. För kalendrar vars epoker kan komma att ändras är dessa index dock inte konstanta värden. den aktuella eran är vid index 0 och den äldsta eran är vid index .Eras.Length - 1 När en ny era läggs till i en kalender ökar indexen för de tidigare epokerna med en. Du kan ange lämpligt era-index på följande sätt:

Kalendrar, epoker och datumintervall: Avslappnade intervallkontroller

Precis som enskilda kalendrar har stöd för datumintervall har rader i JapaneseCalendar klasserna och JapaneseLunisolarCalendar också intervall som stöds. Tidigare använde .NET strikta era-intervallkontroller för att säkerställa att ett tidsspecifikt datum låg inom intervallet för den eran. Om ett datum ligger utanför intervallet för den angivna eran genererar metoden alltså en ArgumentOutOfRangeException. För närvarande använder .NET avslappnad intervallkontroll som standard. Uppdateringar till alla versioner av .NET introducerade avslappnade eraintervallkontroller. Försöket att instansiera ett eraspecifikt datum som ligger utanför intervallet för den angivna eran "spiller" in i följande era och inget undantag utlöses.

I följande exempel försöker man instansiera ett datum under showa-erans 65:e år, som började den 25 december 1926 och avslutades den 7 januari 1989. Det här datumet motsvarar den 9 januari 1990, som ligger utanför intervallet för Showa-eran i JapaneseCalendar. Som utdata från exemplet visar är datumet som visas i exemplet den 9 januari 1990 under heisei-erans andra år.

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

Om kontroller av avslappnade intervall är oönskade kan du återställa strikta intervallkontroller på flera olika sätt, beroende på vilken version av .NET som programmet körs på:

  • .NET Core: Lägg till följande i konfigurationsfilen .netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceJapaneseEraYearRanges": true
      }
    }
    
  • .NET Framework 4.6 eller senare: Ange följande AppContext-växel i filen 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 eller tidigare: Ange följande registervärde:

    Värde
    Tangent HKEY_LOCAL_MACHINE\Software\Microsoft\. NETFramework\AppContext
    Format Switch.System.Globalization.EnforceJapaneseEraYearRanges
    Typ REG_SZ
    Värde true

Med strikta intervallkontroller aktiverade genererar föregående exempel en ArgumentOutOfRangeException och visar följande utdata:

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

Representera datum i kalendrar med flera epoker

Om ett Calendar objekt stöder radering och är den aktuella kalendern för ett CultureInfo objekt inkluderas eran i strängrepresentationen av ett datum- och tidsvärde för mönster för fullständigt datum och tid, långt datum och kort datum. I följande exempel visas dessa datummönster när den aktuella kulturen är Japan (japanska) och den aktuella kalendern är den japanska kalendern.

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 

Varning

Klassen JapaneseCalendar är den enda kalenderklassen i .NET som båda har stöd för datum i mer än en era och som kan vara den aktuella kalendern för ett CultureInfo objekt – specifikt för ett CultureInfo objekt som representerar den japanska kulturen (Japan).

För alla kalendrar innehåller den anpassade formatspecificeraren "g" eran i resultatsträngen. I följande exempel används den anpassade formatsträngen "MM-dd-yyyy g" för att inkludera eran i resultatsträngen när den aktuella kalendern är den gregorianska kalendern.

   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.      

I fall där strängrepresentationen av ett datum uttrycks i en kalender som inte är den aktuella kalendern innehåller Calendar klassen en Calendar.GetEra metod som kan användas tillsammans med Calendar.GetYearmetoderna , Calendar.GetMonthoch Calendar.GetDayOfMonth för att entydigt ange ett datum samt den era som den tillhör. I följande exempel används JapaneseLunisolarCalendar klassen för att tillhandahålla en bild. Observera dock att om du inkluderar ett meningsfullt namn eller en förkortning i stället för ett heltal för eran i resultatsträngen måste du instansiera ett DateTimeFormatInfo objekt och skapa JapaneseCalendar dess aktuella kalender. (Kalendern JapaneseLunisolarCalendar kan inte vara den aktuella kalendern för någon kultur, men i det här fallet delar de två kalendrarna samma epoker.)

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

I de japanska kalendrarna kallas det första året för en era Gannen (元年). I stället för Heisei 1 kan till exempel heisei-erans första år beskrivas som Heisei Gannen. .NET antar den här konventionen i formateringsåtgärder för datum och tider som är formaterade med följande standard- eller anpassade datum- och tidsformatsträngar när de används med ett CultureInfo objekt som representerar kulturen japan-Japan ("ja-JP") med JapaneseCalendar klassen:

I följande exempel visas till exempel ett datum under heisei-erans första år i 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)

Om det här beteendet inte är önskvärt i formateringsåtgärder kan du återställa det tidigare beteendet, som alltid representerar det första året av en era som "1" i stället för "Gannen", genom att göra följande, beroende på versionen av .NET:

  • .NET Core: Lägg till följande i konfigurationsfilen .netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.FormatJapaneseFirstYearAsANumber": true
      }
    }
    
  • .NET Framework 4.6 eller senare: Ange följande AppContext-växel i filen 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 eller tidigare: Ange följande registervärde:

    Värde
    Tangent HKEY_LOCAL_MACHINE\Software\Microsoft\. NETFramework\AppContext
    Format Switch.System.Globalization.FormatJapaneseFirstYearAsANumber
    Typ REG_SZ
    Värde true

Med gannen-stöd för formateringsåtgärder inaktiverat visas följande utdata i föregående exempel:

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

.NET har också uppdaterats så att datum- och tidsparsningsåtgärder stöder strängar som innehåller året som representeras som antingen "1" eller Gannen. Även om du inte behöver göra detta kan du återställa det tidigare beteendet för att bara identifiera "1" som det första året av en era. Du kan göra detta på följande sätt, beroende på vilken version av .NET:

  • .NET Core: Lägg till följande i konfigurationsfilen .netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceLegacyJapaneseDateParsing": true
      }
    }
    
  • .NET Framework 4.6 eller senare: Ange följande AppContext-växel i filen 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 eller tidigare: Ange följande registervärde:

    Värde
    Tangent HKEY_LOCAL_MACHINE\Software\Microsoft\. NETFramework\AppContext
    Format Switch.System.Globalization.EnforceLegacyJapaneseDateParsing
    Typ REG_SZ
    Värde true

Se även