Alguém pode explicar a diferença entre System.DateTime.Now
e System.DateTime.Today
no C # .NET? Prós e contras de cada um, se possível.
Alguém pode explicar a diferença entre System.DateTime.Now
e System.DateTime.Today
no C # .NET? Prós e contras de cada um, se possível.
Respostas:
DateTime.Now
retorna um DateTime
valor que consiste na data e hora locais do computador em que o código está sendo executado. Foi DateTimeKind.Local
atribuído à sua Kind
propriedade. É 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.Today
retorna um DateTime
valor 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.Local
em sua Kind
propriedade. É 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.Now
primeiro obtém o horário UTC (através da GetSystemTimeAsFileTime
funçã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.DateTime
terá valores semelhantes a DateTime.Now
, mas terá DateTimeKind.Unspecified
mais 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.Now
nas primeiras horas de 3 de novembro de 2013. O que 2013-11-03 01:00:00
significa 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 -0600
antes da transição ou 2013-11-03 01:00:00 -0700
apó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.Today
nessa 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 Date
objeto 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 LocalDate
turma 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.Time
objeto 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);
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 MyDateUtc
vez 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.UtcNow
pode ser usado para garantir que o deslocamento do zero seja transmitido com os valores de data e hora.
DateTime.Now.Date
.
Tempo. .Now
inclui 09:23:12 ou o que for; .Today
é apenas a parte da data (às 00:00:00 desse dia).
Portanto, use .Now
se você quiser incluir a hora e .Today
apenas a data!
.Today
é essencialmente o mesmo que .Now.Date
UtcNow
menos que você realmente queira o fuso horário local do sistema. (Em particular, em uma aplicação web que é quase sempre a escolha errada.)
A DateTime.Now
propriedade retorna a data e hora atuais, por exemplo 2011-07-01 10:09.45310
.
A DateTime.Today
propriedade retorna a data atual com os componentes de tempo definidos como zero, por exemplo 2011-07-01 00:00.00000
.
A DateTime.Today
propriedade é realmente implementada para retornar DateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
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
(v=VS.100)
.
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);
}
}
DateTime.Today
é DateTime.Now
com 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 Kind
propriedade estiver, DateTimeKind.Local
ela 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.
DateTime.UtcNow
vez deDateTimeOffset.Now
?