Condividi tramite


Procedura: consentire agli utenti di risolvere orari ambigui

Un'ora ambigua è un'ora associata a più ore UTC (Coordinated Universal Time). Si verifica quando l'orario viene portato indietro, ad esempio durante la transizione da ora legale a ora solare di un fuso orario. Quando si gestisce un'ora ambigua, è possibile effettuare una delle operazioni seguenti:

  • Se l'ora ambigua è un elemento di dati immesso dall'utente, sarà l'utente a risolvere l'ambiguità.

  • Fare una supposizione sul modo in cui l'ora viene associata all'ora UTC. Ad esempio, è possibile presupporre che un'ora ambigua sia sempre espressa nell'ora solare del fuso orario.

In questo argomento viene illustrato come consentire a un utente di risolvere un'ora ambigua.

Per consentire a un utente di risolvere un'ora ambigua

  1. Ottenere l'input di data e ora dall'utente.

  2. Chiamare il metodo IsAmbiguousTime per determinare se l'ora è ambigua.

  3. Se l'ora è ambigua, chiamare il metodo GetAmbiguousTimeOffsets per recuperare una matrice di oggetti TimeSpan. Ogni elemento della matrice contiene un offset UTC a cui è possibile associare l'ora ambigua.

  4. Consentire all'utente di selezionare l'offset desiderato.

  5. Ottenere la data e ora UTC sottraendo l'offset selezionato dall'utente dall'ora locale.

  6. Chiamare il metodo static (Shared in Visual Basic .NET) SpecifyKind per impostare la proprietà Kind del valore di data e ora UTC su DateTimeKind.Utc.

Esempio

Nell'esempio seguente viene richiesto all'utente di immettere una data e ora e, se è ambigua, consente all'utente di selezionare l'ora UTC alla quale è associata l'ora ambigua.

Private Sub GetUserDateInput()
   ' Get date and time from user
   Dim inputDate As Date = GetUserDateTime()
   Dim utcDate As Date

   ' Exit if date has no significant value
   If inputDate = Date.MinValue Then Exit Sub

   If TimeZoneInfo.Local.IsAmbiguousTime(inputDate) Then
      Console.WriteLine("The date you've entered is ambiguous.")
      Console.WriteLine("Please select the correct offset from Universal Coordinated Time:")
      Dim offsets() As TimeSpan = TimeZoneInfo.Local.GetAmbiguousTimeOffsets(inputDate)
      For ctr As Integer = 0 to offsets.Length - 1
         Dim zoneDescription As String
         If offsets(ctr).Equals(TimeZoneInfo.Local.BaseUtcOffset) Then 
            zoneDescription = TimeZoneInfo.Local.StandardName
         Else
            zoneDescription = TimeZoneInfo.Local.DaylightName
         End If
         Console.WriteLine("{0}.) {1} hours, {2} minutes ({3})", _
                           ctr, offsets(ctr).Hours, offsets(ctr).Minutes, zoneDescription)
      Next         
      Console.Write("> ")
      Dim selection As Integer = CInt(Console.ReadLine())

      ' Convert local time to UTC, and set Kind property to DateTimeKind.Utc
      utcDate = Date.SpecifyKind(inputDate - offsets(selection), DateTimeKind.Utc)

      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString())
   Else
      utcDate = inputDate.ToUniversalTime()
      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString())    
   End If
End Sub

Private Function GetUserDateTime() As Date
   Dim exitFlag As Boolean = False            ' flag to exit loop if date is valid
   Dim dateString As String 
   Dim inputDate As Date = Date.MinValue

   Console.Write("Enter a local date and time: ")
   Do While Not exitFlag
      dateString = Console.ReadLine()
      If dateString.ToUpper = "E" Then exitFlag = True
      If Date.TryParse(dateString, inputDate) Then
         exitFlag = true
      Else   
         Console.Write("Enter a valid date and time, or enter 'e' to exit: ")
      End If
   Loop

   Return inputDate        
End Function
private void GetUserDateInput()
{
   // Get date and time from user
   DateTime inputDate = GetUserDateTime();
   DateTime utcDate;

   // Exit if date has no significant value
   if (inputDate == DateTime.MinValue) return;

   if (TimeZoneInfo.Local.IsAmbiguousTime(inputDate))
   {
      Console.WriteLine("The date you've entered is ambiguous.");
      Console.WriteLine("Please select the correct offset from Universal Coordinated Time:");
      TimeSpan[] offsets = TimeZoneInfo.Local.GetAmbiguousTimeOffsets(inputDate);
      for (int ctr = 0; ctr < offsets.Length; ctr++)
      {
         Console.WriteLine("{0}.) {1} hours, {2} minutes", ctr, offsets[ctr].Hours, offsets[ctr].Minutes);
      }
      Console.Write("> ");
      int selection = Convert.ToInt32(Console.ReadLine());

      // Convert local time to UTC, and set Kind property to DateTimeKind.Utc
      utcDate = DateTime.SpecifyKind(inputDate - offsets[selection], DateTimeKind.Utc);

      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString());
   }
   else
   {
      utcDate = inputDate.ToUniversalTime();
      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString());    
   }
}

private DateTime GetUserDateTime() 
{
   bool exitFlag = false;             // flag to exit loop if date is valid
   string dateString;  
   DateTime inputDate = DateTime.MinValue;

   Console.Write("Enter a local date and time: ");
   while (! exitFlag)
   {
      dateString = Console.ReadLine();
      if (dateString.ToUpper() == "E")
         exitFlag = true;

      if (DateTime.TryParse(dateString, out inputDate))
         exitFlag = true;
      else
         Console.Write("Enter a valid date and time, or enter 'e' to exit: ");
   }

   return inputDate;        
}

Nel codice di esempio viene utilizzata una matrice di oggetti TimeSpan per indicare i possibili offset dell'ora ambigua dall'ora UTC. Questi offset non saranno però significativi per l'utente. Per chiarificare il significato di offset, nel codice viene anche indicato se un offset rappresenta l'ora solare o l'ora legale del fuso orario locale. Dal confronto dell'offset con il valore della proprietà BaseUtcOffset è possibile stabilire quale sia l'ora solare e quale l'ora legale. Questa proprietà indica la differenza tra l'ora UTC e l'ora solare del fuso orario.

In questo esempio, tutti i riferimenti al fuso orario locale vengono eseguiti tramite la proprietà TimeZoneInfo.Local. Il fuso orario locale non viene mai assegnato a una variabile oggetto. È una procedura consigliata poiché una chiamata al metodo TimeZoneInfo.ClearCachedData invalida tutti gli oggetti assegnati al fuso orario locale.

Compilazione del codice

Per questo esempio è necessario:

  • Aggiungere un riferimento a System.Core.dll al progetto.

  • Importare lo spazio dei nomi System con l'istruzione using (richiesto nel codice C#).

Vedere anche

Attività

Procedura: risolvere orari ambigui

Altre risorse

Date, ora e fusi orari