it-swarm-pt.tech

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 deve ser usado em qual cenário?

192
Slavo

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 DateTime.Now sempre que você estivesse exibindo uma data para um ser humano - dessa forma, eles estão confortáveis ​​com o valor que veem - é algo que eles podem comparar facilmente ao que vêem em seu relógio ou relógio. Use DateTime.UtcNow quando quiser armazenar datas ou usá-las para cálculos posteriores dessa maneira (em um modelo cliente-servidor) seus cálculos não se tornam confusos por clientes em diferentes fusos horários do seu servidor ou uns dos outros.

306
Blair Conrad

É 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 3 PM hora do sistema ou do servidor, quando realmente aconteceu em 5 PM onde eles vivem.

Usamos DateTime.UtcNow porque temos um público global na web e porque preferimos não incomodar todos os usuários para preencher um formulário indicando em que fuso horário eles vivem.

Nós também exibimos 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.

80
Jeff Atwood

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.

29
Magnus Krisell

Um conceito principal para entender em .NET é que agora é agora all não importa em que fuso horário você está. Portanto, se você carregar uma variável com DateTime.Now ou DateTime.UtcNow - a atribuição é idêntica. * Seu objeto DateTime sabe em que fuso horário você está e leva isso em consideração, 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 um post no blog eu escrevi que explica ainda mais TimeSpan, e inclui um link para um artigo MS ainda mais extenso sobre o tópico.

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

26
Carl Camera

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

Internamente, a data é armazenada como Ticks, 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 Ticks para um valor baseado em GMT. Também define Kind para Utc.

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

Se você estiver 6 horas atrasado (GMT-6), você terá o tempo GMT de 6 horas atrás. O .net na verdade ignora Kind e trata este tempo como se fosse 6 horas atrás, mesmo que seja suposto ser "agora". Isso quebra ainda mais se você criar uma instância DateTime, em seguida, alterar seu fuso horário e tentar usá-lo.

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 <now" deveria ter sido verdade (até adicionei uma hora para ter certeza), mas ainda era falso.

Você também pode ver o 'trabalho em volta', que é simplesmente converter para a hora universal em qualquer lugar que Kind não seja 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 objetos DateTime que tenham Kind=Utc, exceto durante a i/o (exibição e análise). Isso significa que você deve estar quase sempre usando DateTime.UtcNow, exceto nos casos em que você está criando o objeto apenas para exibi-lo e descartá-lo imediatamente.

14
Ted Bigham

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 compatíveis com o 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.

6
Omer van Kloeten

A resposta "simples" para a pergunta é:

DateTime.Now retorna um DateTime valor 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 DateTime valor representando 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

4
PapillonUK

Apenas uma pequena adição 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, também influencia o modo como os métodos ToUniversalTime () e ToLocalTime () funcionam.

4
Jan Zich
2
Sorin Comanescu

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.

1
user1315023

DateTime.UtcNow é uma escala de tempo universal que omite o horário de verão. Então, o UTC nunca muda devido ao horário de verão.

Mas, DateTime.Now não é contínuo ou de valor único porque muda de acordo com o horário de verão. O que significa DateTime.Now, o mesmo valor de tempo pode ocorrer duas vezes deixando os clientes em um estado confuso.

1
ChaiVan

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

Apenas lembre-se, para um site é a configuração do fuso horário do servidor. Portanto, se você está exibindo o horário para o usuário, obtenha o fuso horário preferido e mude o horário (apenas salve o tempo do Utc no banco de dados e modifique-o) ou especifique o UTC. Se você esquecer de fazer isso, o usuário pode ver algo como: postado 3 minus ago e, em seguida, uma hora no futuro perto dele :)

0
kender