Практическое руководство. Отображение дат в календарях, отличных от григорианского
Для типовDateTime и DateTimeOffset в качестве календаря по умолчанию используется григорианский календарь. Это означает, что вызов метода ToString
для значения даты и времени выведет строковое представление даты и времени по григорианскому календарю даже в том случае, если значение даты и времени создавалось с помощью другого календаря. Это показано в следующем примере, в котором двумя разными способами создаются значения даты и времени с персидским календарем. При вызове метода ToString значения даты и времени по-прежнему отображаются в григорианском календаре. В этом примере представлены два часто используемых неверных способа отображения даты в заданном календаре.
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
Для отображения даты в конкретном календаре можно использовать два различных способа. Для первого необходимо, чтобы календарь был установлен в качестве календаря по умолчанию в соответствующих региональных параметрах. Второй может использоваться с любым календарем.
Отображение даты в календаре, который является календарем по умолчанию доя определенного языка и региональных параметров
Создайте экземпляр календаря, производного от класса Calendar, который представляет нужный календарь.
Создайте экземпляр объекта CultureInfo, который представляет нужные язык и региональные параметры для отображения даты.
Вызовите метод Array.Exists, чтобы определить, является ли объект календаря элементом массива, возвращаемого свойством CultureInfo.OptionalCalendars. Если это так, то календарь можно использовать в качестве календаря по умолчанию для объекта CultureInfo. Если это не является элементом массива, следуйте инструкциям в разделе "Отображение даты в любом календаре".
Присвойте объект календаря в качестве значения свойству Calendar в объекте DateTimeFormatInfo, который возвращается свойством CultureInfo.DateTimeFormat.
Примечание.
Класс CultureInfo также содержит свойство Calendar. Но это свойство доступно только для чтения и является константой, то есть не изменяется в соответствии с новым календарем по умолчанию, присвоенным свойству DateTimeFormatInfo.Calendar.
Вызовите метод ToString или ToString, передав ему объект CultureInfo, для которого мы на предыдущем шаге изменили календарь по умолчанию.
Отображение даты в любом календаре
Создайте экземпляр календаря, производного от класса Calendar, который представляет нужный календарь.
Определите, какие элементы даты и времени должны отображаться в строковом представлении значения даты и времени.
Для каждого элемента даты и времени, который требуется отобразить, вызовите метод
Get
... объекта календаря. двумя компьютерами. Доступны следующие методы:GetYear отвечает за отображение года в соответствующем календаре.
GetMonth отвечает за отображение месяца в соответствующем календаре.
GetDayOfMonth отвечает за отображение числа дней в месяце в соответствующем календаре.
GetHour отвечает за отображение часа дня в соответствующем календаре.
GetMinute отвечает за отображение минут в часе в соответствующем календаре.
GetSecond отвечает за отображение секунд в минуте в соответствующем календаре.
GetMilliseconds, чтобы отобразить миллисекунды во втором в соответствующем календаре.
Пример
В примере отображается дата с помощью двух различных календарей. Отображается дата после определения исламского календаря в качестве календаря по умолчанию для региональных параметров ar-JO, а также дата с помощью персидского календаря, который не поддерживается в региональных параметрах 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
Каждый объект CultureInfo может поддерживать один или несколько календарей, что указано в свойстве OptionalCalendars. Один из них обозначается как календарь по умолчанию для выбранных языка и региональных параметров. Он доступен через свойство только для чтения CultureInfo.Calendar. Другие дополнительные календари можно назначить как календари по умолчанию. Для этого объект Calendar, который представляет календарь, присваивается свойству DateTimeFormatInfo.Calendar, возвращаемому свойством CultureInfo.DateTimeFormat. Однако некоторые календари, например персидский календарь (класс PersianCalendar), не могут служить дополнительными календарями для языка и региональных параметров.
В примере определяется повторно используемый служебный класс календаря CalendarUtility
для обработки множества данных, связанных с созданием строкового представления даты с помощью конкретного календаря. В классе CalendarUtility
представлены следующие члены:
Параметризованный конструктор, единственным параметром которого является объект Calendar для представления даты. Он присваивается закрытому полю класса.
Закрытый метод
CalendarExists
, логическое значение которого обозначает, поддерживается ли календарь (представленный объектомCalendarUtility
) объектом CultureInfo, который передан в метод в качестве параметра. При помощи этого метода создается оболочка для вызова метода Array.Exists, в который передается массив CultureInfo.OptionalCalendars.Закрытый метод
HasSameName
, назначенный делегату Predicate<T>, который передается в качестве параметра в метод Array.Exists. Каждый элемент массива передается методу до тех пор, пока метод не вернет значениеtrue
. Этот метод определяет, совпадает ли имя дополнительного календаря с именем календаря, представленного объектомCalendarUtility
.Перегруженный открытый метод
DisplayDate
, в который передаются два параметра: значение DateTime или DateTimeOffset для отображения в календаре, представленном объектомCalendarUtility
, а также язык и региональные параметры, правила форматирования которых нужно применить. Его поведение при возврате строкового представления даты зависит от того, поддерживается ли целевой календарь в языке и региональных параметрах, правила форматирования которых будут использоваться.
Независимо от календаря, используемого в этом примере для создания значения DateTime или DateTimeOffset, это значение обычно выражается в виде григорианской даты. Это происходит потому, что в типах DateTime и DateTimeOffset не сохраняются никакие данные календаря. Внутренне они представлены как число тактов, прошедших с момента полуночи 1 января 0001 г. Интерпретация этого числа зависит от календаря. Для большинства языков и региональных параметров по умолчанию используется григорианский календарь.