Compartir a través de


Cómo: Permitir que los usuarios resuelvan horas ambiguas

Una hora ambigua es aquella que se asigna a más de una hora universal coordinada (UTC). Se produce al retrasar los relojes, como en el cambio de horario de verano a horario estándar. Para tratar una hora ambigua, puede elegir una de las siguientes acciones:

  • Si la hora ambigua es un elemento de datos especificado por el usuario, puede dejar que el usuario resuelva la ambigüedad.

  • Haga una suposición sobre cómo se asigna la hora a la hora UTC. Por ejemplo, puede suponer que una hora ambigua siempre se expresa en la hora estándar de la zona horaria.

En este tema se muestra cómo permitir a un usuario resolver una hora ambigua.

Para permitir a un usuario resolver una hora ambigua

  1. Obtenga la entrada de fecha y hora del usuario.

  2. Llame al método IsAmbiguousTime para determinar si la hora es ambigua.

  3. Si la hora es ambigua, llame al método GetAmbiguousTimeOffsets para recuperar una matriz de objetos TimeSpan. Cada elemento de la matriz contiene una diferencia respecto a la hora UTC a la que puede ser asignada la hora ambigua.

  4. Permita al usuario seleccionar la diferencia deseada.

  5. Obtenga la fecha y hora UTC restando a la hora local la diferencia seleccionada por el usuario.

  6. Llame al método SpecifyKind static (Shared en Visual Basic .NET) para establecer la propiedad Kind del valor de fecha y hora UTC en DateTimeKind.Utc.

Ejemplo

En el ejemplo siguiente se pide al usuario que escriba un valor de fecha y hora y, si la hora es ambigua, le permite seleccionar la hora UTC a la que se asignará esta hora 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;        
}

El núcleo del código de ejemplo utiliza una matriz de objetos TimeSpan para indicar las posibles diferencias de la hora ambigua respecto a la hora UTC. Sin embargo, probablemente estas diferencias no resultan significativas para el usuario. Para aclarar el significado de las diferencias, el código también indica si una diferencia representa la hora estándar de la zona horaria local o del horario de verano. El código determina qué hora es la estándar y cuál pertenece al horario de verano comparando la diferencia con el valor de la propiedad BaseUtcOffset. Esta propiedad indica la diferencia entre la hora UTC y la hora estándar de la zona horaria.

En este ejemplo, todas las referencias a la zona horaria local se realizan a través de la propiedad TimeZoneInfo.Local; la zona horaria local nunca se asigna a una variable de objeto. Este es un procedimiento recomendado porque una llamada al método TimeZoneInfo.ClearCachedData invalida todos los objetos a los que la zona horaria local está asignada.

Compilar el código

Para este ejemplo se necesita:

  • Que se agregue al proyecto una referencia a System.Core.dll.

  • Que se importe el espacio de nombres System con la instrucción using (necesaria en código de C#).

Vea también

Tareas

Cómo: Resolver horas ambiguas

Otros recursos

Fechas, horas y zonas horarias