Partilhar via


Trabalhar com calendários

Embora um valor de data e hora represente um momento no tempo, sua representação de cadeia de caracteres é sensível à cultura e depende tanto das convenções usadas para exibir valores de data e hora por uma cultura específica quanto do calendário usado por essa cultura. Este tópico explora o suporte para calendários no .NET e discute o uso das classes de calendário ao trabalhar com valores de data.

Calendários no .NET

Todos os calendários no .NET derivam da System.Globalization.Calendar classe, que fornece a implementação do calendário base. Uma das classes que herda da classe é a CalendarEastAsianLunisolarCalendar classe, que é a classe base para todos os calendários lunissolares. O .NET inclui as seguintes implementações de calendário:

Um calendário pode ser usado de duas maneiras:

  • Como o calendário usado por uma cultura específica. Cada CultureInfo objeto tem um calendário atual, que é o calendário que o objeto está usando no momento. As representações de cadeia de caracteres de todos os valores de data e hora refletem automaticamente a cultura atual e seu calendário atual. Normalmente, o calendário atual é o calendário padrão da cultura. CultureInfo Os objetos também têm calendários opcionais, que incluem calendários adicionais que a cultura pode usar.

  • Como um calendário independente de uma cultura específica. Nesse caso, Calendar os métodos são usados para expressar datas como valores que refletem o calendário.

Observe que seis classes de calendário – ChineseLunisolarCalendar, JapaneseLunisolarCalendar, JulianCalendar, PersianCalendarKoreanLunisolarCalendar, e TaiwanLunisolarCalendar – podem ser usadas apenas como calendários autônomos. Eles não são usados por nenhuma cultura como o calendário padrão ou como um calendário opcional.

Calendários e culturas

Cada cultura tem um calendário padrão, que é definido pela CultureInfo.Calendar propriedade. A CultureInfo.OptionalCalendars propriedade retorna uma matriz de objetos que especifica todos os calendários suportados Calendar por uma cultura específica, incluindo o calendário padrão dessa cultura.

O exemplo a seguir ilustra as CultureInfo.Calendar propriedades e CultureInfo.OptionalCalendars . Ele cria CultureInfo objetos para as culturas tailandesa (Tailândia) e japonesa (Japão) e exibe seus calendários padrão e opcionais. Observe que, em ambos os casos, o calendário padrão da cultura também está incluído na CultureInfo.OptionalCalendars coleção.

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)

O calendário atualmente em uso por um determinado CultureInfo objeto é definido pela propriedade da DateTimeFormatInfo.Calendar cultura. O objeto de DateTimeFormatInfo uma cultura é retornado pela CultureInfo.DateTimeFormat propriedade. Quando uma cultura é criada, seu valor padrão é o mesmo que o valor da CultureInfo.Calendar propriedade. No entanto, você pode alterar o calendário atual da cultura para qualquer calendário contido na matriz retornada CultureInfo.OptionalCalendars pela propriedade. Se você tentar definir o calendário atual para um calendário que não está incluído no valor da CultureInfo.OptionalCalendars propriedade, um ArgumentException será lançado.

O exemplo a seguir altera o calendário usado pela cultura árabe (Arábia Saudita). Primeiro, instancia um DateTime valor e o exibe usando a cultura atual - que, neste caso, é o inglês (Estados Unidos) - e o calendário da cultura atual (que, neste caso, é o calendário gregoriano). Em seguida, ele altera a cultura atual para árabe (Arábia Saudita) e exibe a data usando seu calendário padrão Um Al-Qura. Em seguida, chama o CalendarExists método para determinar se o calendário Hijri é suportado pela cultura árabe (Arábia Saudita). Como o calendário é suportado, ele altera o calendário atual para Hijri e exibe novamente a data. Observe que, em cada caso, a data é exibida usando o calendário atual da cultura atual.

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

Datas e calendários

Com exceção dos construtores que incluem um parâmetro de tipo Calendar e permitem que os elementos de uma data (ou seja, o mês, o dia e o ano) reflitam valores em um calendário designado, ambos e DateTimeOffsetDateTime valores são sempre baseados no calendário gregoriano. Isso significa, por exemplo, que a DateTime.Year propriedade retorna o ano no calendário gregoriano, e a DateTime.Day propriedade retorna o dia do mês no calendário gregoriano.

Importante

