Partilhar via


Como: Permitir que usuários resolver Times ambíguos

Um horário ambíguo é um horário que aponta para mais de um Tempo Universal Coordenado (UTC).Ele ocorre quando a hora do relógio é atrasada, como durante a transição do horário de verão para o horário padrão de um fuso horário.Ao manipular um horário ambíguo, você pode fazer uma das seguintes opções:

  • Se o horário ambíguo for um item de dados inserido pelo usuário, você pode deixar para o usuário resolver a ambiguidade.

  • Faça uma suposição sobre como o tempo aponta para o UTC.Por exemplo, você pode supor que um horário ambíguo é sempre expresso no horário padrão do fuso horário.

Este tópico mostra como permitir que o usuário resolva um horário ambíguo.

Para permitir que um usuário resolva um horário ambíguo

  1. Obtenha a data e a hora entradas pelo usuário.

  2. Chame o método IsAmbiguousTime para determinar se o horário é ambíguo.

  3. Se o horário for ambíguo, chame o método GetAmbiguousTimeOffsets para recuperar uma matriz de objetos TimeSpan.Cada elemento na matriz contém um deslocamento do UTC para o qual o horário ambíguo pode apontar.

  4. Permita que o usuário selecione o deslocamento desejado.

  5. Obtenha a data e a hora UTC subtraindo do horário local o deslocamento selecionado pelo usuário.

  6. Chame o método static (Shared no Visual Basic .NET) SpecifyKind para definir a propriedade Kind do valor de data e hora UTC para DateTimeKind.Utc.

Exemplo

O exemplo a seguir solicita que o usuário insira uma data e hora e, se ela for ambígua, permite que o usuário selecione o horário UTC para o qual o horário ambíguo aponta.

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;        
}

O núcleo do código de exemplo usa uma matriz de objetos TimeSpan para indicar possíveis deslocamentos do UTC do horário ambíguo.No entanto, esses deslocamentos provavelmente não serão significativos para o usuário.Para esclarecer o significado dos deslocamentos, o código também nota se um deslocamento representa o horário padrão do fuso horário local ou seu horário de verão.O código determina qual horário é padrão e qual é de verão comparando o deslocamento com o valor da propriedade BaseUtcOffset.Essa propriedade indica a diferença entre o UTC e o horário padrão do fuso horário.

Nesse exemplo, todas as referências para o fuso horário local são feitas através da propriedade TimeZoneInfo.Local; o fuso horário local nunca é atribuído a uma variável de objeto.Essa é uma prática recomendada pois uma chamada para o método TimeZoneInfo.ClearCachedData invalida quaisquer objetos aos quais o fuso horário local esteja atribuído.

Compilando o código

Este exemplo requer:

  • Que uma referência a System.Core.dll seja adicionada ao projeto.

  • Que o namespace System seja importado com a instrução using (necessária em código C#).

Consulte também

Tarefas

Como: Resolver Times ambíguos

Outros recursos

Horários e Zonas de Tempo