Практическое руководство. Отображение дат в календарях, отличных от григорианскогоHow to: Display Dates in Non-Gregorian Calendars

Для типовDateTime и DateTimeOffset в качестве календаря по умолчанию используется григорианский календарь.The DateTime and DateTimeOffset types use the Gregorian calendar as their default calendar. Это означает, что вызов метода ToString для значения даты и времени выведет строковое представление даты и времени по григорианскому календарю даже в том случае, если значение даты и времени создавалось с помощью другого календаря.This means that calling a date and time value's ToString method displays the string representation of that date and time in the Gregorian calendar, even if that date and time was created using another calendar. Это показано в следующем примере, в котором двумя разными способами создаются значения даты и времени с персидским календарем. При вызове метода ToString значения даты и времени по-прежнему отображаются в григорианском календаре.This is illustrated in the following example, which uses two different ways to create a date and time value with the Persian calendar, but still displays those date and time values in the Gregorian calendar when it calls the ToString method. В этом примере представлены два часто используемых неверных способа отображения даты в заданном календаре.This example reflects two commonly used but incorrect techniques for displaying the date in a particular calendar.

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

Для отображения даты в конкретном календаре можно использовать два различных способа.Two different techniques can be used to display the date in a particular calendar. Для первого необходимо, чтобы календарь был установлен в качестве календаря по умолчанию в соответствующих региональных параметрах.The first requires that the calendar be the default calendar for a particular culture. Второй может использоваться с любым календарем.The second can be used with any calendar.

Отображение даты в календаре, который является календарем по умолчанию доя определенного языка и региональных параметровTo display the date for a culture's default calendar

  1. Создайте экземпляр календаря, производного от класса Calendar, который представляет нужный календарь.Instantiate a calendar object derived from the Calendar class that represents the calendar to be used.

  2. Создайте экземпляр объекта CultureInfo, который представляет нужные язык и региональные параметры для отображения даты.Instantiate a CultureInfo object representing the culture whose formatting will be used to display the date.

  3. Вызовите метод Array.Exists, чтобы определить, является ли объект календаря элементом массива, возвращаемого свойством CultureInfo.OptionalCalendars.Call the Array.Exists method to determine whether the calendar object is a member of the array returned by the CultureInfo.OptionalCalendars property. Если это так, то календарь можно использовать в качестве календаря по умолчанию для объекта CultureInfo.This indicates that the calendar can serve as the default calendar for the CultureInfo object. Если это не является элементом массива, следуйте инструкциям в разделе "Отображение даты в любом календаре".If it is not a member of the array, follow the instructions in the "To Display the Date in Any Calendar" section.

  4. Присвойте объект календаря в качестве значения свойству Calendar в объекте DateTimeFormatInfo, который возвращается свойством CultureInfo.DateTimeFormat.Assign the calendar object to the Calendar property of the DateTimeFormatInfo object returned by the CultureInfo.DateTimeFormat property.

    Примечание

    Класс CultureInfo также содержит свойство Calendar.The CultureInfo class also has a Calendar property. Но это свойство доступно только для чтения и является константой, то есть не изменяется в соответствии с новым календарем по умолчанию, присвоенным свойству DateTimeFormatInfo.Calendar.However, it is read-only and constant; it does not change to reflect the new default calendar assigned to the DateTimeFormatInfo.Calendar property.

  5. Вызовите метод ToString или ToString, передав ему объект CultureInfo, для которого мы на предыдущем шаге изменили календарь по умолчанию.Call either the ToString or the ToString method, and pass it the CultureInfo object whose default calendar was modified in the previous step.

Отображение даты в любом календареTo display the date in any calendar

  1. Создайте экземпляр календаря, производного от класса Calendar, который представляет нужный календарь.Instantiate a calendar object derived from the Calendar class that represents the calendar to be used.

  2. Определите, какие элементы даты и времени должны отображаться в строковом представлении значения даты и времени.Determine which date and time elements should appear in the string representation of the date and time value.

  3. Для каждого элемента даты и времени, который требуется отобразить, вызовите метод Get... объекта календаря.For each date and time element that you want to display, call the calendar object's Get метод.method. Доступны указанные далее методы.The following methods are available:

    • GetYear отвечает за отображение года в соответствующем календаре.GetYear, to display the year in the appropriate calendar.

    • GetMonth отвечает за отображение месяца в соответствующем календаре.GetMonth, to display the month in the appropriate calendar.

    • GetDayOfMonth отвечает за отображение числа дней в месяце в соответствующем календаре.GetDayOfMonth, to display the number of the day of the month in the appropriate calendar.

    • GetHour отвечает за отображение часа дня в соответствующем календаре.GetHour, to display the hour of the day in the appropriate calendar.

    • GetMinute отвечает за отображение минут в часе в соответствующем календаре.GetMinute, to display the minutes in the hour in the appropriate calendar.

    • GetSecond отвечает за отображение секунд в минуте в соответствующем календаре.GetSecond, to display the seconds in the minute in the appropriate calendar.

    • GetMilliseconds отвечает за отображение миллисекунд в секунде в соответствующем календаре.GetMilliseconds , to display the milliseconds in the second in the appropriate calendar.

