DateTime.Now vs. DateTime.UtcNow


225

Mi chiedevo quali sono esattamente i principi di come funzionano le due proprietà. So che il secondo è universale e fondamentalmente non si occupa dei fusi orari, ma qualcuno può spiegare in dettaglio come funzionano e quale dovrebbe essere utilizzato in quale scenario?


1
potrebbe essere troppo tardi, ma voglio puntare a questo blog: blog.angeloflogic.com/2013/10/…
Kai Wang

piccola marcatura da banco rextester.com/QRDR82396
Daniel B

Risposte:


346

DateTime.UtcNow ti dice la data e l'ora come sarebbe nel tempo coordinato universale, che è anche chiamato il fuso orario di Greenwich - sostanzialmente come sarebbe se tu fossi a Londra, in Inghilterra, ma non durante l'estate. DateTime.Now fornisce la data e l'ora come apparirebbero a qualcuno nella tua locale attuale.

Ti consiglio di usarlo DateTime.Nowogni volta che mostri una data a un essere umano - in questo modo si sentono a proprio agio con il valore che vedono - è qualcosa che possono facilmente confrontare con ciò che vedono sul loro orologio o orologio. Utilizzare DateTime.UtcNowquando si desidera memorizzare le date o utilizzarle per calcoli successivi in ​​questo modo (in un modello client-server) i calcoli non vengono confusi dai client in fusi orari diversi dal server o l'uno dall'altro.


84
un punto eccellente: quando si memorizzano le date in un database o file, sicuramente memorizzarle in UTC!
Jeff Atwood,

15
Devi notare che quando vuoi memorizzare le date in UTC nel database, devi assicurarti che il database non aggiunga il proprio fuso orario alle date che non danno fusi orari espliciti. Si noti che DateTime utilizzerà sempre il fuso orario corrente quando richiesto.
Omer van Kloeten,

@OmervanKloeten dà un ottimo punto. Mi chiedo se esiste un'elegante soluzione "a tutto tondo" per questo, per archiviare e ricevere le date correttamente ogni volta, anche se IIS e SQL Server sono in fusi orari diversi.
TheGeekZn,

1
@ JoshYates1980 Sì, fai DateTime.UtcNow.AddYears (1)
CathalMF,

3
Usa NodaTime - ti costringerà a pensare al tempo in un modo più utile ed
eviterà

86

È davvero abbastanza semplice, quindi penso che dipenda dal tuo pubblico e da dove vivono.

Se non usi Utc, devi conoscere il fuso orario della persona a cui stai visualizzando date e orari - altrimenti dirai loro che è successo qualcosa alle 3 PM nell'ora del sistema o del server, quando è successo davvero alle 17:00 dove capita di vivere.

Usiamo DateTime.UtcNowperché abbiamo un pubblico web globale e perché preferirei non disturbare tutti gli utenti a compilare un modulo che indica in quale fuso orario vivono.

Visualizziamo anche i tempi relativi (2 ore fa, 1 giorno fa, ecc.) Fino a quando il post non invecchierà abbastanza che il tempo sia "lo stesso", indipendentemente da dove vivi sulla Terra.


Voglio anche secondo che la memorizzazione di DateTime.UtcNow è necessaria solo quando si esegue il calcolo con 2 date per ottenere le ore corrette. Quando devo solo visualizzare un RegisterAt Date, Datetime.Now è sufficiente.
Elisabeth,

36

Notare anche la differenza di prestazioni; DateTime.UtcNowè circa 30 volte più veloce di allora DateTime.Now, perché internamente DateTime.Nowsta facendo molte regolazioni del fuso orario (puoi facilmente verificarlo con Reflector).

Quindi NON utilizzare DateTime.Nowper le misurazioni del tempo relativo.


Mi è occorso un viaggio doloroso, so solo che UtcNow ha prestazioni migliori e che semplicemente salvare le tue date in mysql e supporre che sia utc e confrontare i display dipendenti dalla data con UtcNow semplifica questi problemi del fuso orario globale
Diin,

29

