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
Instancie um objeto de calendário derivado da Calendar classe que representa o calendário a ser usado.
Instancie um CultureInfo objeto que representa a cultura cuja formatação será usada para exibir a data.
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".
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.
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
Instancie um objeto de calendário derivado da Calendar classe que representa o calendário a ser usado.
Determine quais elementos de data e hora devem aparecer na representação de cadeia de caracteres do valor de data e hora.
Para cada elemento de data e hora que você deseja exibir, chame o objeto
Get
de 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 peloCalendarUtility
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 retornetrue
. O método determina se o nome de um calendário opcional é o mesmo que o calendário representado peloCalendarUtility
objeto.DisplayDate
, um método público sobrecarregado que é passado dois parâmetros: um DateTime ou DateTimeOffset valor para expressar no calendário representado peloCalendarUtility
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.