Comparteix a través de


Convertir horas entre zonas horarias

Es cada vez más importante para cualquier aplicación que funcione con fechas y horas para controlar las diferencias entre las zonas horarias. Una aplicación ya no puede suponer que todos los tiempos se pueden expresar en la zona horaria local, que es la disponible en la estructura DateTime. Por ejemplo, una página web que muestre la hora actual en la parte oriental de los Estados Unidos carecerá de credibilidad para un cliente en Asia oriental. En este artículo se explica cómo convertir horas de una zona horaria a otra y convertir DateTimeOffset valores que tienen un reconocimiento de zona horaria limitado.

Conversión a hora universal coordinada

La hora universal coordinada (UTC) es un estándar de hora atómica de alta precisión. Las zonas horarias del mundo se expresan como desplazamientos positivos o negativos de UTC. Por lo tanto, UTC proporciona una hora sin zona horaria o una hora neutra de zona horaria. El uso de UTC se recomienda cuando es importante la portabilidad de una fecha y hora entre equipos. Para más información y otros procedimientos recomendados con fechas y horas, consulte Procedimientos recomendados de codificación mediante DateTime en .NET Framework. La conversión de zonas horarias individuales a UTC facilita las comparaciones de hora.

Nota:

También puede serializar una DateTimeOffset estructura para representar un único punto en el tiempo de forma inequívoca. Dado que DateTimeOffset los objetos almacenan un valor de fecha y hora junto con su desplazamiento desde UTC, siempre representan un momento dado en relación con utc.

La manera más fácil de convertir una hora a UTC es llamar al método staticShared en Visual Basic TimeZoneInfo.ConvertTimeToUtc(DateTime). La conversión exacta realizada por el método depende del valor de la dateTime propiedad del Kind parámetro, como se muestra en la tabla siguiente:

DateTime.Kind Conversión
DateTimeKind.Local Convierte la hora local en UTC.
DateTimeKind.Unspecified Supone que el dateTime parámetro es hora local y convierte la hora local en UTC.
DateTimeKind.Utc Devuelve el dateTime parámetro sin cambios.

El código siguiente convierte la hora local actual en UTC y muestra el resultado en la consola:

DateTime dateNow = DateTime.Now;
Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(dateNow)} UTC.");
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
                  TimeZoneInfo.ConvertTimeToUtc(dateNow))

Si el valor de fecha y hora no representa la hora local o UTC, es probable que el ToUniversalTime método devuelva un resultado erróneo. Sin embargo, puede usar el TimeZoneInfo.ConvertTimeToUtc método para convertir la fecha y hora de una zona horaria especificada. Para obtener más información sobre cómo recuperar un TimeZoneInfo objeto que representa la zona horaria de destino, consulte Búsqueda de las zonas horarias definidas en un sistema local. El código siguiente usa el método TimeZoneInfo.ConvertTimeToUtc para convertir la Hora Estándar del Este a UTC.

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00);
string easternZoneId = "Eastern Standard Time";
try
{
    TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
    Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)} UTC.");
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine($"Unable to find the {easternZoneId} zone in the registry.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine($"Registry data on the {easternZoneId} zone has been corrupted.");
}
Dim easternTime As New Date(2007, 01, 02, 12, 16, 00)
Dim easternZoneId As String = "Eastern Standard Time"
Try
    Dim easternZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId)
    Console.WriteLine("The date and time are {0} UTC.", _
                      TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("Unable to find the {0} zone in the registry.", _
                      easternZoneId)
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the {0} zone has been corrupted.", _
                      easternZoneId)
End Try

El método TimeZoneInfo.ConvertTimeToUtc arroja un ArgumentException si la propiedad Kind del objeto DateTime y la zona horaria no coinciden. Se produce una falta de coincidencia si la propiedad Kind es DateTimeKind.Local, pero el objeto TimeZoneInfo no representa la zona horaria local, o si la propiedad Kind es DateTimeKind.Utc, pero el objeto TimeZoneInfo no es igual a TimeZoneInfo.Utc.

