DateTime.Now vs. DateTime.UtcNow

Eu tenho me perguntado quais são exatamente os princípios de como as duas propriedades funcionam. Eu sei que o segundo é universal e basicamente não lida com fusos horários, mas alguém pode explicar em detalhes como eles funcionam e qual deles deve ser usado em qual cenário?

O DateTime.UtcNow informa a data e a hora como seria no Tempo Universal Coordenado, que também é chamado de fuso horário do Greenwich Mean Time – basicamente como seria se você estivesse em Londres, Inglaterra, mas não durante o verão. DateTime.Now fornece a data e a hora como apareceria para alguém em sua localidade atual.

Eu recomendaria usar o DateTime.Now sempre que você estivesse exibindo uma data para um ser humano – assim eles ficariam confortáveis ​​com o valor que vêem – é algo que eles podem facilmente comparar ao que vêem no relógio ou no relógio. Use DateTime.UtcNow quando quiser armazenar datas ou usá-las para cálculos posteriores assim (em um modelo cliente-servidor) seus cálculos não se tornarão confusos por clientes em diferentes fusos horários do seu servidor ou uns dos outros.

É realmente muito simples, então acho que depende do que o seu público é e onde eles moram.

Se você não usa o Utc, você deve saber o fuso horário da pessoa que está exibindo datas e horários – caso contrário, você dirá a eles que algo aconteceu às 15h no horário do sistema ou do servidor, quando realmente aconteceu às 17h, onde eles acontecem a viver.

Usamos DateTime.UtcNow porque temos uma audiência global na web e porque eu prefiro não incomodar todos os usuários para preencher um formulário indicando em que fuso horário eles vivem.

Nós também mostramos os tempos relativos (2 horas atrás, 1 dia atrás, etc) até que o post envelheça o suficiente para que o tempo seja “o mesmo” não importando onde você mora na Terra.

Um conceito principal para entender em .NET é que agora está em todo o mundo, não importa em que fuso horário você esteja. Portanto, se você carregar uma variável com DateTime.Now ou DateTime.UtcNow – a atribuição é idêntica. * Your DateTime O object sabe em que fuso horário você está e leva isso em conta, independentemente da atribuição.

A utilidade de DateTime.UtcNow é útil ao calcular datas nos limites do horário de verão. Ou seja, em locais que participam do horário de verão, às vezes há 25 horas do meio-dia ao meio-dia do dia seguinte e, às vezes, há 23 horas entre o meio-dia e o meio-dia do dia seguinte. Se você quiser determinar corretamente o número de horas do tempo A e do tempo B, primeiro é necessário converter cada um para seus equivalentes UTC antes de calcular o TimeSpan.

Isto é coberto por uma postagem no blog que eu escrevi que explica ainda mais o TimeSpan, e inclui um link para um artigo da MS ainda mais extenso sobre o tópico.

* Esclarecimento: qualquer atribuição armazenará a hora atual. Se você tivesse que carregar duas variables ​​uma via DateTime.Now () e outra via DateTime.UtcNow (), a diferença TimeSpan entre os dois seria milissegundos, não horas, presumindo que você está em um fuso horário de horas longe do GMT. Conforme observado abaixo, a impressão de seus valores de String exibiria strings diferentes.

Observe também a diferença de desempenho; O DateTime.UtcNow é algo em torno de 30 vezes mais rápido do que o DateTime.Now, porque internamente o DateTime.Now está fazendo muitos ajustes de fuso horário (você pode facilmente verificar isso com o Reflector).

Portanto, não use DateTime.Now para medições de tempo relativas.

Essa é uma boa pergunta. Estou revivendo-o para dar um pouco mais de detalhes sobre como o .Net se comporta com diferentes valores ‘Kind’. Como aponta @Jan Zich, na verdade é uma propriedade criticamente importante e é definida de maneira diferente, dependendo se você usa o Now ou o UtcNow.

Internamente, a data é armazenada como “Ticks”, o que (ao contrário da resposta da @Carl Camera) é diferente, dependendo se você usa Now ou UtcNow.

DateTime.UtcNow se comporta como outros idiomas. Define os Ticks para um valor baseado em GMT. Também define ‘Kind’ para ‘Utc’.

O DateTime.Now altera o valor dos Ticks para o que seria se fosse sua hora do dia no fuso horário GMT . Também define ‘Kind’ como ‘Local’.

Se você estiver 6 horas atrasado (GMT-6), você receberá o tempo GMT de 6 horas atrás. .Net na verdade ignora ‘Kind’ e trata desta vez como se fosse 6 horas atrás, mesmo que seja suposto ser “agora”. Isso quebra ainda mais se você criar uma instância DateTime, alterar seu fuso horário e tentar usá-la.

