Differenza tra System.DateTime.Now e System.DateTime.Today


127

Qualcuno può spiegare la differenza tra System.DateTime.Nowe System.DateTime.Todayin C # .NET? Pro e contro di ciascuno, se possibile.

Risposte:


179

DateTime.Nowrestituisce un DateTimevalore costituito dalla data e dall'ora locali del computer su cui è in esecuzione il codice. Ha DateTimeKind.Localassegnato alla sua Kindproprietà. È 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.Todayrestituisce un DateTimevalore con le stesse componenti di anno, mese e giorno delle espressioni precedenti, ma con le componenti di tempo impostate su zero. Ha anche DateTimeKind.Localnella sua Kindproprietà. È 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.Nowper primo ottiene l'ora UTC (tramite la GetSystemTimeAsFileTimefunzione 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.DateTimeavrà valori simili a DateTime.Now, ma avrà DateTimeKind.Unspecifiedpiuttosto 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.Nownelle 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 DateTimeOffsetinvece:

// 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 -0600prima della transizione o 2013-11-03 01:00:00 -0700dopo 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.Todayquella 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 Dateoggetto 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 LocalDateclasse 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.Timeoggetto 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);

9
Che dire dell'uso DateTime.UtcNowinvece di DateTimeOffset.Now?
Samuel Liew

5
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 MyDateUtcinvece di solo MyDate- ma questo è solo la ciliegina sulla torta.) Se non riesci a trasmetterlo nella specifica o nel nome del campo, allora DateTimeOffset.UtcNowpuò essere utilizzato per garantire che l'offset zero venga trasmesso con i valori di data e ora.
Matt Johnson-Pint,

Non sono uguali. Oggi ha il tempo di 00:00:00.
James Wilkins,

@JamesWilkins - Non sono sicuro di cosa stai arrivando. Così fa DateTime.Now.Date.
Matt Johnson-Pint,

@MattJohnson La domanda sta ponendo la differenza tra DateTime.Today e DateTime.Now, non DateTime.Today e DateTime.Now.Date.
David Anderson,

85

Tempo. .Nowinclude le 09:23:12 o altro; .Todayè solo la parte della data (alle 00:00:00 di quel giorno).

Quindi usa .Nowse vuoi includere l'ora e .Todayse vuoi solo la data!

.Today è essenzialmente lo stesso di .Now.Date


27
... e utilizzare a UtcNowmeno che non si desideri davvero il fuso orario locale del sistema. (In particolare, su un'app Web che è quasi sempre la scelta sbagliata.)
Jon Skeet,

22

La DateTime.Nowproprietà restituisce, ad esempio, la data e l'ora correnti 2011-07-01 10:09.45310.

La DateTime.Todayproprietà restituisce la data corrente con i componenti temporali impostati su zero, ad esempio 2011-07-01 00:00.00000.

La DateTime.Todayproprietà è effettivamente implementata per restituire DateTime.Now.Date:

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

9

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


2
solo un'osservazione ... la documentazione 1.1 è molto meno dettagliata della documentazione 4.0; è forse meglio collegarsi a vLatest?
Marc Gravell

3
@megaperlz: ora stai collegando a 4.0 piuttosto che a vLatest. I collegamenti VLatest possono essere creati eliminando il (v=VS.100).
Brian,

6

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);
          }
        }

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

1

DateTime.Todayè DateTime.Nowcon 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 Kindproprietà è DateTimeKind.Localche 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.


-1

DateTime.Now.ToShortDateString() visualizzerà solo la parte della data

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.