É importante lembrar que há uma diferença entre um valor de data e sua representação de cadeia de caracteres. O primeiro é baseado no calendário gregoriano; este último baseia-se no calendário atual de uma cultura específica.

O exemplo a seguir ilustra essa diferença entre DateTime propriedades e seus métodos correspondentes Calendar . No exemplo, a cultura atual é árabe (Egito), e o calendário atual é Um Al Qura. Um DateTime valor é fixado para o décimo quinto dia do sétimo mês de 2011. É claro que isso é interpretado como uma data gregoriana, porque esses mesmos valores são retornados DateTime.ToString(String, IFormatProvider) pelo método quando ele usa as convenções da cultura invariante. A representação de cadeia de caracteres da data que é formatada usando as convenções da cultura atual é 14/08/32, que é a data equivalente no calendário Um Al Qura. Em seguida, os membros de DateTime e Calendar são usados para retornar o dia, o mês e o ano do DateTime valor. Em cada caso, os valores retornados pelos DateTime membros refletem valores no calendário gregoriano, enquanto os valores retornados pelos UmAlQuraCalendar membros refletem valores no calendário 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: {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

Instanciar datas com base em um calendário

Como DateTime os valores são DateTimeOffset baseados no calendário gregoriano, você deve chamar um construtor sobrecarregado que inclua um parâmetro do tipo Calendar para instanciar um valor de data se quiser usar os valores de dia, mês ou ano de um calendário diferente. Você também pode chamar uma das sobrecargas do método de um calendário Calendar.ToDateTime específico para instanciar um DateTime objeto com base nos valores de um calendário específico.

O exemplo a seguir instancia um DateTime valor passando um HebrewCalendar objeto para um DateTime construtor e instancia um segundo DateTime valor chamando o HebrewCalendar.ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) método. Como os dois valores são criados com valores idênticos do calendário hebraico, a chamada para o DateTime.Equals método mostra que os dois DateTime valores são iguais.

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

Representar datas no calendário atual

Os métodos de formatação de data e hora sempre usam o calendário atual ao converter datas em cadeias de caracteres. Isso significa que a representação de cadeia de caracteres do ano, do mês e do dia do mês refletem o calendário atual e não refletem necessariamente o calendário gregoriano.

O exemplo a seguir mostra como o calendário atual afeta a representação de cadeia de caracteres de uma data. Ele altera a cultura atual para chinês (tradicional, Taiwan) e instancia um valor de data. Em seguida, exibe o calendário atual e a data, altera o calendário atual para TaiwanCalendare exibe o calendário e a data atuais mais uma vez. A primeira vez que a data é exibida, ela é representada como uma data no calendário gregoriano. Na segunda vez que é exibido, é representado como uma data no calendário de Taiwan.

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

Representar datas em um calendário não atual

Para representar uma data usando um calendário que não seja o calendário atual de uma cultura específica, você deve chamar métodos desse Calendar objeto. Por exemplo, os Calendar.GetYearmétodos , Calendar.GetMonth, e convertem Calendar.GetDayOfMonth o ano, mês e dia em valores que refletem um calendário específico.

Aviso

Como alguns calendários não são calendários opcionais de nenhuma cultura, representar datas nesses calendários sempre requer que você chame métodos de calendário. Isto é verdade para todos os calendários que derivam do EastAsianLunisolarCalendar, JulianCalendare PersianCalendar classes.

O exemplo a seguir usa um JulianCalendar objeto para instanciar uma data, 9 de janeiro de 1905, no calendário juliano. Quando esta data é exibida usando o calendário padrão (gregoriano), ela é representada como 22 de janeiro de 1905. Chamadas para métodos individuais JulianCalendar permitem que a data seja representada no calendário juliano.

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

Calendários e intervalos de datas

A data mais antiga suportada por um calendário é indicada pela propriedade desse Calendar.MinSupportedDateTime calendário. Para a GregorianCalendar turma, essa data é 1º de janeiro de 0001 E.C. A maioria dos outros calendários no .NET oferece suporte a uma data posterior. Tentar trabalhar com um valor de data e hora que precede a primeira data suportada de um calendário gera uma ArgumentOutOfRangeException exceção.