Un concetto principale da capire in .NET è che ormai è ora su tutta la terra non importa quale fuso orario ci si trova Quindi, se si carica una variabile con. DateTime.NowO DateTime.UtcNow-. L'assegnazione è identica * Il vostro DateTimeoggetto sa che cosa fuso orario ci si trova e ne tiene conto indipendentemente dall'assegnazione.

L'utilità di DateTime.UtcNowè utile quando si calcolano le date oltre i confini dell'ora legale. Cioè, in luoghi che partecipano all'ora legale, a volte ci sono 25 ore da mezzogiorno a mezzogiorno del giorno seguente, e talvolta ci sono 23 ore tra mezzogiorno e mezzogiorno del giorno seguente. Se si desidera determinare correttamente il numero di ore tra l'ora A e l'ora B, è necessario prima tradurre ciascuno in equivalenti UTC prima di calcolare il TimeSpan.

Questo è coperto da un post sul blog che ho scritto che spiega ulteriormente TimeSpane include un collegamento a un articolo MS ancora più ampio sull'argomento.

* Chiarimento: entrambi i compiti memorizzeranno l'ora corrente. Se si caricassero due variabili una via DateTime.Now()e l'altra tramite DateTime.UtcNow()la TimeSpandifferenza tra i due sarebbe millisecondi, non ore supponendo che ci si trovi in ​​un fuso orario a ore di distanza dal GMT. Come indicato di seguito, la stampa dei loro Stringvalori visualizzerebbe stringhe diverse.


1
Per quanto riguarda "carica una variabile con DateTime.Now o DateTime.UtcNow - l'assegnazione è identica": potrebbe essere necessario chiarire? Mentre mi siedo qui nel fuso orario EDT (UTC -4), ho assegnato due variabili rispettivamente a DateTime.UtcNow e DateTime.Now e quindi ho stampato i loro valori con ToString (). I valori visualizzati erano distanti 4 ore - non "identici".
Jon Schneider,

2
@JonSchneider, credo che tu abbia ragione. L'affermazione: "l'assegnazione è identica" non è vera. ToString () non è probabilmente il modo migliore per testarlo, perché potrebbe mostrare date uguali in modo diverso (come fa Java). Le funzioni di confronto sono un test migliore e mostrano che non sono effettivamente uguali.
Ted Bigham,

Chiarimento alla mia affermazione "identica": carica una variabile tramite DateTime.Now e un'altra con DateTime.UtcNow e quindi stampa la differenza TimeSpan. La differenza sarà di millisecondi e non di ore, supponendo che tu sia distante da GMT.
Carl Camera

18

Questa è una buona domanda Lo sto rianimando per dare un po 'più di dettagli su come .Net si comporta con Kindvalori diversi . Come sottolinea @Jan Zich, in realtà è una proprietà di fondamentale importanza ed è impostata in modo diverso a seconda che tu usi Nowo UtcNow.

Internamente la data viene memorizzata come Ticks(contrariamente alla risposta di @Carl Camera) è diversa a seconda se si utilizza Nowo UtcNow.

DateTime.UtcNowsi comporta come altre lingue. Si imposta Tickssu un valore basato su GMT. Imposta anche Kindsu Utc.

DateTime.Nowaltera il Ticksvalore di quello che sarebbe se fosse la tua ora del giorno nel fuso orario GMT . Imposta anche Kindsu Local.

Se sei indietro di 6 ore (GMT-6), otterrai l'ora GMT da 6 ore fa. .Net in realtà ignora Kinde tratta questa volta come se fosse 6 ore fa, anche se dovrebbe essere "adesso". Ciò si interrompe ancora di più se si crea DateTimeun'istanza, quindi si modifica il fuso orario e si tenta di utilizzarlo.

Le istanze di DateTime con valori 'Kind' diversi NON sono compatibili.

Diamo un'occhiata ad un po 'di codice ...

    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

Come puoi vedere qui, i confronti e le funzioni matematiche non si convertono automaticamente in tempi compatibili. L' Timespanavrebbe dovuto essere quasi un'ora, ma invece era quasi 6. "utc <ora" avrebbe dovuto essere vero (Ho anche aggiunto un ora per essere sicuri), ma era ancora falsa.

