Convertendo Horários entre Zonas de Tempo
Está ficando cada vez mais importante para qualquer aplicativo que funciona com datas e horas manipular diferenças entre fusos horários. Um aplicativo não pode assumir que todos os horários podem ser expressos na hora local, que é o tempo disponível a partir da estrutura DateTime. Por exemplo, um página da Web que exibe a hora atual na parte do leste das Estados Unidos não terá credibilidade para um cliente no leste da Ásia. Este tópico explica como converter horas de uma zona de tempo para outra, bem como converter valores DateTimeOffset que tem limitada percepção de zona de tempo.
Convertendo para Tempo Universal Coordenado
Tempo Universal Coordenado (UTC) é um padrão de tempo atômico de alta precisão. Os Fusos horários do mundo são expressos em deslocamentos Positivos ou Negativos do UTC. Assim, o UTC fornece um tipo livre de fuso horário ou tempo neutro de fuso horário. O uso de hora UTC é recomendado quando a portabilidade de uma data e de um tempo entre computadores é importante. (Para Detalhes e as melhores práticas usando datas e horas, consulte Práticas de codificação recomendadas usando DateTime no .NET Framework.) Convertendo fusos horários individuais em UTC facilita as comparações de tempo.
Observação
Você também pode serializar uma estrutura DateTimeOffset para representar de forma não ambígua um único ponto no tempo.Devido aos objetos DateTimeOffset armazenarem valores de data e de tempo junto com seu deslocamento do UTC, eles sempre representam um ponto específico no tempo em relação ao UTC.
A maneira mais fácil para converter um horário para UTC é chamar o método static (Shared no Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime). A conversão exata executada pelo método depende do valor d propriedade dateTime Parâmetro da Kind, como mostra a tabela a seguir.
Propriedade DateTime.Kind |
Conversão |
---|---|
Converte a hora local em UTC. |
|
Assume que o parâmetro dateTime é a hora local e converte a hora local para UTC. |
|
Retorna o parâmetro dateTime inalterado. |
O código a seguir converte o horário local atual para UTC e exibe o resultado no console.
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
TimeZoneInfo.ConvertTimeToUtc(dateNow))
DateTime dateNow = DateTime.Now;
Console.WriteLine("The date and time are {0} UTC.",
TimeZoneInfo.ConvertTimeToUtc(dateNow));
Observação
O método TimeZoneInfo.ConvertTimeToUtc(DateTime) não necessariamente produz resultados que são idênticos aos métodos TimeZone.ToUniversalTime e DateTime.ToUniversalTime.Se a zona de tempo local do sistema host incluir várias regras de ajuste, TimeZoneInfo.ConvertTimeToUtc(DateTime) se aplicará a regra apropriada para uma determinada data e hora.Os outros dois métodos sempre aplicam a regra mais recente de ajuste.
Se o valor de data e tempo não representarem o horário local ou UTC, o método ToUniversalTime provavelmente irá retornar um resultado errado. No entanto, você pode usar o método TimeZoneInfo.ConvertTimeToUtc para converter a data e hora de uma zona de tempo especificada. (Para obter detalhes sobre como recuperar um objeto TimeZoneInfo que representa o fuso horário de destino, consulte Localizando as Zonas de Tempo Definidas em um Sistema Local.) O código a seguir usa a TimeZoneInfo.ConvertTimeToUtc método para converter a hora padrão do Leste para UTC.
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
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);
}
Observe que este método gera uma ArgumentException se a propriedade DateTime do objeto Kind e a zona de tempo são incompatíveis. Uma incompatibilidade ocorre se a propriedade Kind é DateTimeKind.Local, mas o objeto TimeZoneInfo não representa a zona de tempo local, ou se a propriedade Kind é DateTimeKind.Utc, mas o objeto TimeZoneInfo não é igual a DateTimeKind.Utc.
Todos esses métodos tomam valores DateTime como parâmetros e retornam um valor DateTime. Para valores DateTimeOffset, a estrutura DateTimeOffset possui um método de instância ToUniversalTime que converte a data e hora da instância atual em UTC. O exemplo a seguir chama o método ToUniversalTime para converter uma hora local e várias outras horas em Tempo Universal Coordenado (UTC).
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
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
Convertendo UTC em um fuso horário Designado
Para converter UTC em horário local, consulte a seção " Converter UTC para hora local " que segue. Para converter UTC para a hora em qualquer zona de tempo que você designar, chame o método ConvertTimeFromUtc. O método utiliza dois parâmetros:
O UTC a ser convertido. Isso deve ser um valor DateTime cuja propriedade Kind é definida como DateTimeKind.Utc ou DateTimeKind.Unspecified.
A zona de tempo em que o UTC será convertido.
O código a seguir converte UTC para a Hora padrão Central.
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
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.");
}
Convertendo UTC em horário local
Para converter UTC para hora local, chame o método ToLocalTime do objeto DateTime cujo tempo você deseja converter. O comportamento exato do método depende do valor da propriedade Kind do objeto, como mostra a tabela a seguir.
Propriedade DateTime.Kind |
Conversão |
---|---|
DateTimeKind.Local |
Retorna o valor DateTime inalterado. |
DateTimeKind.Unspecified |
Pressupõe que o DateTime o valor é o UTC e converte o UTC para a hora local. |
DateTimeKind.Utc |
Converte o valor DateTime em horário local. |
Observação O método TimeZone.ToLocalTime se comporta de forma idêntica ao método DateTime.ToLocalTime. Leva um único parâmetro, que é o valor de data e tempo a ser convertido.
Você também pode converter a hora em qualquer zona de tempo designada em horário local usando o método static (Shared no Visual Basic) TimeZoneInfo.ConvertTime. Essa técnica é abordada na próxima seção.
Convertendo entre qualquer dois fusos horários
Você pode converter entre quaisquer dois fusos horários usando qualquer um dos dois seguintes métodos static (Shared no Visual Basic) da classe TimeZoneInfo:
-
Esses parâmetros do método são o valor de data e tempo a ser convertido, um objeto TimeZoneInfo que representa a zona de tempo do valor de data e tempo e um objeto TimeZoneInfo que representa a zona de tempo da qual o valor de data e hora será convertido.
-
Esses parâmetros do método são os valores de data e hora a sere convertidos, o identificador da zona de tempo do valor de data e hora, e o identificador da zona de tempo para converter o valor de data e hora.
Ambos os métodos necessitam que a propriedade Kind do valor de data e hora a ser convertido e um objeto TimeZoneInfo ou identificador de zona de tempo que representa que sua zona de tempo corresponde uma com a outra. Caso contrário, uma ArgumentException é lançada. Por exemplo, se a propriedade Kind de valor de data e tempo for DateTimeKind.Local, será lançada uma exceção se o objeto TimeZoneInfo passado como um parâmetro para o método não for igual a TimeZoneInfo.Local. Também será apresentada uma exceção se o identificador passado como um parâmetro para o método não for igual a TimeZoneInfo.Local.Id.
O exemplo a seguir usa o método ConvertTime para converter da hora oficial do Havaí para a hora local.
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
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.");
}
Convertendo valores DateTimeOffset
Valores de data e hora representados pelos objetos DateTimeOffset não apresentam total percepção de fuso horário porque o objeto é desassociado de sua zona de tempo no momento em que ele é instanciado. No entanto, em muitos casos, um aplicativo simplesmente precisa converter uma data e hora com base em dois deslocamentos diferentes do UTC em vez de um tempo em determinados fusos horários. Para executar esta conversão, você pode chamar o método ToOffset da instância atual. O método de parâmetro único é o deslocamento de um novo valor de data e hora que o método deverá retornar.
Por exemplo, se a data e hora de uma solicitação do usuário para um página da Web é conhecida e é serializada como uma sequência de caracteres no formato DD/MM/DD HH: MM: SS zzzz, o seguinte método ReturnTimeOnServer converte esse valor de data e hora para a data e hora no servidor Web.
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
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;
}
}
Se o método é passado a string "1/9/2007 5: 32: 07-05: 00", que representa a data e hora em um fuso horário anteriores ao UTC de cinco horas, ele retorna 1/9/2007 3:32:07 AM-07: 00 para um servidor localizado nos EUA. Fuso de horário padrão do Pacífico.
A classe TimeZoneInfo também inclui uma sobrecarga do método TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) que realiza conversões de tempo com valores DateTimeOffset. Os parâmetros do método são um valor DateTimeOffset e uma referência para a zona de tempo para a qual o tempo deverá ser convertido. A chamada do método retorna um valor DateTimeOffset. Por exemplo, o método ReturnTimeOnServer no exemplo anterior poderia ser reescrito da seguinte maneira para chamar o método ConvertTime(DateTimeOffset, TimeZoneInfo).
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
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;
}
}
Consulte também
Referência
Conceitos
Localizando as Zonas de Tempo Definidas em um Sistema Local