Todos estos métodos toman DateTime valores como parámetros y devuelven un DateTime valor. Para los valores de DateTimeOffset, la estructura DateTimeOffset tiene un método de instancia ToUniversalTime que convierte la fecha y hora actuales de la instancia a UTC. En el ejemplo siguiente, se llama al método ToUniversalTime para convertir una hora local y varias otras horas a UTC.

DateTimeOffset localTime, otherTime, universalTime;

// Define local time in local time zone
localTime = new DateTimeOffset(new DateTime(2007, 6, 15, 12, 0, 0));
Console.WriteLine($"Local time: {localTime}");
Console.WriteLine();

// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine($"Other time: {otherTime}");
Console.WriteLine($"{localTime} = {otherTime}: {localTime.Equals(otherTime)}");
Console.WriteLine($"{localTime} exactly equals {otherTime}: {localTime.EqualsExact(otherTime)}");
Console.WriteLine();

// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine($"Universal time: {universalTime}");
Console.WriteLine($"{otherTime} = {universalTime}: {universalTime.Equals(otherTime)}");
Console.WriteLine($"{otherTime} exactly equals {universalTime}: {universalTime.EqualsExact(otherTime)}");
Console.WriteLine();

// The example produces the following output to the console:
//    Local time: 6/15/2007 12:00:00 PM -07:00
//
//    Other time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
//
//    Universal time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True
Dim localTime, otherTime, universalTime As DateTimeOffset

