Partilhar via


Como: Exibir datas em calendários não gregorianos

Os DateTime tipos e DateTimeOffset usam o calendário gregoriano como calendário padrão. Isso significa que chamar o método de ToString um valor de data e hora exibe a representação de cadeia de caracteres dessa data e hora no calendário gregoriano, mesmo que essa data e hora tenham sido criadas usando outro calendário. Isso é ilustrado no exemplo a seguir, que usa duas maneiras diferentes de criar um valor de data e hora com o calendário persa, mas ainda exibe esses valores de data e hora no calendário gregoriano quando chama o ToString método. Este exemplo reflete duas técnicas comumente usadas, mas incorretas, para exibir a data em um calendário específico.

PersianCalendar persianCal = new PersianCalendar();

DateTime persianDate = persianCal.ToDateTime(1387, 3, 18, 12, 0, 0, 0);
Console.WriteLine(persianDate.ToString());

persianDate = new DateTime(1387, 3, 18, persianCal);
Console.WriteLine(persianDate.ToString());
// The example displays the following output to the console:
//       6/7/2008 12:00:00 PM
//       6/7/2008 12:00:00 AM
Dim persianCal As New PersianCalendar()

Dim persianDate As Date = persianCal.ToDateTime(1387, 3, 18, _
                                                12, 0, 0, 0)
Console.WriteLine(persianDate.ToString())

persianDate = New DateTime(1387, 3, 18, persianCal)
Console.WriteLine(persianDate.ToString())
' The example displays the following output to the console:
'       6/7/2008 12:00:00 PM
'       6/7/2008 12:00:00 AM

Duas técnicas diferentes podem ser usadas para exibir a data em um calendário específico. O primeiro requer que o calendário seja o calendário padrão para uma cultura específica. O segundo pode ser usado com qualquer calendário.

Para exibir a data do calendário padrão de uma cultura

  1. Instancie um objeto de calendário derivado da Calendar classe que representa o calendário a ser usado.

  2. Instancie um CultureInfo objeto que representa a cultura cuja formatação será usada para exibir a data.

  3. Chame o Array.Exists método para determinar se o objeto de calendário é um membro da matriz retornada pela CultureInfo.OptionalCalendars propriedade. Isso indica que o calendário pode servir como o calendário padrão para o CultureInfo objeto. Se não for um membro da matriz, siga as instruções na seção "Para exibir a data em qualquer calendário".

  4. Atribua o objeto de calendário à Calendar propriedade do DateTimeFormatInfo objeto retornado pela CultureInfo.DateTimeFormat propriedade.

    Nota

    A CultureInfo classe também tem uma Calendar propriedade. No entanto, é somente leitura e constante; ele não é alterado para refletir o novo calendário padrão atribuído à DateTimeFormatInfo.Calendar propriedade.

  5. Chame o ToString ou o ToString método e passe-lhe o CultureInfo objeto cujo calendário padrão foi modificado na etapa anterior.

Para exibir a data em qualquer calendário

  1. Instancie um objeto de calendário derivado da Calendar classe que representa o calendário a ser usado.

  2. Determine quais elementos de data e hora devem aparecer na representação de cadeia de caracteres do valor de data e hora.

  3. Para cada elemento de data e hora que você deseja exibir, chame o objeto Getde calendário ... método. Estão disponíveis os seguintes métodos:

    • GetYear, para exibir o ano no calendário apropriado.

    • GetMonth, para exibir o mês no calendário apropriado.

    • GetDayOfMonth, para exibir o número do dia do mês no calendário apropriado.

    • GetHour, para exibir a hora do dia no calendário apropriado.

    • GetMinute, para exibir os minutos na hora no calendário apropriado.

    • GetSecond, para exibir os segundos do minuto no calendário apropriado.

    • GetMilliseconds, para exibir os milissegundos no segundo no calendário apropriado.

Exemplo

O exemplo exibe uma data usando dois calendários diferentes. Ele exibe a data depois de definir o calendário Hijri como o calendário padrão para a cultura ar-JO e exibe a data usando o calendário persa, que não é suportado como um calendário opcional pela cultura fa-IR.

using System;
using System.Globalization;

