Criando um DateTime em um fuso horário específico em c #

Eu estou tentando criar um teste de unidade para testar o caso para quando o fuso horário muda em uma máquina porque ele foi definido incorretamente e, em seguida, corrigido.

No teste, preciso ser capaz de criar objects DateTime em um fuso horário local para garantir que as pessoas que executam o teste possam fazê-lo com êxito, independentemente de onde estejam localizadas.

Pelo que vejo do construtor DateTime, posso definir o fuso horário como o fuso horário local, o fuso horário UTC ou não especificado.

Como faço para criar um DateTime com um fuso horário específico como o PST?

A resposta de Jon fala sobre o TimeZone , mas eu sugiro usar o TimeZoneInfo .

Pessoalmente, gosto de manter as coisas no UTC sempre que possível, então sugiro uma estrutura como esta:

public struct DateTimeWithZone { private readonly DateTime utcDateTime; private readonly TimeZoneInfo timeZone; public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone) { var dateTimeUnspec = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified); utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTimeUnspec, timeZone); this.timeZone = timeZone; } public DateTime UniversalTime { get { return utcDateTime; } } public TimeZoneInfo TimeZone { get { return timeZone; } } public DateTime LocalTime { get { return TimeZoneInfo.ConvertTime(utcDateTime, timeZone); } } } 

Você pode querer mudar os nomes “TimeZone” para “TimeZoneInfo” para deixar as coisas mais claras – eu prefiro os nomes mais curtos eu mesmo.

A estrutura DateTimeOffset foi criada exatamente para esse tipo de uso.

Consulte: http://msdn.microsoft.com/pt-br/library/system.datetimeoffset.aspx

Aqui está um exemplo de criação de um object DateTimeOffset com um fuso horário específico:

DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));

As outras respostas aqui são úteis, mas elas não cobrem como acessar o Pacific especificamente – aqui você vai:

 public static DateTime GmtToPacific(DateTime dateTime) { return TimeZoneInfo.ConvertTimeFromUtc(dateTime, TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time")); } 

Estranhamente, embora “Hora Padrão do Pacífico” normalmente signifique algo diferente de “Hora do Pacífico”, neste caso ela se refere ao horário do Pacífico em geral. Na verdade, se você usar FindSystemTimeZoneById para FindSystemTimeZoneById -lo, uma das propriedades disponíveis é um bool informando se o fuso horário está atualmente no horário de verão ou não.

Você pode ver exemplos mais generalizados disso em uma biblioteca que acabei jogando juntos para lidar com DateTimes que eu preciso em diferentes fusos horários com base em onde o usuário está pedindo, etc:

https://github.com/b9chris/TimeZoneInfoLib.Net

Isso não funcionará fora do Windows (por exemplo, Mono no Linux), já que a lista de vezes vem do Registro do Windows: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\

Abaixo, você encontrará chaves (icons de pastas no Editor do Registro); os nomes dessas chaves são o que você passa para FindSystemTimeZoneById . No Linux, você precisa usar um conjunto separado de definições de fuso horário padrão do Linux, que eu não explorei adequadamente.

Eu alterei Jon Skeet responder um pouco pela web com o método de extensão. Ele também funciona em azul como um encanto.

 public static class DateTimeWithZone { private static readonly TimeZoneInfo timeZone; static DateTimeWithZone() { //I added web.config  //You can add value directly into function. timeZone = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["CurrentTimeZoneId"]); } public static DateTime LocalTime(this DateTime t) { return TimeZoneInfo.ConvertTime(t, timeZone); } } 

Você terá que criar um object personalizado para isso. Seu object personalizado conterá dois valores:

  • um valor de DateTime
  • um object TimeZone

Não tenho certeza se já existe um tipo de dados fornecido pelo CLR que tenha isso, mas pelo menos o componente TimeZone já está disponível.

Eu gosto da resposta de Jon Skeet, mas gostaria de acrescentar uma coisa. Não tenho certeza se Jon estava esperando que o ctor sempre fosse passado no fuso horário local. Mas eu quero usá-lo para casos em que é algo diferente do local.

Estou lendo valores de um database e sei em que fuso horário esse database está. Portanto, no ctor, transmitirei o fuso horário do database. Mas então eu gostaria do valor na hora local. O LocalTime de Jon não retorna a data original convertida em uma data de fuso horário local. Ele retorna a data convertida no fuso horário original (o que quer que você tenha passado para o ctor).

Eu acho que esses nomes de propriedade esclarecem …

 public DateTime TimeInOriginalZone { get { return TimeZoneInfo.ConvertTime(utcDateTime, timeZone); } } public DateTime TimeInLocalZone { get { return TimeZoneInfo.ConvertTime(utcDateTime, TimeZoneInfo.Local); } } public DateTime TimeInSpecificZone(TimeZoneInfo tz) { return TimeZoneInfo.ConvertTime(utcDateTime, tz); }