Kann jemand den Unterschied zwischen System.DateTime.Now
und System.DateTime.Today
in C # .NET erklären ? Vor- und Nachteile von jedem, wenn möglich.
Kann jemand den Unterschied zwischen System.DateTime.Now
und System.DateTime.Today
in C # .NET erklären ? Vor- und Nachteile von jedem, wenn möglich.
Antworten:
DateTime.Now
Gibt einen DateTime
Wert zurück, der aus dem lokalen Datum und der Uhrzeit des Computers besteht, auf dem der Code ausgeführt wird. Es hat DateTimeKind.Local
seinem Kind
Eigentum 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.Today
Gibt einen DateTime
Wert 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.Local
in seinem Kind
Eigentum. 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 GetSystemTimeAsFileTime
Funktion 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.DateTime
dies ähnliche Werte hat wie DateTime.Now
, aber DateTimeKind.Unspecified
eher als DateTimeKind.Local
- was zu anderen Fehlern führen kann, je nachdem, was Sie damit machen.
So ist die einfache Antwort ist , dass DateTime.Today
entspricht 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.Now
in 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 DateTimeOffset
stattdessen:
// 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 -0600
vor dem Übergang oder 2013-11-03 01:00:00 -0700
nach 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.Today
an 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 Date
in .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 LocalDate
Klasse 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.Time
Paketobjekt 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);
DateTime.UtcNow
ist 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 MyDateUtc
nur MyDate
- aber das ist nur das i- Tüpfelchen.) Wenn Sie es nicht in der Spezifikation oder im Feldnamen übermitteln DateTimeOffset.UtcNow
können, können Sie sicherstellen, dass der Nullpunktversatz übermittelt wird mit den Datums- und Zeitwerten.
DateTime.Now.Date
.
Zeit. .Now
beinhaltet die 09:23:12 oder was auch immer; .Today
ist nur der Datumsteil (an diesem Tag um 00:00:00 Uhr).
Verwenden .Now
Sie diese Option, wenn Sie die Uhrzeit und .Today
nur das Datum angeben möchten.
.Today
ist im Wesentlichen das gleiche wie .Now.Date
UtcNow
sei denn, Sie möchten wirklich die lokale Zeitzone des Systems. (Insbesondere in einer Web-App ist das fast immer die falsche Wahl.)
Die DateTime.Now
Eigenschaft gibt beispielsweise das aktuelle Datum und die aktuelle Uhrzeit zurück 2011-07-01 10:09.45310
.
Die DateTime.Today
Eigenschaft gibt beispielsweise das aktuelle Datum zurück, wobei die Zeitkomponenten auf Null gesetzt sind 2011-07-01 00:00.00000
.
Die DateTime.Today
Eigenschaft wird tatsächlich implementiert, um Folgendes zurückzugeben DateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
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
(v=VS.100)
.
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);
}
}
DateTime.Today
ist DateTime.Now
mit 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.Ticks
ist die von .net tatsächlich gespeicherte Zeit (im Wesentlichen UTC-Zeit), der Rest sind nur Darstellungen (die für Anzeigezwecke wichtig sind).
Wenn die Kind
Eigenschaft vorhanden ist, enthält DateTimeKind.Local
sie 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.
DateTime.UtcNow
stattDateTimeOffset.Now
?