Condividi tramite


Lavorare con i calendari

Anche se un valore di data e ora rappresenta un momento nel tempo, la sua rappresentazione in stringa è sensibile alla cultura e dipende sia dalle convenzioni utilizzate per visualizzare i valori di data e ora in una cultura specifica, sia dal calendario utilizzato da quella cultura. Questo argomento illustra il supporto per i calendari in .NET e illustra l'uso delle classi di calendario quando si usano i valori di data.

Calendari in .NET

Tutti i calendari in .NET derivano dalla System.Globalization.Calendar classe , che fornisce l'implementazione del calendario di base. Una delle classi che eredita dalla Calendar classe è la EastAsianLunisolarCalendar classe , ovvero la classe base per tutti i calendari lunisolari. .NET include le implementazioni del calendario seguenti:

Un calendario può essere usato in uno dei due modi seguenti:

  • Come calendario utilizzato da una cultura specifica. Ogni CultureInfo oggetto ha un calendario corrente, ovvero il calendario attualmente utilizzato dall'oggetto. Le rappresentazioni di stringa di tutti i valori di data e ora riflettono automaticamente la cultura corrente e il suo calendario corrente. In genere, il calendario attuale è il calendario predefinito della cultura. CultureInfo gli oggetti hanno anche calendari opzionali, che includono calendari aggiuntivi che la cultura può usare.

  • Come un calendario indipendente da una cultura specifica. In questo caso, Calendar i metodi vengono usati per esprimere le date come valori che riflettono il calendario.

Si noti che sei classi di calendario, ChineseLunisolarCalendar, JulianCalendarJapaneseLunisolarCalendar, KoreanLunisolarCalendar, PersianCalendare TaiwanLunisolarCalendar , possono essere usate solo come calendari autonomi. Non vengono usate da impostazioni cultura come calendario predefinito o come calendario facoltativo.

Calendari e culture

Ogni cultura ha un calendario predefinito, definito dalla CultureInfo.Calendar proprietà . La CultureInfo.OptionalCalendars proprietà restituisce una matrice di Calendar oggetti che specifica tutti i calendari supportati da impostazioni cultura specifiche, incluso il calendario predefinito delle impostazioni cultura.

Nell'esempio seguente vengono illustrate le CultureInfo.Calendar proprietà e CultureInfo.OptionalCalendars . CultureInfo Crea oggetti per le impostazioni cultura thai (Thailandia) e giapponese (Giappone) e visualizza i calendari predefiniti e facoltativi. Si noti che in entrambi i casi, il calendario predefinito della cultura è incluso anch'esso nella CultureInfo.OptionalCalendars raccolta.

