Unterschied zwischen System.DateTime.Now und System.DateTime.Today

126

Kann jemand den Unterschied zwischen System.DateTime.Nowund System.DateTime.Todayin C # .NET erklären ? Vor- und Nachteile von jedem, wenn möglich.

Samuel Liew
quelle

Antworten:

178

DateTime.NowGibt einen DateTimeWert zurück, der aus dem lokalen Datum und der Uhrzeit des Computers besteht, auf dem der Code ausgeführt wird. Es hat DateTimeKind.Localseinem KindEigentum zugewiesen . Dies entspricht dem Aufruf einer der folgenden Optionen:

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

DateTime.TodayGibt einen DateTimeWert zurück, der dieselben Jahres-, Monats- und Tageskomponenten wie alle oben genannten Ausdrücke enthält, wobei jedoch die Zeitkomponenten auf Null gesetzt sind. Es hat auch DateTimeKind.Localin seinem KindEigentum. Es entspricht einer der folgenden Angaben:

  • 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

Beachten Sie, dass die Systemuhr intern in UTC angegeben ist. Wenn Sie sie also aufrufen DateTime.Now, wird zuerst die UTC-Zeit (über die GetSystemTimeAsFileTimeFunktion in der Win32-API) abgerufen und anschließend der Wert in die lokale Zeitzone konvertiert. (Daher DateTime.Now.ToUniversalTime()ist teurer als DateTime.UtcNow.)

Beachten Sie auch, dass DateTimeOffset.Now.DateTimedies ähnliche Werte hat wie DateTime.Now, aber DateTimeKind.Unspecifiedeher als DateTimeKind.Local- was zu anderen Fehlern führen kann, je nachdem, was Sie damit machen.

So ist die einfache Antwort ist , dass DateTime.Todayentspricht DateTime.Now.Date.
Aber IMHO - Sie sollten weder eines dieser noch eines der oben genannten Äquivalente verwenden.

Wenn Sie danach fragen DateTime.Now, fragen Sie nach dem Wert der lokalen Kalenderuhr des Computers, auf dem der Code ausgeführt wird. Aber was Sie zurückbekommen, hat keine Informationen über diese Uhr! Das Beste, was Sie bekommen, ist das DateTime.Now.Kind == DateTimeKind.Local. Aber wessen Einheimischer ist es? Diese Informationen gehen verloren, sobald Sie etwas mit dem Wert tun, z. B. in einer Datenbank speichern, auf dem Bildschirm anzeigen oder über einen Webdienst übertragen.

Wenn Ihre lokale Zeitzone den Sommerzeitregeln entspricht, erhalten Sie diese Informationen nicht zurück DateTime.Now. In mehrdeutigen Zeiten, z. B. während eines "Fallback" -Übergangs, wissen Sie nicht, welcher der beiden möglichen Momente dem Wert entspricht, mit dem Sie abgerufen haben DateTime.Now. Angenommen, Ihre Systemzeitzone ist auf eingestellt Mountain Time (US & Canada)und Sie fragen DateTime.Nowin den frühen Morgenstunden des 3. November 2013 nach. Was bedeutet das Ergebnis 2013-11-03 01:00:00? Es gibt zwei Momente der augenblicklichen Zeit, die durch dieselbe Kalenderzeit dargestellt werden. Wenn ich diesen Wert an jemand anderen senden würde, hätte er keine Ahnung, welchen ich meinte. Besonders wenn sie sich in einer Zeitzone befinden, in der die Regeln unterschiedlich sind.

Das Beste, was Sie tun könnten, wäre DateTimeOffsetstattdessen:

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

Für dasselbe Szenario, das ich oben beschrieben habe, erhalte ich den Wert 2013-11-03 01:00:00 -0600vor dem Übergang oder 2013-11-03 01:00:00 -0700nach dem Übergang. Jeder, der sich diese Werte ansieht, kann sagen, was ich meinte.

Ich habe einen Blog-Beitrag zu diesem Thema geschrieben. Bitte lesen Sie - Der Fall gegen DateTime.Now .

Es gibt auch einige Orte auf dieser Welt (wie Brasilien), an denen der "Spring-Forward" -Übergang genau um Mitternacht stattfindet. Die Uhren gehen von 23:59 bis 01:00 Uhr. Dies bedeutet, dass der Wert, den Sie DateTime.Todayan diesem Datum erhalten, nicht vorhanden ist! Selbst wenn Sie verwenden DateTimeOffset.Now.Date, erhalten Sie das gleiche Ergebnis, und Sie haben immer noch dieses Problem. Dies liegt daran, dass es Datein .Net traditionell kein Objekt gegeben hat. Unabhängig davon, wie Sie den Wert erhalten, müssen Sie sich daran erinnern, dass er nicht wirklich "Mitternacht" darstellt, obwohl dies der Wert ist, mit dem Sie arbeiten.

Wenn Sie wirklich eine vollständig korrekte Lösung für dieses Problem wünschen, ist die Verwendung von NodaTime der beste Ansatz . Die LocalDateKlasse repräsentiert ein Datum ohne Uhrzeit. Sie können das aktuelle Datum für jede Zeitzone abrufen, einschließlich der lokalen Systemzeitzone:

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;

