Como exibir datas em calendários não gregorianos

 

O DateTime e DateTimeOffset tipos usam o calendário gregoriano como seu calendário padrão. Isso significa que chamar o método ToString de um valor de data e hora exibe a representação de cadeia de caracteres da data e hora no calendário gregoriano, mesmo que a data e hora tenha sido criada 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 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

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 de uma determinada cultura. O segundo pode ser usado com qualquer calendário.

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

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

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

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

  4. Atribuir o objeto de calendário para o Calendar propriedade o DateTimeFormatInfo objeto retornado pelo CultureInfo.DateTimeFormat propriedade.

    System_CAPS_noteObservação

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

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

Para exibir a data em qualquer calendário

  1. Instanciar um objeto de calendário derivado de 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, ligue para o objeto de calendário Get... método. Os métodos 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 calendários diferentes. Ele exibe a data após definir o calendário islâmico como calendário padrão para a cultura ar-JO e exibe a data usando o calendário persa, que não tem suporte como 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

Cada CultureInfo objeto pode oferecer suporte a um ou mais calendários, que são indicados pelo OptionalCalendars propriedade. Um deles é designado como o calendário padrão da cultura e é retornado pelo somente leitura CultureInfo.Calendar propriedade. Outro dos calendários opcionais pode ser designado como o padrão, atribuindo um Calendar objeto que representa o calendário para o DateTimeFormatInfo.Calendar retornada pelo CultureInfo.DateTimeFormat propriedade. No entanto, alguns calendários, como o calendário persa representado pelo PersianCalendar da 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 manipular muitos dos detalhes de gerar a representação de cadeia de caracteres de uma data usando um calendário específico. A classe CalendarUtility tem os seguintes membros:

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

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

  • HasSameName, um método particular atribuído para o Predicate<T> delegate é passado como um parâmetro para o Array.Exists<T> método. 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 público sobrecarregado que é passado dois parâmetros: tanto um DateTime ou DateTimeOffset valor para expressar no calendário representado pelo CalendarUtility objeto; e a cultura cujas regras de formatação devem ser usados. Seu comportamento ao retornar a representação de cadeia de caracteres de uma data depende de o calendário de destino ter suporte da cultura cujas regras de formatação devem ser usadas.

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

Compilando o Código

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

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

Mostrar: