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
Crie uma instância de um objeto de calendário derivado da classe Calendar que representa o calendário a ser usado.
Crie uma instância de um objeto CultureInfo que representa a cultura cuja formatação será usada para exibir a data.
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 ".
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.
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
Crie uma instância de um objeto de calendário derivado da classe Calendar que representa o calendário a ser usado.
Determine que elementos de data e hora devem aparecem na representação de sequência de caracteres do valor de data e hora.
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.