Obter fuso horário de DateTime

103

O .Net DateTime contém informações sobre o fuso horário onde foi criado?

Eu tenho uma biblioteca que analisa DateTime de um formato que tem "+ zz" no final e, embora ela analise corretamente e ajuste a hora local, preciso saber qual era o fuso horário específico do objeto DateTime.

Isso é possível em tudo? Tudo o que posso ver é DateTime.Kind, que especifica se a hora é local ou UTC.

dbkk
fonte
Consulte as notas na documentação DateTime.Parse para lidar com fusos horários e DateTimeStyles. Mas não, o que você quer não é realmente possível.
yoyo

Respostas:

136

DateTime em si não contém informações de fuso horário real. Ele pode saber se é UTC ou local, mas não o que local realmente significa.

DateTimeOffset é um pouco melhor - basicamente uma hora UTC e um deslocamento. No entanto, isso ainda não é realmente o suficiente para determinar o fuso horário, já que muitos fusos horários diferentes podem ter o mesmo deslocamento em qualquer momento. No entanto, parece que pode ser bom o suficiente para você, já que tudo o que você precisa fazer ao analisar a data / hora é o deslocamento.

O suporte para fusos horários a partir do .NET 3.5 é muito melhor do que antes, mas eu realmente gostaria de ver um "ZonedDateTime" padrão ou algo parecido - um horário UTC e um fuso horário real. É fácil construir o seu próprio, mas seria bom vê-lo nas bibliotecas padrão.

EDIT: Quase quatro anos depois, eu agora sugiro usar o Noda Time, que tem um conjunto mais rico de tipos de data / hora. No entanto, sou tendencioso, como autor principal de Noda Time :)

Jon Skeet
fonte
2
O projeto PublicDomain no CodePlex faz isso por você.
Cheeso
Um enum TimeZone no BCL seria bom se os fusos horários mundiais fossem estáticos e não mudassem.
Jeff LaFay
1
@jlafay: No entanto, eles mudam - mais fusos horários foram adicionados ao Windows no ano passado, por exemplo.
Jon Skeet de
Este projeto não é mais mantido pelo autor; publicdomain.codeplex.com Parece que talvez este possa ajudar, dependendo do uso, é preciso configurá-lo antes de usá-lo; timezone.codeplex.com
AnneTheAgile
3
@AnneTheAgile: Pessoalmente, eu recomendo usar minha própria biblioteca Noda Time, é claro :)
Jon Skeet
36

Não.

Um desenvolvedor é responsável por controlar as informações de fuso horário associadas a um valor DateTime por meio de algum mecanismo externo.

Uma citação de um excelente artigo aqui . Uma leitura obrigatória para cada desenvolvedor .Net.

Portanto, meu conselho é escrever uma pequena aula de wrapper que atenda às suas necessidades.

Gerrie Schenck
fonte
2

Você pode usar a classe TimeZoneInfo

A classe TimeZone reconhece o fuso horário local e pode converter os horários entre o Tempo Universal Coordenado (UTC) e o horário local. Um objeto TimeZoneInfo pode representar qualquer fuso horário e os métodos da classe TimeZoneInfo podem ser usados ​​para converter a hora em um fuso horário para a hora correspondente em qualquer outro fuso horário. Os membros da classe TimeZoneInfo suportam as seguintes operações:

  1. Recuperando um fuso horário já definido pelo sistema operacional.

  2. Enumerando os fusos horários disponíveis em um sistema.

  3. Conversão de horários entre diferentes fusos horários.

  4. Criar um novo fuso horário que ainda não foi definido pelo sistema operacional.

    Serializando um fuso horário para recuperação posterior.

Shekhar
fonte
1
... mas, dado um DateTime, ainda não há uma maneira de usar TimeZoneInfo para determinar o TimeZone de DateTime, que eu saiba.
Remi Despres-Smyth
@ RemiDespres-Smyth Acabei de armazenar TimeZoneInfo junto com DateTime em 1 classe.
Konrad
0

Geralmente, a prática seria passar os dados como DateTime com um "fuso horário" do UTC e, em seguida, passar um objeto TimeZoneInfo e, quando estiver pronto para exibir os dados, use o objeto TimeZoneInfo para converter o DateTime UTC.

A outra opção é definir DateTime com o fuso horário atual e, em seguida, certificar-se de que o "fuso horário" é desconhecido para o objeto DateTime e, em seguida, certificar-se de que DateTime seja passado novamente com um TimeZoneInfo que indica o fuso horário do DateTime passado.

Como outros indicaram aqui, seria bom se a Microsoft resolvesse isso e criasse um objeto legal para fazer tudo, mas por enquanto você tem que lidar com dois objetos.

Roubar
fonte
0

DateTime não sabe seu deslocamento de fuso horário. Não existe um método integrado para retornar o deslocamento ou o nome do fuso horário (por exemplo, EAT, CEST, EST etc).

Como sugerido por outros, você pode converter sua data para UTC:

DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();

e então apenas calcule a diferença:

TimeSpan difference = localtime - utctime;

Além disso, você pode converter uma hora para outra usando o DateTimeOffset:

DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));

Mas isso é um tipo de compactação com perdas - o deslocamento por si só não pode dizer qual fuso horário é, pois dois países diferentes podem estar em fusos horários diferentes e ter o mesmo tempo apenas durante parte do ano (por exemplo, África do Sul e Europa). Além disso, esteja ciente de que o horário de verão pode ser introduzido em datas diferentes (EST vs CET - uma diferença de 3 semanas).

Você pode obter o nome do fuso horário do sistema local usando a classe TimeZoneInfo:

TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName

Concordo com Gerrie Schenck, leia o artigo que ele sugeriu.

Henryalligator
fonte