public class CalendarDates
{
   public static void Main()
   {
      HijriCalendar hijriCal = new HijriCalendar();
      CalendarUtility hijriUtil = new CalendarUtility(hijriCal);
      DateTime dateValue1 = new DateTime(1429, 6, 29, hijriCal);
      DateTimeOffset dateValue2 = new DateTimeOffset(dateValue1,
                                  TimeZoneInfo.Local.GetUtcOffset(dateValue1));
      CultureInfo jc = CultureInfo.CreateSpecificCulture("ar-JO");

      // Display the date using the Gregorian calendar.
      Console.WriteLine("Using the system default culture: {0}",
                        dateValue1.ToString("d"));
      // Display the date using the ar-JO culture's original default calendar.
      Console.WriteLine("Using the ar-JO culture's original default calendar: {0}",
                        dateValue1.ToString("d", jc));
      // Display the date using the Hijri calendar.
      Console.WriteLine("Using the ar-JO culture with Hijri as the default calendar:");
      // Display a Date value.
      Console.WriteLine(hijriUtil.DisplayDate(dateValue1, jc));
      // Display a DateTimeOffset value.
      Console.WriteLine(hijriUtil.DisplayDate(dateValue2, jc));

      Console.WriteLine();

      PersianCalendar persianCal = new PersianCalendar();
      CalendarUtility persianUtil = new CalendarUtility(persianCal);
      CultureInfo ic = CultureInfo.CreateSpecificCulture("fa-IR");

      // Display the date using the ir-FA culture's default calendar.
      Console.WriteLine("Using the ir-FA culture's default calendar: {0}",
                        dateValue1.ToString("d", ic));
      // Display a Date value.
      Console.WriteLine(persianUtil.DisplayDate(dateValue1, ic));
      // Display a DateTimeOffset value.
      Console.WriteLine(persianUtil.DisplayDate(dateValue2, ic));
   }
}

public class CalendarUtility
{
   private Calendar thisCalendar;
   private CultureInfo targetCulture;

   public CalendarUtility(Calendar cal)
   {
      this.thisCalendar = cal;
   }

   private bool CalendarExists(CultureInfo culture)
   {
      this.targetCulture = culture;
      return Array.Exists(this.targetCulture.OptionalCalendars,
                          this.HasSameName);
   }

   private bool HasSameName(Calendar cal)
   {
      if (cal.ToString() == thisCalendar.ToString())
         return true;
      else
         return false;
   }

   public string DisplayDate(DateTime dateToDisplay, CultureInfo culture)
   {
      DateTimeOffset displayOffsetDate = dateToDisplay;
      return DisplayDate(displayOffsetDate, culture);
   }

   public string DisplayDate(DateTimeOffset dateToDisplay,
                             CultureInfo culture)
   {
      string specifier = "yyyy/MM/dd";

      if (this.CalendarExists(culture))
      {
         Console.WriteLine("Displaying date in supported {0} calendar...",
                           this.thisCalendar.GetType().Name);
         culture.DateTimeFormat.Calendar = this.thisCalendar;
         return dateToDisplay.ToString(specifier, culture);
      }
      else
      {
         Console.WriteLine("Displaying date in unsupported {0} calendar...",
                           thisCalendar.GetType().Name);

         string separator = targetCulture.DateTimeFormat.DateSeparator;

         return thisCalendar.GetYear(dateToDisplay.DateTime).ToString("0000") +
                separator +
                thisCalendar.GetMonth(dateToDisplay.DateTime).ToString("00") +
                separator +
                thisCalendar.GetDayOfMonth(dateToDisplay.DateTime).ToString("00");
      }
   }
}
// The example displays the following output to the console:
//       Using the system default culture: 7/3/2008
//       Using the ar-JO culture's original default calendar: 03/07/2008
//       Using the ar-JO culture with Hijri as the default calendar:
//       Displaying date in supported HijriCalendar calendar...
//       1429/06/29
//       Displaying date in supported HijriCalendar calendar...
//       1429/06/29
//
//       Using the ir-FA culture's default calendar: 7/3/2008
//       Displaying date in unsupported PersianCalendar calendar...
//       1387/04/13
//       Displaying date in unsupported PersianCalendar calendar...
//       1387/04/13
Imports System.Globalization

Public Class CalendarDates
    Public Shared Sub Main()
        Dim hijriCal As New HijriCalendar()
        Dim hijriUtil As New CalendarUtility(hijriCal)
        Dim dateValue1 As Date = New Date(1429, 6, 29, hijriCal)
        Dim dateValue2 As DateTimeOffset = New DateTimeOffset(dateValue1, _
                                           TimeZoneInfo.Local.GetUtcOffset(dateValue1))
        Dim jc As CultureInfo = CultureInfo.CreateSpecificCulture("ar-JO")

        ' Display the date using the Gregorian calendar.
        Console.WriteLine("Using the system default culture: {0}", _
                          dateValue1.ToString("d"))
        ' Display the date using the ar-JO culture's original default calendar.
        Console.WriteLine("Using the ar-JO culture's original default calendar: {0}", _
                          dateValue1.ToString("d", jc))
        ' Display the date using the Hijri calendar.
        Console.WriteLine("Using the ar-JO culture with Hijri as the default calendar:")
        ' Display a Date value.
        Console.WriteLine(hijriUtil.DisplayDate(dateValue1, jc))
        ' Display a DateTimeOffset value.
        Console.WriteLine(hijriUtil.DisplayDate(dateValue2, jc))

        Console.WriteLine()

        Dim persianCal As New PersianCalendar()
        Dim persianUtil As New CalendarUtility(persianCal)
        Dim ic As CultureInfo = CultureInfo.CreateSpecificCulture("fa-IR")

        ' Display the date using the ir-FA culture's default calendar.
        Console.WriteLine("Using the ir-FA culture's default calendar: {0}", _
                          dateValue1.ToString("d", ic))
        ' Display a Date value.
        Console.WriteLine(persianUtil.DisplayDate(dateValue1, ic))
        ' Display a DateTimeOffset value.
        Console.WriteLine(persianUtil.DisplayDate(dateValue2, ic))
    End Sub