No entanto, há uma exceção importante. O valor padrão (não inicializado) de um DateTime objeto e um DateTimeOffset objeto é igual ao GregorianCalendar.MinSupportedDateTime valor. Se você tentar formatar essa data em um calendário que não suporta 1 de janeiro de 0001 E.C. e não fornecer um especificador de formato, o método de formatação usará o especificador de formato "s" (padrão de data/hora classificável) em vez do especificador de formato "G" (padrão geral de data/hora). Como resultado, a operação de formatação não lança uma ArgumentOutOfRangeException exceção. Em vez disso, ele retorna a data sem suporte. Isso é ilustrado no exemplo a seguir, que exibe o valor de DateTime.MinValue quando a cultura atual é definida como japonês (Japão) com o calendário japonês e para árabe (Egito) com o calendário Um Al Qura. Ele também define a cultura atual para inglês (Estados Unidos) e chama o DateTime.ToString(IFormatProvider) método com cada um desses CultureInfo objetos. Em cada caso, a data é exibida usando o padrão de data/hora classificável.

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

Trabalhar com eras

Normalmente, os calendários dividem as datas em eras. No entanto, as Calendar classes no .NET não suportam todas as épocas definidas por um calendário e a Calendar maioria das classes suporta apenas uma única era. Apenas as JapaneseCalendar classes e JapaneseLunisolarCalendar suportam várias eras.

Importante

A era Reiwa, uma nova era no JapaneseCalendar e JapaneseLunisolarCalendar, começa em 1º de maio de 2019. Essa alteração afeta todos os aplicativos que usam esses calendários. Consulte os seguintes artigos para obter mais informações:

Uma era na maioria dos calendários denota um período de tempo extremamente longo. No calendário gregoriano, por exemplo, a era atual se estende por mais de dois milênios. Para o JapaneseCalendar e o JapaneseLunisolarCalendar, os dois calendários que suportam várias eras, este não é o caso. Uma era corresponde ao período do reinado de um imperador. O apoio a várias épocas, particularmente quando o limite superior da era atual é desconhecido, coloca desafios especiais.

Nomes de épocas e épocas

No .NET, inteiros que representam as eras suportadas por uma implementação de calendário específica são armazenados em ordem inversa Calendar.Eras na matriz. A era atual (que é a era com o intervalo de tempo mais recente) está no índice zero e, para Calendar classes que suportam várias eras, cada índice sucessivo reflete a era anterior. A propriedade static Calendar.CurrentEra define o índice da era atual na Calendar.Eras matriz, é uma constante cujo valor é sempre zero. As classes individuais Calendar também incluem campos estáticos que retornam o valor da era atual. Eles estão listados na tabela a seguir.

Classe de calendário Campo da era atual
ChineseLunisolarCalendar ChineseEra
GregorianCalendar ADEra
HebrewCalendar HebrewEra
HijriCalendar HijriEra
JapaneseLunisolarCalendar JapaneseEra
JulianCalendar JulianEra
KoreanCalendar KoreanEra
KoreanLunisolarCalendar GregorianEra
PersianCalendar PersianEra
ThaiBuddhistCalendar ThaiBuddhistEra
UmAlQuraCalendar UmAlQuraEra

O nome que corresponde a um determinado número de era pode ser recuperado passando o número de era para o DateTimeFormatInfo.GetEraName método ou DateTimeFormatInfo.GetAbbreviatedEraName . O exemplo a seguir chama esses métodos para recuperar informações sobre o GregorianCalendar suporte de era na classe. Ele exibe a data do calendário gregoriano que corresponde a 1º de janeiro do segundo ano da era atual, bem como a data do calendário gregoriano que corresponde a 1º de janeiro do segundo ano de cada era do calendário japonês suportado.

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

Além disso, a cadeia de caracteres de formato de data e hora personalizada "g" inclui o nome da era de um calendário na representação da cadeia de caracteres de uma data e hora. Para obter mais informações, consulte Cadeias de caracteres de formato de data e hora personalizadas.

Instanciar uma data com uma era

