Partilhar via


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

Os tipos DateTime e DateTimeOffset usam o calendário gregoriano como seu calendário padrão. Isso significa que chamar um método ToString de um valor de data e hora exibe a representação de sequência de caracteres da data e hora no calendário gregoriano, mesmo que a data e hora tenham sido criadas usando outro calendário. Isso é ilustrado no exemplo a seguir, que usa duas maneiras diferentes para 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 ele chama o método ToString. Este exemplo reflete duas técnicas comumente usadas, mas incorretas, para exibir a data em um calendário específico.

������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
������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

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

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

  1. Crie uma instância de um objeto de calendário derivado da classe Calendar que representa o calendário a ser usado.

  2. Crie uma instância de um objeto CultureInfo que representa a cultura cuja formatação será usada para exibir a data.

  3. Chame o método Array.Exists<T> para determinar se o objeto de calendário é um membro da matriz retornada pela propriedade CultureInfo.OptionalCalendars. Isso indica que o calendário pode servir como o calendário padrão para o objeto CultureInfo. 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 à propriedade Calendar do objeto DateTimeFormatInfo retornado pela propriedade CultureInfo.DateTimeFormat.

    Observação

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

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

Para exibir a data em qualquer calendário

  1. Crie uma instância de um objeto de calendário derivado da classe Calendar que representa o calendário a ser usado.

  2. Determine que elementos de data e hora devem aparecem na representação de sequência de caracteres do valor de data e hora.

  3. Para cada elemento de data e hora que você desejar exibir, chame método Get … do objeto de calendário. As ações a seguir estão disponíveis:

    • 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 no minuto no calendário apropriado.

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

Exemplo

O exemplo exibe uma data usando dois diferentes calendários. Ele exibe a data após definir o calendário islâmico 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.

Imports System.Globalization

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

      ' Display the date using the Gregorian calendar.
      Console.WriteLine("Using the system default culture: {0}", _
                        hijriDate1.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}", _
                        hijriDate1.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(hijriDate1, jc))
      ' Display a DateTimeOffset value.
      Console.WriteLine(hijriUtil.DisplayDate(hijriDate2, 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}", _      
                        hijriDate1.ToString("d", ic))
      ' Display a Date value.
      Console.WriteLine(persianUtil.DisplayDate(hijriDate1, ic))
      ' Display a DateTimeOffset value.
      Console.WriteLine(persianUtil.DisplayDate(hijriDate2, 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
using System;
using System.Globalization;

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

      // Display the date using the Gregorian calendar.
      Console.WriteLine("Using the system default culture: {0}", 
                        hijriDate1.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}", 
                        hijriDate1.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(hijriDate1, jc));
      // Display a DateTimeOffset value.
      Console.WriteLine(hijriUtil.DisplayDate(hijriDate2, 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}",       
                        hijriDate1.ToString("d", ic));
      // Display a Date value.
      Console.WriteLine(persianUtil.DisplayDate(hijriDate1, ic));
      // Display a DateTimeOffset value.
      Console.WriteLine(persianUtil.DisplayDate(hijriDate2, 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

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

O exemplo define uma classe de utilitário calendário reutilizável, CalendarUtility, para manipular muitos dos detalhes de gerar a representação de sequência de caracteres de uma data usando um calendário específico. A classe CalendarUtility possui os seguintes membros:

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

  • CalendarExists, um método particular que retorna um valor Booleano que indica se o calendário representado pelo objeto CalendarUtility é suportado pelo objeto CultureInfo que é passado ao método como um parâmetro. O método ajusta uma chamada para o método Array.Exists<T>, ao qual ele passa a matriz CultureInfo.OptionalCalendars.

  • HasSameName, um método particular atribuído ao representante Predicate<T> que é passado como um parâmetro ao método Array.Exists<T>. Cada membro da matriz é passado ao 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 objeto CalendarUtility.

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

Independentemente do calendário usado para criar um valor DateTime ou um valor DateTimeOffset nesse exemplo, o valor normalmente é expresso como uma data gregoriana. Isso ocorre porque os tipos DateTime e DateTimeOffset não preservar nenhuma informação de calendário. Internamente, elas são representadas como o número de tiques transcorridos desde a meia-noite de 1º de janeiro de 0001. A interpretação desse número depende do calendário. Para a maioria dos culturas, o calendário padrão é o calendário gregoriano.

Compilando o código

Esse exemplo requer uma referência a System.Core.dll.

Compile o código na linha de comando usando o CSC ou vb.exe. Para compilar o código em Visual Studio, colocá-lo no modelo de projeto do console um aplicativo.

Consulte também

Conceitos

Executar operações de formatação