Condividi tramite


Procedura: Visualizzare le date in calendari non gregoriani

I tipi DateTime e DateTimeOffset e usano il calendario gregoriano come calendario predefinito. Ciò significa che la chiamata al metodo ToString di un valore di data e ora visualizza la rappresentazione di stringa di tale data e ora nel calendario gregoriano, anche se la data e l'ora sono state create usando un altro calendario. Questo processo viene mostrato nell'esempio seguente, che usa due modi diversi per creare un valore di data e ora con il calendario persiano, continuando a visualizzare questi valori di data e ora nel calendario gregoriano quando viene chiamato il metodo ToString. L'esempio riflette due tecniche comuni ma non corrette per la visualizzazione della data in un determinato calendario.

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

Per visualizzare la data in un determinato calendario è possibile usare due tecniche differenti. La prima richiede che il calendario sia il calendario predefinito per determinate impostazioni cultura. La seconda può essere usata con qualsiasi calendario.

Per visualizzare la data per il calendario predefinito di determinate impostazione cultura

  1. Creare un'istanza di un oggetto calendario derivato dalla classe Calendar che rappresenta il calendario da usare.

  2. Creare un'istanza di un oggetto CultureInfo che rappresenta le impostazioni cultura la cui formattazione verrà usata per visualizzare la data.

  3. Chiamare il metodo Array.Exists per determinare se l'oggetto calendario è un membro della matrice restituita dalla proprietà CultureInfo.OptionalCalendars. Questo indica che il calendario può diventare il calendario predefinito per l'oggetto CultureInfo. Se non è un membro della matrice, seguire le istruzioni riportate nella sezione "Per visualizzare la data in qualsiasi calendario".

  4. Assegnare l'oggetto calendario alla proprietà Calendar dell'oggetto DateTimeFormatInfo restituito dalla proprietà CultureInfo.DateTimeFormat.

    Nota

    La classe CultureInfo include anche una proprietà Calendar. È tuttavia costante e di sola lettura e non viene modificata per riflettere il nuovo calendario predefinito assegnato alla proprietà DateTimeFormatInfo.Calendar.

  5. Chiamare il metodo ToString o ToString e passare al metodo l'oggetto CultureInfo il cui calendario predefinito è stato modificato nel passaggio precedente.

Per visualizzare la data in qualsiasi calendario

  1. Creare un'istanza di un oggetto calendario derivato dalla classe Calendar che rappresenta il calendario da usare.

  2. Determinare gli elementi di data e ora da visualizzare nella rappresentazione di stringa del valore di data e ora.

  3. Per ogni elemento di data e ora che si vuole visualizzare, chiamare il metodo Get dell'oggetto calendario. ProcessOnStatus. Sono disponibili i seguenti metodi:

    • GetYear, per visualizzare l'anno nel calendario appropriato.

    • GetMonth, per visualizzare il mese nel calendario appropriato.

    • GetDayOfMonth, per visualizzare il numero del giorno e del mese nel calendario appropriato.

    • GetHour, per visualizzare l'ora del giorno nel calendario appropriato.

    • GetMinute, per visualizzare i minuti dell'ora nel calendario appropriato.

    • GetSecond, per visualizzare i secondi del minuto nel calendario appropriato.

    • GetMilliseconds, per visualizzare i millisecondi del secondo nel calendario appropriato.

Esempio

L'esempio visualizza una data usando due calendari diversi. La data viene visualizzata dopo aver definito il calendario Hijri come calendario predefinito per le impostazioni cultura ar-JO e usando il calendario persiano che non è supportato come calendario facoltativo nelle impostazioni 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

Ogni oggetto CultureInfo può supportare uno o più calendari, indicati dalla proprietà OptionalCalendars. Uno di questi è designato come calendario predefinito delle impostazioni cultura e viene restituito dalla proprietà CultureInfo.Calendar di sola lettura. È possibile designare come predefinito un altro calendario tra quelli facoltativi assegnando un oggetto Calendar che rappresenta il calendario alla proprietà DateTimeFormatInfo.Calendar restituita dalla proprietà CultureInfo.DateTimeFormat. Tuttavia, alcuni calendari, ad esempio quello persiano rappresentato dalla classe PersianCalendar, non vengono usati come calendari facoltativi per alcuna delle impostazioni cultura.

Nell'esempio viene definita la classe dell'utilità di calendario riutilizzabile CalendarUtility per gestire molti dei dettagli relativi alla generazione della rappresentazione di stringa di una data mediante un determinato calendario. La classe CalendarUtility ha i seguenti membri:

  • Un costruttore con parametri il cui unico parametro è un oggetto Calendar in cui deve essere rappresentata una data. Viene assegnato a un campo privato della classe.

  • CalendarExists, metodo privato che restituisce un valore booleano indicante se il calendario rappresentato dall'oggetto CalendarUtility è supportato dall'oggetto CultureInfo passato al metodo come parametro. Il metodo esegue il wrapping di una chiamata al metodo Array.Exists, a cui passa la matrice CultureInfo.OptionalCalendars.

  • HasSameName, metodo privato assegnato al delegato Predicate<T> che viene passato come parametro al metodo Array.Exists. Ogni membro della matrice viene passato al metodo finché quest'ultimo non restituisce true. Il metodo determina se il nome di un calendario facoltativo è identico a quello del calendario rappresentato dall'oggetto CalendarUtility.

  • DisplayDate, metodo pubblico in overload a cui vengono passati due parametri: un valore DateTime o DateTimeOffset da esprimere nel calendario rappresentato dall'oggettoCalendarUtility e le impostazioni cultura di cui usare le regole di formattazione. Il comportamento nella restituzione della rappresentazione di stringa di una data varia a seconda che il calendario di destinazione sia supportato dalle impostazioni cultura le cui regole di formattazione devono essere usate.

Indipendentemente dal calendario usato per creare un valore DateTime o DateTimeOffset in questo esempio, il valore viene in genere espresso come data del calendario gregoriano. Il motivo è che i tipi DateTime e DateTimeOffset non mantengono le informazioni sul calendario. Internamente vengono rappresentati come numero di cicli trascorsi dopo la mezzanotte del 1 gennaio 0001. L'interpretazione del numero dipende dal calendario. Per la maggior parte delle impostazioni cultura, il calendario predefinito è il calendario gregoriano.