Para as duas Calendar classes que suportam várias eras, uma data que consiste em um determinado ano, mês e dia do valor do mês pode ser ambígua. Por exemplo, todas as eras suportadas JapaneseCalendar pelo têm anos cujo número é 1. Normalmente, se uma era não for especificada, os métodos de data e hora e calendário assumem que os valores pertencem à era atual. Isso é verdadeiro para os DateTime construtores e DateTimeOffset que incluem parâmetros do tipo Calendar, bem como os métodos JapaneseCalendar.ToDateTime e JapaneseLunisolarCalendar.ToDateTime . O exemplo a seguir instancia uma data que representa 1º de janeiro do segundo ano de uma era não especificada. Se você executar o exemplo quando a era Reiwa é a era atual, a data é interpretada como o segundo ano da era Reiwa. A era, 令和, precede o ano na string retornada DateTime.ToString(String, IFormatProvider) pelo método e corresponde a 1º de janeiro de 2020, no calendário gregoriano. (A era Reiwa começa no ano de 2019 do calendário 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

No entanto, se a era mudar, a intenção deste código torna-se ambígua. A data pretende representar o segundo ano da era atual ou pretende representar o segundo ano da era Heisei? Existem duas formas de evitar esta ambiguidade:

  • Instancie o valor de data e hora usando a classe padrão GregorianCalendar . Em seguida, você pode usar o calendário japonês ou o calendário Lunisolar japonês para a representação de cadeias de caracteres de datas, como mostra o exemplo a seguir.

    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
    
    
    
  • Chame um método de data e hora que especifique explicitamente uma era. Isso inclui os seguintes métodos:

    O exemplo a seguir usa três desses métodos para instanciar uma data e hora na era Meiji, que começou em 8 de setembro de 1868 e terminou em 29 de julho de 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)
    

Gorjeta

Ao trabalhar com calendários que suportam várias eras, use sempre a data gregoriana para instanciar uma data ou especifique a era quando você instanciar uma data e hora com base nesse calendário.

Ao especificar uma era para o ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) método, você fornece o índice da era na propriedade do Eras calendário. No entanto, para calendários cujas eras estão sujeitas a alterações, estes índices não são valores constantes; A era atual está no índice 0, e a era mais antiga está no índice Eras.Length - 1. Quando uma nova era é adicionada a um calendário, os índices das eras anteriores aumentam em um. Você pode fornecer o índice de era apropriado da seguinte maneira:

Calendários, eras e intervalos de datas: Verificações de intervalo relaxadas

Assim como os calendários individuais têm suportado intervalos de datas, as eras JapaneseCalendar nas classes e JapaneseLunisolarCalendar também têm intervalos suportados. Anteriormente, o .NET usava verificações rigorosas de intervalo de era para garantir que uma data específica de era estivesse dentro do intervalo dessa era. Ou seja, se uma data estiver fora do intervalo da era especificada, o método lançará um ArgumentOutOfRangeException. Atualmente, o .NET usa a verificação de intervalo relaxada por padrão. As atualizações para todas as versões do .NET introduziram verificações de intervalo de era relaxadas; A tentativa de instanciar uma data específica da era que está fora do intervalo da era especificada "transborda" para a era seguinte, e nenhuma exceção é lançada.

O exemplo a seguir tenta instanciar uma data no 65º ano da era Showa, que começou em 25 de dezembro de 1926 e terminou em 7 de janeiro de 1989. Esta data corresponde a 9 de janeiro de 1990, que está fora do alcance da era Showa JapaneseCalendarno . Como o resultado do exemplo ilustra, a data exibida pelo exemplo é 9 de janeiro de 1990, no segundo ano da 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 as verificações de intervalo relaxadas forem indesejáveis, você poderá restaurar as verificações de intervalo estritas de várias maneiras, dependendo da versão do .NET na qual seu aplicativo está sendo executado:

  • .NET Core: Adicione o seguinte ao arquivo de configuração .netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceJapaneseEraYearRanges": true
      }
    }
    
  • .NET Framework 4.6 ou posterior: defina a seguinte opção AppContext no arquivo 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 ou anterior: defina o seguinte valor do Registro:

    Value
    Chave HKEY_LOCAL_MACHINE\Software\Microsoft\. NETFramework\AppContext
    Entrada Switch.System.Globalization.EnforceJapaneseEraYearRanges
    Tipo REG_SZ
    Valor verdadeiro

Com verificações de intervalo estritas habilitadas, o exemplo anterior lança um ArgumentOutOfRangeException e exibe a seguinte saída:

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

Representar datas em calendários com várias eras

Se um Calendar objeto suportar eras e for o calendário atual de um CultureInfo objeto, a era será incluída na representação de cadeia de caracteres de um valor de data e hora para os padrões de data e hora completas, data longa e data curta. O exemplo a seguir exibe esses padrões de data quando a cultura atual é Japão (japonês) e o calendário atual é o calendário japonês.

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 

Aviso

