Diferença entre System.DateTime.Now e System.DateTime.Today

127

Alguém pode explicar a diferença entre System.DateTime.Nowe System.DateTime.Todayno C # .NET? Prós e contras de cada um, se possível.

Samuel Liew
fonte

Respostas:

179

DateTime.Nowretorna um DateTimevalor que consiste na data e hora locais do computador em que o código está sendo executado. Foi DateTimeKind.Localatribuído à sua Kindpropriedade. É equivalente a chamar qualquer um dos seguintes:

  • DateTime.UtcNow.ToLocalTime()
  • DateTimeOffset.UtcNow.LocalDateTime
  • DateTimeOffset.Now.LocalDateTime
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)

DateTime.Todayretorna um DateTimevalor que possui os mesmos componentes de ano, mês e dia que qualquer uma das expressões acima, mas com os componentes de tempo definidos como zero. Ele também tem DateTimeKind.Localem sua Kindpropriedade. É equivalente a qualquer um dos seguintes:

  • DateTime.Now.Date
  • DateTime.UtcNow.ToLocalTime().Date
  • DateTimeOffset.UtcNow.LocalDateTime.Date
  • DateTimeOffset.Now.LocalDateTime.Date
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date

Observe que internamente, o relógio do sistema está em termos de UTC; portanto, quando você o chama DateTime.Nowprimeiro obtém o horário UTC (através da GetSystemTimeAsFileTimefunção na API do Win32) e, em seguida, converte o valor no fuso horário local. (Portanto, DateTime.Now.ToUniversalTime()é mais caro que DateTime.UtcNow.)

Observe também que DateTimeOffset.Now.DateTimeterá valores semelhantes a DateTime.Now, mas terá DateTimeKind.Unspecifiedmais do que DateTimeKind.Local- o que pode levar a outros erros, dependendo do que você faz com ele.

Portanto, a resposta simples é que DateTime.Todayé equivalente a DateTime.Now.Date.
Mas IMHO - Você não deve usar um desses, ou qualquer um dos equivalentes acima.

Quando você solicita DateTime.Now, está solicitando o valor do relógio do calendário local do computador em que o código está sendo executado. Mas o que você recebe de volta não tem nenhuma informação sobre esse relógio! O melhor que você recebe é isso DateTime.Now.Kind == DateTimeKind.Local. Mas de quem é o local? Essas informações são perdidas assim que você faz algo com o valor, como armazená-las em um banco de dados, exibi-las na tela ou transmiti-las usando um serviço da Web.

Se o seu fuso horário local seguir alguma regra de horário de verão, você não receberá essas informações novamente DateTime.Now. Em tempos ambíguos, como durante uma transição de "retorno", você não saberá qual dos dois momentos possíveis corresponde ao valor recuperado DateTime.Now. Por exemplo, diga que o fuso horário do sistema está definido como Mountain Time (US & Canada)e você solicita DateTime.Nownas primeiras horas de 3 de novembro de 2013. O que 2013-11-03 01:00:00significa o resultado ? Existem dois momentos de tempo instantâneo representados por essa mesma data e hora do calendário. Se eu enviasse esse valor para outra pessoa, eles não teriam idéia de qual eu quis dizer. Especialmente se eles estiverem em um fuso horário em que as regras sejam diferentes.

A melhor coisa que você poderia fazer seria usar DateTimeOffset:

// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;

Agora, para o mesmo cenário que descrevi acima, obtenho o valor 2013-11-03 01:00:00 -0600antes da transição ou 2013-11-03 01:00:00 -0700após a transição. Quem olhar para esses valores pode dizer o que eu quis dizer.

Eu escrevi um post sobre esse assunto. Por favor, leia - The Case Against DateTime.Now .

Além disso, existem alguns lugares no mundo (como o Brasil) onde a transição "primavera" acontece exatamente à meia-noite. Os relógios vão das 23:59 às 01:00. Isso significa que o valor que você recebe DateTime.Todaynessa data não existe! Mesmo se você usar DateTimeOffset.Now.Date, você está obtendo o mesmo resultado e ainda tem esse problema. Isso ocorre porque, tradicionalmente, não existe um Dateobjeto no .Net. Portanto, independentemente de como você obtém o valor, depois de tirar o tempo - você deve lembrar que ele realmente não representa "meia-noite", mesmo que esse seja o valor com o qual você está trabalhando.

Se você realmente deseja uma solução totalmente correta para esse problema, a melhor abordagem é usar o NodaTime . A LocalDateturma representa adequadamente uma data sem hora. Você pode obter a data atual para qualquer fuso horário, incluindo o fuso horário do sistema local:

using NodaTime;
...

Instant now = SystemClock.Instance.Now;

DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;

DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;

