Qualcuno può spiegare la differenza tra System.DateTime.Now
e System.DateTime.Today
in C # .NET? Pro e contro di ciascuno, se possibile.
Qualcuno può spiegare la differenza tra System.DateTime.Now
e System.DateTime.Today
in C # .NET? Pro e contro di ciascuno, se possibile.
Risposte:
DateTime.Now
restituisce un DateTime
valore costituito dalla data e dall'ora locali del computer su cui è in esecuzione il codice. Ha DateTimeKind.Local
assegnato alla sua Kind
proprietà. È equivalente a chiamare uno dei seguenti:
DateTime.UtcNow.ToLocalTime()
DateTimeOffset.UtcNow.LocalDateTime
DateTimeOffset.Now.LocalDateTime
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)
DateTime.Today
restituisce un DateTime
valore con le stesse componenti di anno, mese e giorno delle espressioni precedenti, ma con le componenti di tempo impostate su zero. Ha anche DateTimeKind.Local
nella sua Kind
proprietà. È equivalente a uno dei seguenti:
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
Nota che internamente, l'orologio di sistema è in termini di UTC, quindi quando lo chiami DateTime.Now
per primo ottiene l'ora UTC (tramite la GetSystemTimeAsFileTime
funzione nell'API Win32) e quindi converte il valore nel fuso orario locale. (Pertanto DateTime.Now.ToUniversalTime()
è più costoso di DateTime.UtcNow
.)
Si noti inoltre che DateTimeOffset.Now.DateTime
avrà valori simili a DateTime.Now
, ma avrà DateTimeKind.Unspecified
piuttosto che DateTimeKind.Local
- il che potrebbe portare ad altri errori a seconda di cosa ne fai.
Quindi, la semplice risposta DateTime.Today
è equivalente a DateTime.Now.Date
.
Ma IMHO - Non dovresti usare uno di questi o uno dei precedenti equivalenti.
Quando lo chiedi DateTime.Now
, stai chiedendo il valore dell'orologio del calendario locale del computer su cui è in esecuzione il codice. Ma ciò che ottieni non ha informazioni su quell'orologio! Il meglio che ottieni è quello DateTime.Now.Kind == DateTimeKind.Local
. Ma di chi è questo locale? Tali informazioni vengono perse non appena si fa qualcosa con il valore, come archiviarle in un database, visualizzarle sullo schermo o trasmetterle utilizzando un servizio Web.
Se il tuo fuso orario locale segue le regole dell'ora legale, non riceverai tali informazioni DateTime.Now
. In tempi ambigui, come durante una transizione "fallback", non saprai con quale dei due possibili momenti corrisponda il valore con cui hai recuperato DateTime.Now
. Ad esempio, supponi che il fuso orario del tuo sistema sia impostato Mountain Time (US & Canada)
e lo richiedi DateTime.Now
nelle prime ore del 3 novembre 2013. Cosa significa il risultato 2013-11-03 01:00:00
? Ci sono due momenti di tempo istantaneo rappresentati da questo stesso datetime di calendario. Se dovessi inviare questo valore a qualcun altro, non avrebbero idea di quale intendessi. Soprattutto se si trovano in un fuso orario in cui le regole sono diverse.
La cosa migliore che potresti fare sarebbe usare DateTimeOffset
invece:
// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;
Ora per lo stesso scenario che ho descritto sopra, ottengo il valore 2013-11-03 01:00:00 -0600
prima della transizione o 2013-11-03 01:00:00 -0700
dopo la transizione. Chiunque guardi questi valori può dire cosa intendevo dire.
Ho scritto un post sul blog proprio su questo argomento. Si prega di leggere - Il caso contro DateTime.Now .
Inoltre, ci sono alcuni posti in questo mondo (come il Brasile) in cui la transizione "primaverile" avviene esattamente a mezzanotte. Gli orologi vanno dalle 23:59 all'01: 00. Ciò significa che il valore ottenuto per DateTime.Today
quella data non esiste! Anche se lo usi DateTimeOffset.Now.Date
, stai ottenendo lo stesso risultato e hai ancora questo problema. È perché, tradizionalmente, non esiste un Date
oggetto in .Net. Quindi, indipendentemente dal modo in cui ottieni il valore, una volta che hai perso il tempo, devi ricordare che in realtà non rappresenta "mezzanotte", anche se questo è il valore con cui stai lavorando.
Se vuoi davvero una soluzione completamente corretta a questo problema, l'approccio migliore è usare NodaTime . La LocalDate
classe rappresenta correttamente una data senza ora. È possibile ottenere la data corrente per qualsiasi fuso orario, incluso il fuso orario del sistema locale:
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 non vuoi usare Noda Time, ora c'è un'altra opzione. Ho contribuito all'implementazione di un oggetto solo data al progetto .Net CoreFX Lab . Puoi trovare l' System.Time
oggetto pacchetto nel loro feed MyGet. Una volta aggiunto al tuo progetto, scoprirai che puoi eseguire una delle seguenti operazioni:
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
DateTime.UtcNow
è accettabile se è possibile comunicare nella propria applicazione o specifica che il valore è in UTC. (In realtà mi piace chiamare il campo o la proprietà qualcosa di simile MyDateUtc
invece di solo MyDate
- ma questo è solo la ciliegina sulla torta.) Se non riesci a trasmetterlo nella specifica o nel nome del campo, allora DateTimeOffset.UtcNow
può essere utilizzato per garantire che l'offset zero venga trasmesso con i valori di data e ora.
DateTime.Now.Date
.
Tempo. .Now
include le 09:23:12 o altro; .Today
è solo la parte della data (alle 00:00:00 di quel giorno).
Quindi usa .Now
se vuoi includere l'ora e .Today
se vuoi solo la data!
.Today
è essenzialmente lo stesso di .Now.Date
UtcNow
meno che non si desideri davvero il fuso orario locale del sistema. (In particolare, su un'app Web che è quasi sempre la scelta sbagliata.)
La DateTime.Now
proprietà restituisce, ad esempio, la data e l'ora correnti 2011-07-01 10:09.45310
.
La DateTime.Today
proprietà restituisce la data corrente con i componenti temporali impostati su zero, ad esempio 2011-07-01 00:00.00000
.
La DateTime.Today
proprietà è effettivamente implementata per restituire DateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
DateTime.Today rappresenta la data corrente del sistema con la parte temporale impostata su 00:00:00
e
DateTime.Now rappresenta la data e l'ora correnti del sistema
(v=VS.100)
.
Ho pensato di aggiungere questi collegamenti -
Tornando alla domanda originale, usando Reflector ho spiegato la differenza di codice
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
con il tempo impostato su zero.
È importante notare che esiste una differenza tra un valore DateTime, che rappresenta il numero di tick che sono trascorsi dalla mezzanotte del 1 ° gennaio 0000 e la rappresentazione di stringa di quel valore DateTime, che esprime un valore di data e ora in un formato specifico per cultura specifica: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx
DateTime.Now.Ticks
è l'ora effettiva memorizzata da .net (essenzialmente l'ora UTC), il resto sono solo rappresentazioni (che sono importanti ai fini della visualizzazione).
Se la Kind
proprietà è DateTimeKind.Local
che implicitamente include le informazioni sul fuso orario del computer locale. Quando si invia tramite un servizio web .net, i valori di DateTime sono serializzati per impostazione predefinita con le informazioni sul fuso orario incluse, ad esempio 2008-10-31T15: 07: 38.6875000-05: 00, e un computer in un altro fuso orario può ancora sapere esattamente che ora è a cui si fa riferimento.
Quindi, usando DateTime.Now e DateTime.Today è perfettamente OK.
Di solito si inizia a incorrere in problemi quando si inizia a confondere la rappresentazione della stringa con il valore effettivo e si tenta di "correggere" il DateTime, quando non è rotto.
DateTime.UtcNow
invece diDateTimeOffset.Now
?