A JapaneseCalendar classe é a única classe de calendário no .NET que oferece suporte a datas em mais de uma era e que pode ser o calendário atual de um CultureInfo objeto - especificamente, de um CultureInfo objeto que representa a cultura japonesa (Japão).

Para todos os calendários, o especificador de formato personalizado "g" inclui a era na cadeia de caracteres de resultado. O exemplo a seguir usa a cadeia de caracteres de formato personalizado "MM-dd-yyyy g" para incluir a era na cadeia de caracteres de resultado quando o calendário atual é o calendário gregoriano.

   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.      

Nos casos em que a representação de cadeia de caracteres de uma data é expressa em um calendário que não é o calendário atual, a Calendar classe inclui um Calendar.GetEra método que pode ser usado junto com o Calendar.GetYear, Calendar.GetMonthe Calendar.GetDayOfMonth métodos para indicar inequivocamente uma data, bem como a era à qual ela pertence. O exemplo a seguir usa a JapaneseLunisolarCalendar classe para fornecer uma ilustração. No entanto, observe que incluir um nome ou abreviatura significativa em vez de um inteiro para a era na cadeia de caracteres de resultado requer que você instancie um DateTimeFormatInfo objeto e crie JapaneseCalendar seu calendário atual. (O JapaneseLunisolarCalendar calendário não pode ser o calendário atual de nenhuma cultura, mas neste caso os dois calendários compartilham as mesmas eras.)

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

Nos calendários japoneses, o primeiro ano de uma era é chamado Gannen (元年). Por exemplo, em vez de Heisei 1, o primeiro ano da era Heisei pode ser descrito como Heisei Gannen. O .NET adota essa convenção em operações de formatação para datas e horas formatadas com as seguintes cadeias de caracteres de formato de data e hora padrão ou personalizadas, quando são usadas com um CultureInfo objeto que representa a cultura japonês-japonesa ("ja-JP") com a JapaneseCalendar classe:

  • O padrão de data longa, indicado pela cadeia de caracteres de formato de data e hora padrão "D".
  • O padrão de tempo longo de data completa, indicado pela cadeia de caracteres de formato de data e hora padrão "F".
  • O padrão de tempo curto de data completa, indicado pela cadeia de caracteres de formato de data e hora padrão "f".
  • O padrão ano/mês, indicado pela cadeia de caracteres de formato de data e hora padrão "Y" ou "y".
  • A cadeia de caracteres de formato de data e hora personalizada "ggy'年'" ou "ggy年".

Por exemplo, o exemplo a seguir exibe uma data no primeiro ano da era Heisei no 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 esse comportamento for indesejável em operações de formatação, você pode restaurar o comportamento anterior, que sempre representa o primeiro ano de uma era como "1" em vez de "Gannen", fazendo o seguinte, dependendo da versão do .NET:

  • .NET Core: Adicione o seguinte ao arquivo de configuração .netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.FormatJapaneseFirstYearAsANumber": true
      }
    }
    
  • .NET Framework 4.6 ou posterior: defina a seguinte opção AppContext no arquivo 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 ou anterior: defina o seguinte valor do Registro:

    Value
    Chave HKEY_LOCAL_MACHINE\Software\Microsoft\. NETFramework\AppContext
    Entrada Switch.System.Globalization.FormatJapaneseFirstYearAsANumber
    Tipo REG_SZ
    Valor verdadeiro

Com o suporte gannen em operações de formatação desativado, o exemplo anterior exibe a seguinte saída:

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

O .NET também foi atualizado para que as operações de análise de data e hora suportem cadeias de caracteres que contêm o ano representado como "1" ou Gannen. Embora você não deva precisar fazer isso, você pode restaurar o comportamento anterior para reconhecer apenas "1" como o primeiro ano de uma era. Você pode fazer isso da seguinte maneira, dependendo da versão do .NET:

  • .NET Core: Adicione o seguinte ao arquivo de configuração .netcore.runtime.json :

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceLegacyJapaneseDateParsing": true
      }
    }
    
  • .NET Framework 4.6 ou posterior: defina a seguinte opção AppContext no arquivo 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 ou anterior: defina o seguinte valor do Registro:

    Value
    Chave HKEY_LOCAL_MACHINE\Software\Microsoft\. NETFramework\AppContext
    Entrada Switch.System.Globalization.EnforceLegacyJapaneseDateParsing
    Tipo REG_SZ
    Valor verdadeiro

Consulte também