Se você não quiser usar o Noda Time, agora existe outra opção. Contribuí com a implementação de um objeto somente de data no projeto do .Net CoreFX Lab . Você pode encontrar o System.Timeobjeto do pacote no feed MyGet. Depois de adicionado ao seu projeto, você descobrirá que pode fazer o seguinte:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
Matt Johnson-Pint
fonte
9
E o uso de em DateTime.UtcNowvez de DateTimeOffset.Now?
Samuel Liew
5
DateTime.UtcNowé aceitável se você puder transmitir em seu aplicativo ou especificar que o valor está em UTC. (Na verdade, eu gosto de chamar o campo ou a propriedade como algo em MyDateUtcvez de apenas MyDate- mas isso é apenas uma cereja no topo do bolo.) Se você não pode transmiti-lo no nome da especificação ou do campo, DateTimeOffset.UtcNowpode ser usado para garantir que o deslocamento do zero seja transmitido com os valores de data e hora.
Matt Johnson-Pint
Eles não são iguais. Hoje tem o horário como 00:00:00.
James Wilkins
@ JamesWilkins - Não tenho certeza do que você está falando. O mesmo acontece DateTime.Now.Date.
Matt Johnson-Pint
@MattJohnson A pergunta está fazendo a diferença entre DateTime.Today e DateTime.Now, não DateTime.Today e DateTime.Now.Date.
David Anderson
85

Tempo. .Nowinclui 09:23:12 ou o que for; .Todayé apenas a parte da data (às 00:00:00 desse dia).

Portanto, use .Nowse você quiser incluir a hora e .Todayapenas a data!

.Today é essencialmente o mesmo que .Now.Date

Marc Gravell
fonte
27
... e use a UtcNowmenos que você realmente queira o fuso horário local do sistema. (Em particular, em uma aplicação web que é quase sempre a escolha errada.)
Jon Skeet
22

A DateTime.Nowpropriedade retorna a data e hora atuais, por exemplo 2011-07-01 10:09.45310.

A DateTime.Todaypropriedade retorna a data atual com os componentes de tempo definidos como zero, por exemplo 2011-07-01 00:00.00000.

A DateTime.Todaypropriedade é realmente implementada para retornar DateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}
Guffa
fonte
9

DateTime.Today representa a data atual do sistema com a parte da hora definida para 00:00:00

e

DateTime.Now representa a data e hora atuais do sistema

daniel.herken
fonte
2
apenas uma observação ... a documentação 1.1 é muito menos detalhada que a documentação 4.0; talvez seja melhor vincular ao vLatest?
Marc Gravell
3
@megaperlz: Agora você está acessando o 4.0 em vez do vLatest. Os links VLatest podem ser criados excluindo o (v=VS.100).
Brian
6

Pensei em adicionar esses links -

Voltando à pergunta original, Usando o Refletor, expliquei a diferença no código

 public static DateTime Today
    {
      get
      {
        return DateTime.Now.Date;   // It returns the date part of Now

        //Date Property
       // returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00) 
      }
    }


    private const long TicksPerMillisecond = 10000L;
    private const long TicksPerDay = 864000000000L;
    private const int MillisPerDay = 86400000;

    public DateTime Date
    {
       get
      {
        long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks 
        return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);  
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time 
      }
    }


     public static DateTime Now
        {
          get
          {
           /* this is why I guess Jon Skeet is recommending to use  UtcNow as you can see in one of the above comment*/
            DateTime utcNow = DateTime.UtcNow;


            /* After this i guess it is Timezone conversion */
            bool isAmbiguousLocalDst = false;
            long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
            long ticks2 = utcNow.Ticks + ticks1;
            if (ticks2 > 3155378975999999999L)
              return new DateTime(3155378975999999999L, DateTimeKind.Local);
            if (ticks2 < 0L)
              return new DateTime(0L, DateTimeKind.Local);
            else
              return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
          }
        }
dekdev
fonte
5
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time
deepi
fonte
1

DateTime.Todayé DateTime.Nowcom tempo definido como zero.

É importante observar que existe uma diferença entre um valor DateTime, que representa o número de ticks decorridos desde a meia-noite de 1º de janeiro de 0000 e a representação em cadeia desse valor DateTime, que expressa um valor de data e hora em um formato específico de cultura: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Ticksé o tempo real armazenado pelo .net (horário essencialmente UTC), o restante são apenas representações (que são importantes para fins de exibição).

Se a Kindpropriedade estiver, DateTimeKind.Localela inclui implicitamente as informações de fuso horário do computador local. Ao enviar por um serviço da web .net, os valores DateTime são serializados por padrão com as informações de fuso horário incluídas, por exemplo, 2008-10-31T15: 07: 38.6875000-05: 00, e um computador em outro fuso horário ainda pode saber exatamente a que horas é sendo referido.

Portanto, usar DateTime.Now e DateTime.Today está perfeitamente OK.

Você geralmente começa a ter problemas quando começa a confundir a representação da string com o valor real e tenta "consertar" o DateTime, quando não está quebrado.

Kobus
fonte
-1

DateTime.Now.ToShortDateString() exibirá apenas a parte da data

sunnyca99
fonte