Convertir horas entre zonas horarias
Para cualquier aplicación que trabaje con fechas y horas se está volviendo cada vez más importante controlar las diferencias entre zonas horarias. Una aplicación ya no puede asumir que todas las horas se pueden expresar en la hora local, que es la hora disponible en la DateTime estructura . Por ejemplo, una página web que muestre la hora actual en la zona oriental de los Estados Unidos no tendrá credibilidad para un cliente de Asia oriental. En este tema se explica cómo convertir horas de una zona horaria a otra, así como cómo convertir valores que tienen un reconocimiento de DateTimeOffset zona horaria limitado.
Conversión a la 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 con respecto a la hora UTC. Por lo tanto, UTC proporciona un tipo de hora libre o neutra de zona horaria. Se recomienda el uso de la hora UTC cuando importa la portabilidad de la fecha y la hora entre equipos. (Para obtener más información y otros procedimientos recomendados que usan fechas y horas, consulte Codificación de procedimientos recomendados mediante DateTime en .NET Framework). La conversión de zonas horarias individuales a UTC facilita las comparaciones horarias.
Nota
También puede serializar una DateTimeOffset estructura para representar inequívocamente un único punto en el tiempo. Dado que los objetos almacenan un valor de fecha y hora junto con su desplazamiento con respecto a la hora UTC, siempre representan un momento determinado en relación DateTimeOffset con utc.
La manera más fácil de convertir una hora a UTC es llamar al static método ( Shared en TimeZoneInfo.ConvertTimeToUtc(DateTime) Visual Basic). La conversión exacta realizada por el método depende del valor de la propiedad dateTime del Kind parámetro, como se muestra en la tabla siguiente.
DateTime.Kind |
Conversión |
|---|---|
DateTimeKind.Local |
Convierte la hora local a UTC. |
DateTimeKind.Unspecified |
Supone que el parámetro dateTime es la hora local y la convierte a UTC. |
DateTimeKind.Utc |
Devuelve el parámetro dateTime sin modificar. |
El código siguiente convierte la hora local actual a UTC y muestra el resultado en la consola.
DateTime dateNow = DateTime.Now;
Console.WriteLine("The date and time are {0} UTC.",
TimeZoneInfo.ConvertTimeToUtc(dateNow));
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 método ToUniversalTime devuelva un resultado erróneo. Sin embargo, puede usar el método para convertir la fecha y hora TimeZoneInfo.ConvertTimeToUtc de una zona horaria especificada. (Para obtener más información sobre cómo recuperar un objeto que representa la zona horaria de destino, vea Búsqueda de las zonas horarias definidas TimeZoneInfo en un sistema local). El código siguiente usa el método para convertir la hora estándar del Este TimeZoneInfo.ConvertTimeToUtc 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 {0} UTC.",
TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone));
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("Unable to find the {0} zone in the registry.",
easternZoneId);
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the {0} zone has been corrupted.",
easternZoneId);
}
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
Tenga en cuenta que este método produce una excepción si la propiedad del objeto y la zona horaria no ArgumentException DateTime son Kind coincidentes. Se produce un error de coincidencia si la propiedad es pero el objeto no representa la zona horaria local, o si la propiedad es pero el objeto Kind no es igual a DateTimeKind.Local TimeZoneInfo Kind DateTimeKind.Utc TimeZoneInfo TimeZoneInfo.Utc .
Todos estos métodos toman DateTime valores como parámetros y devuelven un DateTime valor. Para los valores, la estructura tiene un método de instancia que convierte la fecha y hora DateTimeOffset de la instancia actual a DateTimeOffset ToUniversalTime UTC. En el ejemplo siguiente se llama al método para convertir una hora local y otras varias veces ToUniversalTime a la hora universal coordinada (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: {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
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
Conversión de una hora UTC a una zona horaria designada
Para convertir utc a hora local, consulte la sección "Conversión de UTC a hora local" que se muestra a continuación. Para convertir utc a la hora de cualquier zona horaria que designe, llame al ConvertTimeFromUtc método . El método toma dos parámetros:
La hora UTC que se va a convertir. Debe ser un DateTime valor cuya propiedad esté establecida en o Kind
UnspecifiedUtc.La zona horaria a la que se va a convertir la hora UTC.
El código siguiente convierte la hora UTC a la 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 una hora UTC a la hora local
Para convertir utc a hora local, llame al ToLocalTime método del objeto cuya hora desea DateTime 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 a la hora local. |
DateTimeKind.Utc |
Convierte el valor DateTime a la hora local. |
Nota
El TimeZone.ToLocalTime método se comporta de forma idéntica al método DateTime.ToLocalTime . Toma un único parámetro, que es el valor de fecha y hora que se va a convertir.
También puede convertir la hora de cualquier zona horaria designada a la hora local mediante el método static ( Shared en TimeZoneInfo.ConvertTime Visual Basic). Esta técnica se describe en la sección siguiente.
Conversión entre dos zonas horarias cualquiera
Puede convertir entre dos zonas horarias cualquiera mediante cualquiera de los dos métodos siguientes static Shared (en Visual Basic) de la TimeZoneInfo clase :
-
Los parámetros de este método son el valor de fecha y hora que se va a convertir, un objeto que representa la zona horaria del valor de fecha y hora y un objeto que representa la zona horaria a la que se va a convertir el valor de fecha y
TimeZoneInfoTimeZoneInfohora. -
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 en la que se va a convertir el valor de fecha y hora.
Ambos métodos requieren que la propiedad del valor de fecha y hora que se convertirá y el objeto o identificador de zona horaria que representa su zona horaria Kind TimeZoneInfo se correspondan entre sí. De lo contrario, se produce una excepción ArgumentException. Por ejemplo, si la propiedad del valor de fecha y hora es , se produce una excepción si el objeto pasado como parámetro al método Kind no es igual a DateTimeKind.Local TimeZoneInfo 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 método para convertir la hora ConvertTime estándar de Hawái a la 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 objetos no son totalmente conscientes de la zona horaria porque el objeto está desasociado de su zona horaria en el momento en que se DateTimeOffset crea una instancia de él. Pero en muchos casos una aplicación simplemente necesita convertir una fecha y hora basada en dos diferencias horarias diferentes con respecto a la hora UTC en lugar de en la hora en zonas horarias determinadas. Para realizar esta conversión, puede llamar al método de la instancia ToOffset actual. El parámetro único del método es el desplazamiento del nuevo valor de fecha y hora que va a devolver el método.
Por ejemplo, si la fecha y hora de una solicitud de usuario de una página web se conoce y se serializa como una cadena con el formato MM/dd/aaaa hh: mm:ss zzzz, el siguiente método ReturnTimeOnServer convierte este valor de fecha y hora en la fecha y hora del 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 se pasa al método la cadena "9/1/2007 5:32:07 -05:00", que representa la fecha y hora de una zona horaria cinco horas antes de 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 método que realiza conversiones de zona horaria con valores TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) ToOffset(TimeSpan) . Los parámetros del método son un valor y una referencia a la zona horaria a la que se va DateTimeOffset a convertir la hora. La llamada al método devuelve un DateTimeOffset valor . Por ejemplo, el método del ejemplo anterior podría reescribirse como ReturnTimeOnServer se muestra a continuación para llamar al método ConvertTime(DateTimeOffset, TimeZoneInfo) .
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