ПримерExample

В примере отображается дата с помощью двух различных календарей.The example displays a date using two different calendars. Отображается дата после определения исламского календаря в качестве календаря по умолчанию для региональных параметров ar-JO, а также дата с помощью персидского календаря, который не поддерживается в региональных параметрах fa-IR как дополнительный календарь.It displays the date after defining the Hijri calendar as the default calendar for the ar-JO culture, and displays the date using the Persian calendar, which is not supported as an optional calendar by the fa-IR culture.

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.Each CultureInfo object can support one or more calendars, which are indicated by the OptionalCalendars property. Один из них обозначается как календарь по умолчанию для выбранных языка и региональных параметров. Он доступен через свойство только для чтения CultureInfo.Calendar.One of these is designated as the culture's default calendar and is returned by the read-only CultureInfo.Calendar property. Другие дополнительные календари можно назначить как календари по умолчанию. Для этого объект Calendar, который представляет календарь, присваивается свойству DateTimeFormatInfo.Calendar, возвращаемому свойством CultureInfo.DateTimeFormat.Another of the optional calendars can be designated as the default by assigning a Calendar object that represents that calendar to the DateTimeFormatInfo.Calendar property returned by the CultureInfo.DateTimeFormat property. Однако некоторые календари, например персидский календарь (класс PersianCalendar), не могут служить дополнительными календарями для языка и региональных параметров.However, some calendars, such as the Persian calendar represented by the PersianCalendar class, do not serve as optional calendars for any culture.

В примере определяется повторно используемый служебный класс календаря CalendarUtility для обработки множества данных, связанных с созданием строкового представления даты с помощью конкретного календаря.The example defines a reusable calendar utility class, CalendarUtility, to handle many of the details of generating the string representation of a date using a particular calendar. В классе CalendarUtilityпредставлены следующие члены:The CalendarUtility class has the following members:

  • Параметризованный конструктор, единственным параметром которого является объект Calendar для представления даты.A parameterized constructor whose single parameter is a Calendar object in which a date is to be represented. Он присваивается закрытому полю класса.This is assigned to a private field of the class.

  • Закрытый метод CalendarExists, логическое значение которого обозначает, поддерживается ли календарь (представленный объектом CalendarUtility) объектом CultureInfo, который передан в метод в качестве параметра.CalendarExists, a private method that returns a Boolean value indicating whether the calendar represented by the CalendarUtility object is supported by the CultureInfo object that is passed to the method as a parameter. При помощи этого метода создается оболочка для вызова метода Array.Exists, в который передается массив CultureInfo.OptionalCalendars.The method wraps a call to the Array.Exists method, to which it passes the CultureInfo.OptionalCalendars array.

  • Закрытый метод HasSameName, назначенный делегату Predicate<T>, который передается в качестве параметра в метод Array.Exists.HasSameName, a private method assigned to the Predicate<T> delegate that is passed as a parameter to the Array.Exists method. Каждый элемент массива передается методу до тех пор, пока метод не вернет значение true.Each member of the array is passed to the method until the method returns true. Этот метод определяет, совпадает ли имя дополнительного календаря с именем календаря, представленного объектом CalendarUtility.The method determines whether the name of an optional calendar is the same as the calendar represented by the CalendarUtility object.

  • Перегруженный открытый метод DisplayDate, в который передаются два параметра: значение DateTime или DateTimeOffset для отображения в календаре, представленном объектом CalendarUtility, а также язык и региональные параметры, правила форматирования которых нужно применить.DisplayDate, an overloaded public method that is passed two parameters: either a DateTime or DateTimeOffset value to express in the calendar represented by the CalendarUtility object; and the culture whose formatting rules are to be used. Его поведение при возврате строкового представления даты зависит от того, поддерживается ли целевой календарь в языке и региональных параметрах, правила форматирования которых будут использоваться.Its behavior in returning the string representation of a date depends on whether the target calendar is supported by the culture whose formatting rules are to be used.

Независимо от календаря, используемого в этом примере для создания значения DateTime или DateTimeOffset, это значение обычно выражается в виде григорианской даты.Regardless of the calendar used to create a DateTime or DateTimeOffset value in this example, that value is typically expressed as a Gregorian date. Это происходит потому, что в типах DateTime и DateTimeOffset не сохраняются никакие данные календаря.This is because the DateTime and DateTimeOffset types do not preserve any calendar information. Внутренне они представлены как число тактов, прошедших с момента полуночи 1 января 0001 г.Internally, they are represented as the number of ticks that have elapsed since midnight of January 1, 0001. Интерпретация этого числа зависит от календаря.The interpretation of that number depends on the calendar. Для большинства языков и региональных параметров по умолчанию используется григорианский календарь.For most cultures, the default calendar is the Gregorian calendar.

См. такжеSee also