Compartilhar via


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 obter detalhes e Outros práticas recomendadas usando datas e horários, consulte Codificando as práticas recomendadas usando DateTime no .NET estrutura.) Convertendo fusos horários individuais em UTC facilita as comparações de tempo.

Observação:

Você também pode serializar um DateTimeOffset estrutura de forma não ambígua representam um único ponto no time. 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

DateTimeKind.Local

Converte a hora local em UTC.

DateTimeKind.Unspecified

Assume que o parâmetro dateTime é a hora local e converte a hora local para UTC.

DateTimeKind.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:

T Ele TimeZoneInfo.ConvertTimeToUtc(DateTime) método necessariamente não produzem resultados idênticos do TimeZone.ToUniversalTime e DateTime.ToUniversalTime métodos. 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 o método TimeZoneInfo.ConvertTimeToUtc para converter hora oficial do leste dos EUA em 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 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

Assume que o parâmetro DateTime é a hora local e converte 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:

  • ConvertTime

    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.

  • ConvertTimeBySystemTimeZoneId

    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 seqüência de caracteres "1/9/2007 5:32:07-05: 00", que representa a data e time em um fuso horário anteriores ao UTC cinco horas, ele retorna 1/9/2007 3:32:07 AM-07: 00 para um servidor localizado nos Estados UnidosPadrão do Pacífico time zona.

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

Conceitos

Localizando as Zonas de Tempo Definidas em um Sistema Local

Referência

TimeZoneInfo

Outros recursos

Horários e Zonas de Tempo