How to: Display Dates in Non-Gregorian Calendars

Microsoft Silverlight will reach end of support after October 2021. Learn more.

The DateTime and DateTimeOffset types use the Gregorian calendar as their default calendar. 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.

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. Instantiate a calendar object derived from the Calendar class that represents the calendar to be used.

  2. Instantiate a CultureInfo object representing the culture whose formatting will be used to display the date.

  3. Determine whether the calendar object is a member of the array returned by the CultureInfo.OptionalCalendars property. 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. Assign the calendar object to the Calendar property of the DateTimeFormatInfo object returned by the CultureInfo.DateTimeFormat property.

    NoteNote:

    The CultureInfo class also has a Calendar property. However, it is read-only and constant; it does not change to reflect the new default calendar assigned to the DateTimeFormatInfo.Calendar property.

  5. 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. 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. For each date and time element that you want to display, call the calendar object's Get… method. The following methods are available:

    • GetYear, to display the year in the appropriate calendar.

    • GetMonth, to display the month in the appropriate calendar.

    • GetDayOfMonth, to display the number of the day of the month in the appropriate calendar.

    • GetHour, to display the hour of the day in the appropriate calendar.

    • GetMinute, to display the minutes in the hour in the appropriate calendar.

    • GetSecond, to display the seconds in the minute in the appropriate calendar.

    • GetMilliseconds , to display the milliseconds in the second in the appropriate calendar.

Example

The example displays a date using two different calendars. 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.

Imports System.Globalization

Public Class Example
   Public Shared Sub Demo(ByVal outputBlock As System.Windows.Controls.TextBlock)
      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 New CultureInfo("ar-JO")

      ' Display the date using the Gregorian calendar.
      outputBlock.Text += String.Format("Using the system default culture: {0}", _
                        hijriDate1.ToString("d")) & vbCrLf
      ' Display the date using the ar-JO culture's original default calendar.
      outputBlock.Text += String.Format("Using the ar-JO culture's original default calendar: {0}", _
                        hijriDate1.ToString("d", jc)) & vbCrLf
      ' Display the date using the Hijri calendar.
      outputBlock.Text &= "Using the ar-JO culture with Hijri as the default calendar:" & vbCrLf
      ' Display a Date value.
      outputBlock.Text &= hijriUtil.DisplayDate(hijriDate1, jc) & vbCrLf
      ' Display a DateTimeOffset value.
      outputBlock.Text &= hijriUtil.DisplayDate(hijriDate2, jc) & vbCrLf
   End Sub
End Class

Public Class CalendarUtility
   Private thisCalendar As Calendar
   Private targetCulture As CultureInfo

   Public Sub New(ByVal cal As Calendar)
      Me.thisCalendar = cal
   End Sub

   Private Function CalendarExists(ByVal culture As CultureInfo) As Boolean
      Me.targetCulture = culture
      For Each cal As Calendar In Me.targetCulture.OptionalCalendars
         If Me.HasSameName(cal) Then Return True
      Next   
      Return False
   End Function

   Private Function HasSameName(ByVal cal As Calendar) As Boolean
      If cal.ToString() = thisCalendar.ToString() Then
         Return True
      Else
         Return False
      End If
   End Function

   Public Function DisplayDate(ByVal dateToDisplay As Date, _
                               ByVal culture As CultureInfo) As String
      Dim displayOffsetDate As DateTimeOffset = dateToDisplay
      Return DisplayDate(displayOffsetDate, culture)
   End Function

   Public Function DisplayDate(ByVal dateToDisplay As DateTimeOffset, _
                               ByVal culture As CultureInfo) As String
      Dim returnString As String
      Dim specifier As String = "yyyy/MM/dd"

      If Me.CalendarExists(culture) Then
         returnString = String.Format("Displaying date in supported {0} calendar...", _
                                      thisCalendar.GetType().Name) & vbCrLf
         culture.DateTimeFormat.Calendar = Me.thisCalendar
         Return returnString & dateToDisplay.ToString(specifier, culture)
      Else
         returnString = String.Format("Displaying date in unsupported {0} calendar...", _
                                      thisCalendar.GetType().Name) & vbCrLf

         Dim separator As String = "/"

         Return returnString & 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:
'       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 System;
using System.Globalization;

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      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 = new CultureInfo("ar-JO");

      // Display the date using the Gregorian calendar.
      outputBlock.Text += String.Format("Using the system default culture: {0}",
                        hijriDate1.ToString("d")) + "\n";
      // Display the date using the ar-JO culture's original default calendar.
      outputBlock.Text += String.Format("Using the ar-JO culture's original default calendar: {0}",
                        hijriDate1.ToString("d", jc)) + "\n";
      // Display the date using the Hijri calendar.
      outputBlock.Text += "Using the ar-JO culture with Hijri as the default calendar:" + "\n";
      // Display a Date value.
      outputBlock.Text += hijriUtil.DisplayDate(hijriDate1, jc) + "\n";
      // Display a DateTimeOffset value.
      outputBlock.Text += hijriUtil.DisplayDate(hijriDate2, jc) + "\n";
   }
}

public class CalendarUtility
{
   private Calendar thisCalendar;
   private CultureInfo targetCulture;

   public CalendarUtility(Calendar cal)
   {
      this.thisCalendar = cal;
   }

   private bool CalendarExists(CultureInfo culture)
   {
      this.targetCulture = culture;
      foreach (Calendar cal in this.targetCulture.OptionalCalendars)
      {
         if (this.HasSameName(cal))
            return true;
      }
      return false;
   }

   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 returnString; 
      string specifier = "yyyy/MM/dd";

      if (this.CalendarExists(culture))
      {
         returnString = String.Format("Displaying date in supported {0} calendar...\n",
                                        this.thisCalendar.GetType().Name);
         culture.DateTimeFormat.Calendar = this.thisCalendar;
         return returnString + dateToDisplay.ToString(specifier, culture);
      }
      else
      {
         returnString = String.Format("Displaying date in unsupported {0} calendar...\n",
                           thisCalendar.GetType().Name);

         return returnString + thisCalendar.GetYear(dateToDisplay.DateTime).ToString("0000") +
                "/" +
                thisCalendar.GetMonth(dateToDisplay.DateTime).ToString("00") +
                "/" +
                thisCalendar.GetDayOfMonth(dateToDisplay.DateTime).ToString("00");
      }
   }
}
// The example displays the following output:
//       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

Each CultureInfo object can support one or more calendars, which are indicated by the OptionalCalendars property. One of these is designated as the culture's default calendar and is returned by the read-only CultureInfo.Calendar property. 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.

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. The CalendarUtility class has the following members:

  • 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, 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.

  • HasSameName, a method that compares calendar names to determine whether they represent the same calendar. The CalendarExists method passes each member of a culture's CultureInfo.OptionalCalendars array to the method until the method returns true. The method determines whether the name of an optional calendar is the same as the calendar represented by the CalendarUtility object.

  • 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.

Regardless of the calendar used to create a DateTime or DateTimeOffset value in this example, that value is typically expressed as a Gregorian date. This is because the DateTime and DateTimeOffset types do not preserve any calendar information. 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.