using System;
using System.Globalization;

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

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

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

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

      if (defaultCalendar is GregorianCalendar)
         Console.WriteLine($" ({((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)

Il calendario attualmente in uso da un CultureInfo oggetto particolare è definito dalla proprietà della DateTimeFormatInfo.Calendar cultura. L'oggetto di DateTimeFormatInfo di una cultura viene restituito dalla proprietà CultureInfo.DateTimeFormat. Quando si crea una cultura, il valore predefinito è lo stesso del valore della proprietà CultureInfo.Calendar. Tuttavia, è possibile cambiare il calendario corrente della cultura in qualsiasi calendario contenuto nella matrice restituita dalla proprietà CultureInfo.OptionalCalendars. Se tenti di impostare il calendario corrente su uno non incluso nel valore della proprietà CultureInfo.OptionalCalendars, viene generata un'eccezione ArgumentException.

Nell'esempio seguente viene cambiato il calendario utilizzato dalle impostazioni della cultura araba (Arabia Saudita). Crea prima un'istanza di un valore di DateTime e la visualizza utilizzando la cultura corrente, che è l'inglese (Stati Uniti), e il calendario della cultura corrente, che è il calendario gregoriano. Successivamente, cambia la cultura corrente in arabo (Arabia Saudita) e visualizza la data utilizzando il calendario predefinito Um Al-Qura. Chiama quindi il metodo CalendarExists per determinare se il calendario Hijri è supportato dalla cultura araba (Arabia Saudita). Poiché il calendario è supportato, cambia il calendario corrente in Hijri e visualizza nuovamente la data. Si noti che in ogni caso, la data viene visualizzata utilizzando il calendario della cultura corrente.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Date e calendari

Ad eccezione dei costruttori che includono un parametro di tipo Calendar e consentono agli elementi di una data (ovvero il mese, il giorno e l'anno) di riflettere i valori in un calendario designato, entrambi DateTime i valori e DateTimeOffset sono sempre basati sul calendario gregoriano. Ciò significa, ad esempio, che la DateTime.Year proprietà restituisce l'anno nel calendario gregoriano e la DateTime.Day proprietà restituisce il giorno del mese nel calendario gregoriano.

Importante

È importante ricordare che esiste una differenza tra un valore di data e la relativa rappresentazione di stringa. Il primo è basato sul calendario gregoriano; il secondo è basato sul calendario attuale di una cultura specifica.

Nell'esempio seguente viene illustrata la differenza tra le proprietà DateTime e i metodi corrispondenti Calendar. Nell'esempio, la cultura attuale è arabo (Egitto) e il calendario attuale è Um Al Qura. Un DateTime valore viene impostato sul quindicesimo giorno del settimo mese del 2011. È chiaro che questo viene interpretato come una data gregoriana, perché questi stessi valori vengono restituiti dal metodo DateTime.ToString(String, IFormatProvider) quando usa le convenzioni della cultura invariante. La rappresentazione di stringa della data formattata usando le convenzioni delle impostazioni culturali correnti è 14/08/32, che corrisponde alla data nel calendario Um Al Qura. Successivamente, i membri di DateTime e Calendar vengono usati per restituire il giorno, il mese e l'anno del DateTime valore. In ogni caso, i valori restituiti dai DateTime membri riflettono i valori nel calendario gregoriano, mentre i valori restituiti dai UmAlQuraCalendar membri riflettono i valori nel calendario Uum al-Qura.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Creare un'istanza delle date in base a un calendario

Poiché DateTime e DateTimeOffset i valori sono basati sul calendario gregoriano, è necessario chiamare un costruttore sovraccarico che includa un parametro di tipo Calendar per istanziare un valore di data se si desidera utilizzare i valori di giorno, mese o anno da un calendario diverso. È anche possibile chiamare uno degli overload del metodo di un calendario specifico per creare un'istanza di DateTime basato sui valori di un determinato calendario.

L'esempio seguente crea un'istanza di un DateTime valore passando un HebrewCalendar oggetto a un DateTime costruttore e crea un'istanza di un secondo DateTime valore chiamando il HebrewCalendar.ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) metodo . Poiché i due valori vengono creati con valori identici dal calendario ebraico, la chiamata al DateTime.Equals metodo mostra che i due DateTime valori sono uguali.

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

Rappresentare le date nel calendario corrente

I metodi di formattazione di data e ora usano sempre il calendario corrente durante la conversione di date in stringhe. Ciò significa che la rappresentazione di stringa dell'anno, il mese e il giorno del mese riflettono il calendario corrente e non riflettono necessariamente il calendario gregoriano.

Nell'esempio seguente viene illustrato come il calendario corrente influisce sulla rappresentazione di stringa di una data. Modifica le impostazioni cultura correnti in cinese (tradizionale, Taiwan) e crea un'istanza di un valore di data. Visualizza quindi il calendario corrente e la data, modifica il calendario corrente in TaiwanCalendare visualizza nuovamente il calendario e la data correnti. La prima volta che viene visualizzata la data, viene rappresentata come data nel calendario gregoriano. La seconda volta che viene visualizzata, viene rappresentata come data nel calendario taiwanese.

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

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

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

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

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

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

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

Rappresentare le date in un calendario non corrente

Per rappresentare una data utilizzando un calendario che non è il calendario corrente di impostazioni cultura specifiche, è necessario chiamare metodi di tale Calendar oggetto. Ad esempio, i Calendar.GetYearmetodi , Calendar.GetMonthe Calendar.GetDayOfMonth converteno l'anno, il mese e il giorno in valori che riflettono un determinato calendario.

Avvertimento

Poiché alcuni calendari non sono calendari facoltativi di una cultura, per rappresentare le date in questi calendari è sempre necessario chiamare i metodi dei calendari. Questo vale per tutti i calendari che derivano dalle EastAsianLunisolarCalendarclassi , JulianCalendare PersianCalendar .

Nell'esempio seguente, un oggetto JulianCalendar viene utilizzato per creare un'istanza di una data, il 9 gennaio 1905, nel calendario giuliano. Quando questa data viene visualizzata usando il calendario gregoriano predefinito, viene rappresentata come 22 gennaio 1905. Le chiamate ai singoli JulianCalendar metodi consentono di rappresentare la data nel calendario julian.

using System;
using System.Globalization;

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

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

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

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

Calendari e intervalli di date

La data meno recente supportata da un calendario è indicata dalla proprietà del Calendar.MinSupportedDateTime calendario. Per la GregorianCalendar classe, tale data è il 1° gennaio 0001 C.E. La maggior parte degli altri calendari in .NET supporta una data successiva. Il tentativo di utilizzare un valore di data e ora che precede la data meno recente supportata di un calendario genera un'eccezione ArgumentOutOfRangeException .

Tuttavia, esiste un'eccezione importante. Il valore predefinito (non inizializzato) di un DateTime oggetto e un DateTimeOffset oggetto è uguale al GregorianCalendar.MinSupportedDateTime valore . Se si tenta di formattare questa data in un calendario che non supporta il 1° gennaio 0001 C.E. e non si specifica un identificatore di formato, il metodo di formattazione utilizza l'identificatore di formato "s" (criterio di data/ora ordinabile) anziché l'identificatore di formato "G" (modello di data/ora generale). Di conseguenza, l'operazione di formattazione non genera un'eccezione ArgumentOutOfRangeException . Restituisce invece la data non supportata. Questo è illustrato nell'esempio seguente, che visualizza il valore di DateTime.MinValue quando le impostazioni cultura correnti sono impostate su Giapponese (Giappone) con il calendario giapponese e su Arabo (Egitto) con il calendario Um Al Qura. Imposta anche la cultura corrente su Inglese (Stati Uniti) e chiama il DateTime.ToString(IFormatProvider) metodo con ciascuno di questi CultureInfo oggetti. In ogni caso, la data viene visualizzata usando il modello di data/ora ordinabile.

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 {GetCalendarName(jaJP)} calendar: {jaJP.DateTimeFormat.Calendar.MinSupportedDateTime:d}");
      // 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 {GetCalendarName(arEG)} calendar: {arEG.DateTimeFormat.Calendar.MinSupportedDateTime:d}");
      // 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

Usare le ere

I calendari in genere dividono le date in ere. Tuttavia, le Calendar classi in .NET non supportano ogni era definita da un calendario e la Calendar maggior parte delle classi supporta solo una singola era. Solo le JapaneseCalendar classi e JapaneseLunisolarCalendar supportano più ere.

Importante

L'era di Reiwa, una nuova era in JapaneseCalendar e JapaneseLunisolarCalendar, inizia il 1° maggio 2019. Questa modifica influisce su tutte le applicazioni che usano questi calendari. Per altre informazioni, vedere gli articoli seguenti:

Un'era nella maggior parte dei calendari indica un periodo di tempo estremamente lungo. Nel calendario gregoriano, ad esempio, l'era corrente si estende più di due millenni. JapaneseCalendar Per e JapaneseLunisolarCalendar, i due calendari che supportano più ere, questo non è il caso. Un'era corrisponde al periodo del regno di un imperatore. Il supporto per più ere, in particolare quando il limite superiore dell'era corrente è sconosciuto, pone sfide speciali.

Era e nomi di era

In .NET, i numeri interi che rappresentano le era supportate da una particolare implementazione del calendario vengono archiviati in ordine inverso nella Calendar.Eras matrice. L'era corrente (ovvero l'era con l'intervallo di tempo più recente) è in corrispondenza dell'indice zero e per Calendar le classi che supportano più ere, ogni indice successivo riflette l'era precedente. La proprietà statica Calendar.CurrentEra definisce l'indice dell'era corrente nella Calendar.Eras matrice; è una costante il cui valore è sempre zero. Le singole Calendar classi includono anche campi statici che restituiscono il valore dell'era corrente. Sono elencati nella tabella seguente.

Classe Calendar Campo era corrente
ChineseLunisolarCalendar ChineseEra
GregorianCalendar ADEra
HebrewCalendar HebrewEra
HijriCalendar HijriEra
JapaneseLunisolarCalendar JapaneseEra
JulianCalendar JulianEra
KoreanCalendar KoreanEra
KoreanLunisolarCalendar GregorianEra
PersianCalendar PersianEra
ThaiBuddhistCalendar ThaiBuddhistEra
UmAlQuraCalendar UmAlQuraEra

Il nome che corrisponde a un determinato numero dell'era può essere recuperato passando il numero dell'era al DateTimeFormatInfo.GetEraName o DateTimeFormatInfo.GetAbbreviatedEraName metodo. L'esempio seguente chiama questi metodi per recuperare informazioni sul supporto dell'era nella classe GregorianCalendar. Visualizza la data del calendario gregoriano che corrisponde al 1° gennaio del secondo anno dell'era corrente, nonché la data del calendario gregoriano che corrisponde al 1° gennaio del secondo anno di ogni era del calendario giapponese supportata.

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

Inoltre, la stringa di formato di data e ora personalizzata "g" include il nome dell'era di un calendario nella rappresentazione di stringa di una data e ora. Per altre informazioni, vedere Stringhe di formato di data e ora personalizzato.

Instanziare una data con un'era

Per le due Calendar classi che supportano più ere, una data costituita da un determinato anno, mese e giorno del valore del mese può essere ambigua. Ad esempio, tutte le ere supportate da hanno anni il JapaneseCalendar cui numero è 1. In genere, se non viene specificata un'era, i metodi di data e ora e di calendario presuppongono che i valori appartengano all'era corrente. Questo vale per i DateTime costruttori e DateTimeOffset che includono parametri di tipo Calendar, nonché i metodi JapaneseCalendar.ToDateTime e JapaneseLunisolarCalendar.ToDateTime . Nell'esempio seguente viene creata un'istanza di una data che rappresenta il 1° gennaio del secondo anno di un'era non specificata. Se si esegue l'esempio quando l'era Reiwa è l'era corrente, la data viene interpretata come il secondo anno dell'era Reiwa. L'era, 令和, precede l'anno nella stringa restituita dal DateTime.ToString(String, IFormatProvider) metodo e corrisponde al 1° gennaio 2020, nel calendario gregoriano. L'era Reiwa inizia nell'anno 2019 del calendario gregoriano.

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

Tuttavia, se l'era cambia, la finalità di questo codice diventa ambigua. La data è destinata a rappresentare il secondo anno dell'era corrente o è destinata a rappresentare il secondo anno dell'era Heisei? Esistono due modi per evitare questa ambiguità:

  • Creare un'istanza del valore di data e ora usando la classe predefinita GregorianCalendar . È quindi possibile usare il calendario giapponese o il calendario lunisolar giapponese per la rappresentazione di stringa delle date, come illustrato nell'esempio seguente.

    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
    
    
    
  • Chiamare un metodo di data e ora che specifica in modo esplicito un'era. Sono inclusi i metodi seguenti:

    L'esempio seguente usa tre di questi metodi per creare un'istanza di una data e un'ora nell'era Meiji, iniziata l'8 settembre 1868 e terminata il 29 luglio 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)
    

Suggerimento

Quando si usano calendari che supportano più ere, usare sempre la data gregoriana per creare un'istanza di una data o specificare l'era quando si crea un'istanza di una data e un'ora in base a tale calendario.

Se si specifica un'era per il ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) metodo , specificare l'indice dell'era nella proprietà del Eras calendario. Per i calendari le cui ere sono soggette a modifiche, tuttavia, questi indici non sono valori costanti; l'era corrente è in corrispondenza dell'indice 0 e l'era meno recente è in corrispondenza dell'indice Eras.Length - 1. Quando una nuova era viene aggiunta a un calendario, gli indici delle epoche precedenti aumentano di uno. È possibile specificare l'indice dell'era appropriato nel modo seguente:

Calendari, ere e intervalli di date: controlli semplificati degli intervalli

Proprio come i singoli calendari hanno intervalli di date supportati, le classi JapaneseCalendar e JapaneseLunisolarCalendar hanno anche intervalli supportati. In precedenza, .NET usava controlli di intervallo di era rigorosi per garantire che una data specifica dell'era fosse compresa nell'intervallo di quell'era. Ovvero, se una data non rientra nell'intervallo dell'era specificata, il metodo genera un'eccezione ArgumentOutOfRangeException. Attualmente, .NET usa il controllo degli intervalli meno rigido per impostazione predefinita. Gli aggiornamenti a tutte le versioni di .NET hanno introdotto controlli di intervallo di era rilassati; il tentativo di creare un'istanza di una data specifica dell'era che si trova al di fuori dell'intervallo dell'era specificata "trasborda" nell'era successiva, e non viene generata alcuna eccezione.

L'esempio seguente tenta di creare un'istanza di una data nel 65° anno dell'era Showa, iniziata il 25 dicembre 1926 e terminata il 7 gennaio 1989. Questa data corrisponde al 9 gennaio 1990, che non rientra nell'intervallo dell'era Showa in JapaneseCalendar. Come illustrato nell'output dell'esempio, la data visualizzata dall'esempio è il 9 gennaio 1990, nel secondo anno dell'era Heisei.

using System;
using System.Globalization;

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

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

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

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

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

Public Module Example
    Dim jaJp As CultureInfo
    Dim cal As Calendar

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

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

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

Se i controlli di intervallo rilassato sono indesiderati, è possibile ripristinare controlli di intervallo rigorosi in diversi modi, a seconda della versione di .NET in cui è in esecuzione l'applicazione:

  • .NET Core: Aggiungere quanto segue al file di configurazione.netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceJapaneseEraYearRanges": true
      }
    }
    
  • .NET Framework 4.6 o versione successiva: Impostare l'opzione AppContext seguente nel file 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 o versioni precedenti: Impostare il valore del Registro di sistema seguente:

    Valore
    chiave HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    voce Switch.System.Globalization.EnforceJapaneseEraYearRanges
    Tipo REG_SZ
    valore vero