' Define local time in local time zone
localTime = New DateTimeOffset(#6/15/2007 12:00:00PM#)
Console.WriteLine("Local time: {0}", localTime)
Console.WriteLine()

' Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero)
Console.WriteLine("Other time: {0}", otherTime)
Console.WriteLine("{0} = {1}: {2}", _
                  localTime, otherTime, _
                  localTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  localTime, otherTime, _
                  localTime.EqualsExact(otherTime))
Console.WriteLine()

' Convert other time to UTC
universalTime = localTime.ToUniversalTime()
Console.WriteLine("Universal time: {0}", universalTime)
Console.WriteLine("{0} = {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.EqualsExact(otherTime))
Console.WriteLine()
' The example produces the following output to the console:
'    Local time: 6/15/2007 12:00:00 PM -07:00
'    
'    Other time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
'    
'    Universal time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True   

Convertir UTC en una zona horaria designada

Para convertir UTC a hora local, consulte la sección Conversión de UTC a hora local siguiente. Para convertir UTC a la hora en cualquier zona horaria que designe, llame al método ConvertTimeFromUtc. El método toma dos parámetros:

  • Hora UTC que se va a convertir. Debe ser un DateTime valor cuya Kind propiedad está establecida en Unspecified o Utc.

  • La zona horaria a la que convertir UTC.

El código siguiente convierte UTC a Hora estándar central:

DateTime timeUtc = DateTime.UtcNow;
try
{
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    Console.WriteLine("The date and time are {0} {1}.",
                      cstTime,
                      cstZone.IsDaylightSavingTime(cstTime) ?
                              cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}
Dim timeUtc As Date = Date.UtcNow
Try
    Dim cstZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
    Dim cstTime As Date = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone)
    Console.WriteLine("The date and time are {0} {1}.", _
                      cstTime, _
                      IIf(cstZone.IsDaylightSavingTime(cstTime), _
                          cstZone.DaylightName, cstZone.StandardName))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Central Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.")
End Try

Conversión de UTC a hora local

Para convertir UTC a hora local, llame al ToLocalTime método del DateTime objeto cuya hora desea convertir. El comportamiento exacto del método depende del valor de la propiedad del Kind objeto, como se muestra en la tabla siguiente:

DateTime.Kind Conversión
DateTimeKind.Local Devuelve el DateTime valor sin cambios.
DateTimeKind.Unspecified Supone que el DateTime valor es UTC y convierte la hora UTC en hora local.
DateTimeKind.Utc Convierte el DateTime valor en hora local.

Nota:

El TimeZone.ToLocalTime método se comporta de forma idéntica al DateTime.ToLocalTime método . Toma un único parámetro, que es el valor de fecha y hora, para convertir.

También puede convertir la hora en cualquier zona horaria designada a hora local mediante el static método (Shared en Visual Basic). TimeZoneInfo.ConvertTime Esta técnica se describe en la sección siguiente.

Conversión entre dos zonas horarias

Puede convertir entre dos zonas horarias mediante cualquiera de los dos static métodos siguientes (Shared en Visual Basic) de la TimeZoneInfo clase :

  • ConvertTime

    Los parámetros de este método son el valor de fecha y hora que se va a convertir, un TimeZoneInfo objeto que representa la zona horaria del valor de fecha y hora, y un TimeZoneInfo objeto que representa la zona horaria a la que se va a convertir el valor de fecha y hora.

  • ConvertTimeBySystemTimeZoneId

    Los parámetros de este método son el valor de fecha y hora que se va a convertir, el identificador de la zona horaria del valor de fecha y hora, y el identificador de la zona horaria a la que se va a convertir el valor de fecha y hora.

Ambos métodos requieren que la Kind propiedad del valor de fecha y hora se convierta y el objeto o identificador TimeZoneInfo de zona horaria que represente su zona horaria se correspondan entre sí. De lo contrario, se produce una excepción ArgumentException. Por ejemplo, si la Kind propiedad del valor de fecha y hora es DateTimeKind.Local, se produce una excepción si el TimeZoneInfo objeto pasado como parámetro al método no es igual a TimeZoneInfo.Local. También se produce una excepción si el identificador pasado como parámetro al método no es igual a TimeZoneInfo.Local.Id.

En el ejemplo siguiente se usa el ConvertTime método para convertir de hora estándar hawaiana a hora local:

DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
    TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
    Console.WriteLine("{0} {1} is {2} local time.",
            hwTime,
            hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName,
            TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local));
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.");
}
Dim hwTime As Date = #2/01/2007 8:00:00 AM#
Try
    Dim hwZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time")
    Console.WriteLine("{0} {1} is {2} local time.", _
                      hwTime, _
                      IIf(hwZone.IsDaylightSavingTime(hwTime), hwZone.DaylightName, hwZone.StandardName), _
                      TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.")
End Try

Conversión de valores DateTimeOffset

Los valores de fecha y hora representados por DateTimeOffset objetos no tienen plena conciencia de la zona horaria porque el objeto está desvinculado de su zona horaria al momento de su creación. Sin embargo, en muchos casos, una aplicación simplemente necesita convertir una fecha y hora en función de dos desplazamientos diferentes de UTC en lugar de en la hora en determinadas zonas horarias. Para realizar esta conversión, puede llamar al método ToOffset de la instancia actual. El parámetro único del método es el desplazamiento del nuevo valor de fecha y hora que devolverá el método.

Por ejemplo, si se conoce la fecha y hora de una solicitud de usuario para una página web y se serializa como una cadena con el formato MM/dd/aaaa hh:mm:ss zzzz, el método siguiente ReturnTimeOnServer convierte este valor de fecha y hora en la fecha y hora en el servidor web:

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";
   TimeSpan serverOffset = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now);

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = clientTime.ToOffset(serverOffset);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"
    Dim serverOffset As TimeSpan = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now)

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = clientTime.ToOffset(serverOffset)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Si el método pasa la cadena "9/1/2007 5:32:07 -05:00", que representa la fecha y hora en una zona horaria cinco horas anteriores a utc, devuelve "9/1/2007 3:32:07 AM -07:00" para un servidor ubicado en la zona horaria estándar del Pacífico de EE. UU.

La TimeZoneInfo clase también incluye una sobrecarga del TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) método que realiza conversiones de zona horaria con ToOffset(TimeSpan) valores. Los parámetros del método son un DateTimeOffset valor y una referencia a la zona horaria a la que se va a convertir la hora. La llamada al método devuelve un DateTimeOffset valor. Por ejemplo, el ReturnTimeOnServer método del ejemplo anterior podría volver a escribirse como se indica a continuación para llamar al ConvertTime(DateTimeOffset, TimeZoneInfo) método .

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format,
                                  CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = TimeZoneInfo.ConvertTime(clientTime,
                                  TimeZoneInfo.Local);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Consulte también