Wenn Sie Noda Time nicht verwenden möchten, gibt es jetzt eine andere Option. Ich habe eine Implementierung eines Nur-Datum-Objekts zum .Net CoreFX Lab- Projekt beigetragen . Sie finden das System.TimePaketobjekt in ihrem MyGet-Feed. Nach dem Hinzufügen zu Ihrem Projekt können Sie eine der folgenden Aktionen ausführen:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
Matt Johnson-Pint
quelle
9
Was ist mit der Verwendung von DateTime.UtcNowstatt DateTimeOffset.Now?
Samuel Liew
5
DateTime.UtcNowist akzeptabel, wenn Sie in Ihrer Anwendung oder Spezifikation angeben können, dass der Wert in UTC angegeben ist. (Ich nenne das Feld oder die Eigenschaft gerne so etwas wie MyDateUtcnur MyDate- aber das ist nur das i- Tüpfelchen.) Wenn Sie es nicht in der Spezifikation oder im Feldnamen übermitteln DateTimeOffset.UtcNowkönnen, können Sie sicherstellen, dass der Nullpunktversatz übermittelt wird mit den Datums- und Zeitwerten.
Matt Johnson-Pint
Sie sind nicht gleich. Heute ist die Zeit als 00:00:00.
James Wilkins
@ JamesWilkins - Ich bin mir nicht sicher, worauf du hinaus willst. Das tut es auch DateTime.Now.Date.
Matt Johnson-Pint
@MattJohnson Die Frage stellt den Unterschied zwischen DateTime.Today und DateTime.Now, nicht DateTime.Today und DateTime.Now.Date.
David Anderson
85

Zeit. .Nowbeinhaltet die 09:23:12 oder was auch immer; .Todayist nur der Datumsteil (an diesem Tag um 00:00:00 Uhr).

Verwenden .NowSie diese Option, wenn Sie die Uhrzeit und .Todaynur das Datum angeben möchten.

.Today ist im Wesentlichen das gleiche wie .Now.Date

Marc Gravell
quelle
27
... und verwenden, es UtcNowsei denn, Sie möchten wirklich die lokale Zeitzone des Systems. (Insbesondere in einer Web-App ist das fast immer die falsche Wahl.)
Jon Skeet
22

Die DateTime.NowEigenschaft gibt beispielsweise das aktuelle Datum und die aktuelle Uhrzeit zurück 2011-07-01 10:09.45310.

Die DateTime.TodayEigenschaft gibt beispielsweise das aktuelle Datum zurück, wobei die Zeitkomponenten auf Null gesetzt sind 2011-07-01 00:00.00000.

Die DateTime.TodayEigenschaft wird tatsächlich implementiert, um Folgendes zurückzugeben DateTime.Now.Date:

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

DateTime.Today repräsentiert das aktuelle Systemdatum, wobei der Zeitteil auf 00:00:00 eingestellt ist

und

DateTime.Now repräsentiert das aktuelle Systemdatum und die aktuelle Systemzeit

daniel.herken
quelle
2
nur eine Beobachtung ... die 1.1-Dokumentation ist weit weniger detailliert als die 4.0-Dokumentation; ist es vielleicht besser, auf vLatest zu verlinken?
Marc Gravell
3
@megaperlz: Sie verlinken jetzt auf 4.0 anstatt auf vLatest. VLatest-Links können durch Löschen von erstellt werden (v=VS.100).
Brian
6

Ich dachte daran, diese Links hinzuzufügen -

Zurück zur ursprünglichen Frage: Mit Reflector habe ich den Unterschied im Code erklärt

 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
quelle
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
quelle
1

DateTime.Todayist DateTime.Nowmit der Zeit auf Null gesetzt.

Es ist wichtig zu beachten, dass es einen Unterschied zwischen einem DateTime-Wert gibt, der die Anzahl der seit Mitternacht des 1. Januar 0000 verstrichenen Ticks darstellt, und der Zeichenfolgendarstellung dieses DateTime-Werts, der einen Datums- und Zeitwert in a ausdrückt kulturspezifisches Format: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Ticksist die von .net tatsächlich gespeicherte Zeit (im Wesentlichen UTC-Zeit), der Rest sind nur Darstellungen (die für Anzeigezwecke wichtig sind).

Wenn die KindEigenschaft vorhanden ist, enthält DateTimeKind.Localsie implizit die Zeitzoneninformationen des lokalen Computers. Beim Senden über einen .net-Webdienst werden DateTime-Werte standardmäßig mit Zeitzoneninformationen serialisiert, z. B. 2008-10-31T15: 07: 38.6875000-05: 00, und ein Computer in einer anderen Zeitzone kann immer noch genau wissen, wie spät es ist verwiesen werden.

Die Verwendung von DateTime.Now und DateTime.Today ist also vollkommen in Ordnung.

Normalerweise treten Probleme auf, wenn Sie die Zeichenfolgendarstellung mit dem tatsächlichen Wert verwechseln und versuchen, die DateTime zu "reparieren", wenn sie nicht beschädigt ist.

Kobus
quelle
-1

DateTime.Now.ToShortDateString() zeigt nur den Datumsteil an

sunnyca99
quelle