Con controlli di intervallo rigorosi abilitati, l'esempio precedente genera un'eccezione ArgumentOutOfRangeException e visualizza l'output seguente:

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

Rappresentare le date nei calendari con più ere

Se un Calendar oggetto supporta le ere ed è il calendario corrente di un CultureInfo oggetto, l'era viene inclusa nella rappresentazione di stringa di un valore di data e ora per i formati di data e ora completi, data lunga e data breve. Nell'esempio seguente vengono visualizzati questi modelli di data quando le impostazioni cultura correnti sono Giappone (giapponese) e il calendario corrente è il calendario giapponese.

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 

Avvertimento

La JapaneseCalendar classe è l'unica classe di calendario in .NET che supporta date in più di un'era e che può essere il calendario corrente di un oggetto CultureInfo, in particolare, di un oggetto CultureInfo che rappresenta la cultura giapponese (Giappone).

Per tutti i calendari, l'identificatore di formato personalizzato "g" include l'era nella stringa di risultato. Nell'esempio seguente viene utilizzata la stringa di formato personalizzata "MM-gg-a g" per includere l'era nella stringa di risultato quando il calendario corrente è il calendario gregoriano.

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

Nei casi in cui la rappresentazione di stringa di una data viene espressa in un calendario che non è il calendario corrente, la Calendar classe include un Calendar.GetEra metodo che può essere usato insieme Calendar.GetYearai metodi , Calendar.GetMonthe Calendar.GetDayOfMonth per indicare in modo univoco una data e l'era a cui appartiene. Nell'esempio seguente viene utilizzata la JapaneseLunisolarCalendar classe per fornire un'illustrazione. Si noti tuttavia che, includendo un nome significativo o un'abbreviazione anziché un numero intero per l'era nella stringa di risultato, è necessario creare un'istanza di un DateTimeFormatInfo oggetto e impostarne JapaneseCalendar il calendario corrente. Il JapaneseLunisolarCalendar calendario non può essere il calendario corrente di una cultura, ma in questo caso i due calendari condividono le stesse ere.

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