End Class

Public Class CalendarUtility
    Private thisCalendar As Calendar
    Private targetCulture As CultureInfo

    Public Sub New(cal As Calendar)
        Me.thisCalendar = cal
    End Sub

    Private Function CalendarExists(culture As CultureInfo) As Boolean
        Me.targetCulture = culture
        Return Array.Exists(Me.targetCulture.OptionalCalendars, _
                            AddressOf Me.HasSameName)
    End Function

    Private Function HasSameName(cal As Calendar) As Boolean
        If cal.ToString() = thisCalendar.ToString() Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function DisplayDate(dateToDisplay As Date, _
                                culture As CultureInfo) As String
        Dim displayOffsetDate As DateTimeOffset = dateToDisplay
        Return DisplayDate(displayOffsetDate, culture)
    End Function

    Public Function DisplayDate(dateToDisplay As DateTimeOffset, _
                                culture As CultureInfo) As String
        Dim specifier As String = "yyyy/MM/dd"

        If Me.CalendarExists(culture) Then
            Console.WriteLine("Displaying date in supported {0} calendar...", _
                              thisCalendar.GetType().Name)
            culture.DateTimeFormat.Calendar = Me.thisCalendar
            Return dateToDisplay.ToString(specifier, culture)
        Else
            Console.WriteLine("Displaying date in unsupported {0} calendar...", _
                              thisCalendar.GetType().Name)

            Dim separator As String = targetCulture.DateTimeFormat.DateSeparator

            Return thisCalendar.GetYear(dateToDisplay.DateTime).ToString("0000") & separator & _
                   thisCalendar.GetMonth(dateToDisplay.DateTime).ToString("00") & separator & _
                   thisCalendar.GetDayOfMonth(dateToDisplay.DateTime).ToString("00")
        End If
    End Function
End Class
' The example displays the following output to the console:
'       Using the system default culture: 7/3/2008
'       Using the ar-JO culture's original default calendar: 03/07/2008
'       Using the ar-JO culture with Hijri as the default calendar:
'       Displaying date in supported HijriCalendar calendar...
'       1429/06/29
'       Displaying date in supported HijriCalendar calendar...
'       1429/06/29
'       
'       Using the ir-FA culture's default calendar: 7/3/2008
'       Displaying date in unsupported PersianCalendar calendar...
'       1387/04/13
'       Displaying date in unsupported PersianCalendar calendar...
'       1387/04/13

Cada CultureInfo objeto pode suportar um ou mais calendários, que são indicados pela OptionalCalendars propriedade. Um deles é designado como o calendário padrão da cultura e é retornado pela propriedade somente CultureInfo.Calendar leitura. Outro dos calendários opcionais pode ser designado como padrão atribuindo um Calendar objeto que representa esse calendário à DateTimeFormatInfo.Calendar propriedade retornada CultureInfo.DateTimeFormat pela propriedade. No entanto, alguns calendários, como o calendário persa PersianCalendar representado pela classe, não servem como calendários opcionais para nenhuma cultura.

O exemplo define uma classe de utilitário de calendário reutilizável, CalendarUtility, para lidar com muitos dos detalhes da geração da representação de cadeia de caracteres de uma data usando um calendário específico. A CalendarUtility classe tem os seguintes membros:

  • Um construtor parametrizado cujo único parâmetro é um Calendar objeto no qual uma data deve ser representada. Isso é atribuído a um campo privado da classe.

  • CalendarExists, um método privado que retorna um valor booleano indicando se o calendário representado pelo CalendarUtility objeto é suportado CultureInfo pelo objeto que é passado para o método como um parâmetro. O método encapsula uma chamada para o método, para o Array.Exists qual ele passa a CultureInfo.OptionalCalendars matriz.

  • HasSameName, um método privado atribuído ao Predicate<T> delegado que é passado como um parâmetro para o Array.Exists método. Cada membro da matriz é passado para o método até que o método retorne true. O método determina se o nome de um calendário opcional é o mesmo que o calendário representado pelo CalendarUtility objeto.

  • DisplayDate, um método público sobrecarregado que é passado dois parâmetros: um DateTime ou DateTimeOffset valor para expressar no calendário representado pelo CalendarUtility objeto; e a cultura cujas regras de formatação devem ser usadas. Seu comportamento ao retornar a representação de cadeia de caracteres de uma data depende se o calendário de destino é suportado pela cultura cujas regras de formatação devem ser usadas.

Independentemente do calendário usado para criar um DateTime ou DateTimeOffset valor neste exemplo, esse valor é normalmente expresso como uma data gregoriana. Isso ocorre porque os tipos e DateTimeOffset não preservam nenhuma informação de DateTime calendário. Internamente, eles são representados como o número de carrapatos que decorreram desde a meia-noite de 1º de janeiro de 0001. A interpretação desse número depende do calendário. Para a maioria das culturas, o calendário padrão é o calendário gregoriano.