As instâncias de DateTime com diferentes valores ‘Kind’ não são compatíveis.

Vamos ver um código …

  DateTime utc = DateTime.UtcNow; DateTime now = DateTime.Now; Debug.Log (utc + " " + utc.Kind); // 05/20/2015 17:19:27 Utc Debug.Log (now + " " + now.Kind); // 05/20/2015 10:19:27 Local Debug.Log (utc.Ticks); // 635677391678617830 Debug.Log (now.Ticks); // 635677139678617840 now = now.AddHours(1); TimeSpan diff = utc - now; Debug.Log (diff); // 05:59:59.9999990 Debug.Log (utc < now); // false Debug.Log (utc == now); // false Debug.Log (utc > now); // true Debug.Log (utc.ToUniversalTime() < now.ToUniversalTime()); // true Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime()); // false Debug.Log (utc.ToUniversalTime() > now.ToUniversalTime()); // false Debug.Log (utc.ToUniversalTime() - now.ToUniversalTime()); // -01:00:00.0000010 

Como você pode ver aqui, comparações e funções matemáticas não são convertidas automaticamente para tempos compatíveis. O Timespan deveria ter sido quase uma hora, mas em vez disso era quase 6. “utc

Você também pode ver o ‘trabalho em volta’, que é simplesmente converter para a hora universal em qualquer lugar que ‘Kind’ não é o mesmo.

Minha resposta direta à pergunta está de acordo com a recomendação da resposta aceita sobre quando usar cada uma delas. Você deve sempre tentar trabalhar com objects DateTime que tenham Kind = Utc, exceto durante a i / o (exibição e análise). Isso significa que você quase sempre deve estar usando DateTime.UtcNow, exceto nos casos em que você está criando o object apenas para exibi-lo e descartá-lo imediatamente.

O DateTime não tem ideia de que fusos horários são. Ele sempre assume que você está no seu horário local. UtcNow significa apenas “Subtrair meu fuso horário do tempo”.

Se você quiser usar datas com reconhecimento de fuso horário, use DateTimeOffset , que representa uma data / hora com um fuso horário. Eu tive que aprender isso da maneira mais difícil.

Apenas um pequeno acréscimo aos pontos acima: a estrutura DateTime também contém um campo pouco conhecido chamado Kind (pelo menos, eu não sabia disso há muito tempo). É basicamente apenas uma bandeira indicando se a hora é local ou UTC; ele não especifica o deslocamento real do UTC para os horários locais. Além do fato de que indica com quais intenções o stuct foi construído, ele também influencia a maneira como os methods ToUniversalTime () e ToLocalTime () funcionam.

A resposta “simples” para a pergunta é:

DateTime.Now retorna um valor DateTime representando a hora atual do sistema (em qualquer fuso horário em que o sistema esteja sendo executado). A propriedade DateTime.Kind será DateTimeKind.Local

DateTime.UtcNow retorna um valor DateTime que representa o atual Tempo Coordenado Universal (também conhecido como UTC), que será o mesmo, independentemente do fuso horário do sistema. A propriedade DateTime.Kind será DateTimeKind.Utc

Um pouco atrasado para a festa, mas achei estes dois links (4guysfromrolla) muito úteis:

Usando o tempo universal coordenado (UTC) para armazenar valores de data / hora

Conselhos para armazenar e exibir datas e horários em diferentes fusos horários

DateTime.UtcNow é uma escala de tempo contínua e de valor único, enquanto DateTime.Now não é contínua ou de valor único. O principal motivo é o horário de verão, que não se aplica ao UTC. Assim, o UTC nunca salta para frente ou para trás uma hora, enquanto o horário local (DateTime.Now) faz. E quando ele salta para trás, o mesmo valor de tempo ocorre duas vezes.

Quando você precisar de um horário local para a máquina na qual seu aplicativo é executado (como o CEST para a Europa), use Now. Se você quer um tempo universal – UtcNow. É apenas uma questão de suas preferências – provavelmente criar um site local / aplicativo independente que você queira usar o tempo que o usuário tem – tão afetado por sua configuração de fuso horário – DateTime.Now.

Basta lembrar que, para um site, é a configuração de fuso horário do servidor. Portanto, se você estiver exibindo o horário para o usuário, obtenha o fuso horário preferido e altere o horário (apenas salve o tempo do Utc no database e modifique-o) ou especifique o UTC. Se você esquecer de fazer isso, o usuário pode ver algo como: postado 3 minutos atrás e, em seguida, uma hora no futuro perto dele 🙂