Nei calendari giapponesi, il primo anno di un'era è chiamato Gannen (元年). Ad esempio, invece di Heisei 1, il primo anno dell'era Heisei può essere descritto come Heisei Gannen. .NET adotta questa convenzione nelle operazioni di formattazione per date e ore formattate con le stringhe di formato di data e ora standard o personalizzate seguenti quando vengono usate con un CultureInfo oggetto che rappresenta le impostazioni cultura Japanese-Japan ("ja-JP") con la JapaneseCalendar classe :

Nell'esempio seguente, ad esempio, viene visualizzata una data nel primo anno dell'era Heisei in 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)

Se questo comportamento è indesiderato nelle operazioni di formattazione, è possibile ripristinare il comportamento precedente, che rappresenta sempre il primo anno di un'era come "1" anziché "Gannen", eseguendo le operazioni seguenti, a seconda della versione di .NET:

  • .NET Core: Aggiungere quanto segue al file di configurazione.netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.FormatJapaneseFirstYearAsANumber": true
      }
    }
    
  • .NET Framework 4.6 o versione successiva: Impostare l'opzione AppContext seguente nel file 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 o versioni precedenti: Impostare il valore del Registro di sistema seguente:

    Valore
    chiave HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    voce Switch.System.Globalization.FormatJapaneseFirstYearAsANumber
    Tipo REG_SZ
    valore vero

Con il supporto di gannen nelle operazioni di formattazione disabilitate, nell'esempio precedente viene visualizzato l'output seguente:

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

.NET è stato aggiornato anche in modo che le operazioni di analisi di data e ora supportino stringhe che contengono l'anno rappresentato come "1" o Gannen. Anche se non è necessario eseguire questa operazione, è possibile ripristinare il comportamento precedente per riconoscere solo "1" come primo anno di un'era. È possibile eseguire questa operazione come indicato di seguito, a seconda della versione di .NET:

  • .NET Core: Aggiungere quanto segue al file di configurazione.netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceLegacyJapaneseDateParsing": true
      }
    }
    
  • .NET Framework 4.6 o versione successiva: Impostare l'opzione AppContext seguente nel file 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 o versioni precedenti: Impostare il valore del Registro di sistema seguente:

    Valore
    chiave HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    voce Switch.System.Globalization.EnforceLegacyJapaneseDateParsing
    Tipo REG_SZ
    valore vero

Vedere anche