Puoi anche vedere il "aggirare" che è semplicemente convertire in tempo universale ovunque Kindnon sia lo stesso.

La mia risposta diretta alla domanda concorda con la raccomandazione della risposta accettata su quando utilizzarla. Dovresti sempre provare a lavorare con DateTimeoggetti che hanno Kind=Utc, tranne durante l'I / O (visualizzazione e analisi). Ciò significa che dovresti quasi sempre utilizzarlo DateTime.UtcNow, ad eccezione dei casi in cui stai creando l'oggetto solo per visualizzarlo e scartarlo immediatamente.


7

DateTime non ha idea di quali fusi orari siano. Presuppone sempre che tu sia all'ora locale. UtcNow significa solo "Sottrai il mio fuso orario dal tempo".

Se si desidera utilizzare date in base al fuso orario, utilizzare DateTimeOffset , che rappresenta una data / ora con un fuso orario. Ho dovuto impararlo nel modo più duro.


9
Per essere del tutto precisi (ed evitare alle persone di utilizzare Now su UtcNow per motivi di prestazioni), è il contrario: ora aggiunge il fuso orario a UtcNow ed è in effetti un rallentamento della grandezza.
mafu,

5

La "semplice" risposta alla domanda è:

DateTime.Now restituisce un valore DateTime che rappresenta l'ora corrente del sistema (in qualunque fuso orario il sistema è in esecuzione). La proprietà DateTime.Kind sarà DateTimeKind.Local

DateTime.UtcNow restituisce un valore DateTime che rappresenta l'ora coordinata universale corrente (aka UTC) che sarà la stessa indipendentemente dal fuso orario del sistema. La proprietà DateTime.Kind sarà DateTimeKind.Utc


4

Solo una piccola aggiunta ai punti sopra menzionati: la struttura DateTime contiene anche un campo poco noto chiamato Kind (almeno, non lo sapevo da molto tempo). Fondamentalmente è solo una bandiera che indica se l'ora è locale o UTC; non specifica l'offset reale da UTC per l'ora locale. Oltre al fatto che indica con quali intenzioni è stata costruita la struttura, influenza anche il modo in cui funzionano i metodi ToUniversalTime () e ToLocalTime () .



1

DateTime.UtcNow è una scala temporale continua a valore singolo, mentre DateTime.Now non è continuo o a valore singolo. Il motivo principale è l'ora legale, che non si applica all'ora UTC. Quindi UTC non salta mai avanti o indietro di un'ora, mentre l'ora locale (DateTime.Now) lo fa. E quando salta all'indietro, lo stesso valore temporale si verifica due volte.


1

DateTime.UtcNow è una scala di tempo universale che omette l'ora legale. Quindi UTC non cambia mai a causa dell'ora legale.

Tuttavia, DateTime.Now non è continuo o a valore singolo perché cambia in base all'ora legale. Il che significa DateTime.Now, lo stesso valore temporale può verificarsi due volte lasciando i clienti in uno stato confuso.


0

Quando è necessaria l'ora locale per il computer su cui viene eseguita l'applicazione (come CEST per l'Europa), utilizzare Now. Se vuoi un tempo universale - UtcNow. È solo una questione di preferenze - probabilmente creando un sito Web locale / un'applicazione autonoma che vorresti usare il tempo che l'utente ha - così influenzato dalle sue impostazioni del fuso orario - DateTime.Now.

Ricorda, per un sito Web è l'impostazione del fuso orario del server. Quindi, se stai visualizzando il tempo per l'utente, ottieni il suo fuso orario preferito e sposta il tempo (basta salvare il tempo Utc nel database e modificarlo) o specificare il suo UTC. Se ti dimentichi di farlo, l'utente può vedere qualcosa di simile: pubblicato 3 svantaggi fa e poi un tempo in futuro vicino ad esso :)


0

La grande differenza :) è che DateTime.Now non è supportato nel flusso di lavoro di SharePoint, è necessario utilizzare DateTime.UtcNow

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.