DateTime.Now vs. DateTime.UtcNow

225

Ich habe mich gefragt, was genau die Prinzipien sind, wie die beiden Eigenschaften funktionieren. Ich weiß, dass die zweite universell ist und sich im Grunde nicht mit Zeitzonen befasst, aber kann jemand detailliert erklären, wie sie funktionieren und welche in welchem ​​Szenario verwendet werden sollte?

Slavo
quelle
1
Vielleicht ist es zu spät, aber ich möchte auf diesen Blog verweisen
Kai Wang
kleines Benchmarking rextester.com/QRDR82396
Daniel B

Antworten:

346

DateTime.UtcNow zeigt Ihnen Datum und Uhrzeit wie in der koordinierten Weltzeit an, die auch als Greenwich Mean Time-Zeitzone bezeichnet wird - im Grunde wie in London, England, aber nicht im Sommer. DateTime.Now gibt Datum und Uhrzeit so an, wie sie jemandem in Ihrem aktuellen Gebietsschema erscheinen würden.

Ich würde empfehlen, DateTime.Nowwann immer Sie einem Menschen ein Datum anzeigen - auf diese Weise fühlen sie sich mit dem Wert, den sie sehen, wohl - es ist etwas, das sie leicht mit dem vergleichen können, was sie auf ihrer Uhr sehen. Verwenden DateTime.UtcNowSie diese Option, wenn Sie Datumsangaben speichern oder für spätere Berechnungen verwenden möchten. Auf diese Weise (in einem Client-Server-Modell) werden Ihre Berechnungen nicht von Clients in verschiedenen Zeitzonen von Ihrem Server oder voneinander verwirrt.

Blair Conrad
quelle
84
ein ausgezeichneter Punkt - wenn Speichern von Daten in einer Datenbank oder Datei, speichern Sie auf jeden Fall sie in UTC!
Jeff Atwood
15
Sie müssen beachten, dass Sie beim Speichern von Datumsangaben in UTC in der Datenbank sicherstellen müssen, dass die Datenbank Datumsangaben, die keine expliziten Zeitzonen enthalten, keine eigene Zeitzone hinzufügt. Beachten Sie, dass DateTime immer die aktuelle Zeitzone verwendet, wenn Sie dazu aufgefordert werden.
Omer van Kloeten
@OmervanKloeten gibt einen sehr guten Punkt. Ich frage mich, ob es dafür eine elegante Allround-Lösung gibt, mit der Daten jedes Mal korrekt gespeichert und empfangen werden können, selbst wenn sich Ihr IIS und Ihr SQL Server in unterschiedlichen Zeitzonen befinden.
TheGeekZn
1
@ JoshYates1980 Ja, Sie tun nur DateTime.UtcNow.AddYears (1)
CathalMF
3
Verwenden Sie NodaTime - es wird Sie zwingen, nützlicher über die Zeit nachzudenken und solche Probleme zu vermeiden
aateeque
86

Es ist wirklich ganz einfach, also denke ich, dass es davon abhängt, was Ihr Publikum ist und wo es lebt.

Wenn Sie Utc nicht verwenden, müssen Sie die Zeitzone der Person kennen, für die Sie Datum und Uhrzeit anzeigen. Andernfalls werden Sie ihnen mitteilen, dass um 15 Uhr in der System- oder Serverzeit etwas passiert ist, wenn es tatsächlich um 17 Uhr passiert ist sie leben zufällig.

Wir verwenden, DateTime.UtcNowweil wir ein globales Webpublikum haben und weil ich es vorziehen würde, nicht jeden Benutzer zu nerven, um ein Formular auszufüllen, in dem angegeben ist, in welcher Zeitzone er lebt.

Wir zeigen auch relative Zeiten an (vor 2 Stunden, vor 1 Tag usw.), bis der Beitrag so alt ist, dass die Zeit "dieselbe" ist, egal wo auf der Erde Sie leben.

Jeff Atwood
quelle
Ich möchte auch zweitens, dass das Speichern von DateTime.UtcNow auch nur benötigt wird, wenn eine Berechnung mit 2 Daten durchgeführt wird, um die richtigen Stunden zu erhalten. Wenn ich nur ein RegisterAt-Datum anzeigen muss, reicht Datetime.Now aus.
Elisabeth
36

Beachten Sie auch den Leistungsunterschied. DateTime.UtcNowist dann ungefähr 30- mal schneller als dort DateTime.Now, da intern DateTime.Nowviele Zeitzonenanpassungen vorgenommen werden (Sie können dies leicht mit Reflector überprüfen).

Also NICHT DateTime.Nowfür relative Zeitmessungen verwenden.

Magnus Krisell
quelle
Es hat mich auf eine schmerzhafte Reise geführt, nur zu wissen, dass UtcNow eine bessere Leistung hat und dass das einfache Speichern Ihrer Daten in MySQL und die Annahme, dass dies utc ist und das Vergleichen von datumsabhängigen Anzeigen mit UtcNow diese globalen Zeitzonenprobleme vereinfacht
Diin
29

Ein Hauptkonzept in .NET zu verstehen ist , dass jetzt ist jetzt über die ganze Erde , egal in welcher Zeitzone Sie sind in Also , wenn Sie eine Variable laden mit. DateTime.NowOder DateTime.UtcNow-. Die Zuordnung identisch ist * Ihr DateTimeObjekt weiß , welche Zeitzone Sie sind in und berücksichtigt dies unabhängig von der Zuordnung.

Die Nützlichkeit von ist DateTime.UtcNownützlich, wenn Sie Daten über die Grenzen der Sommerzeit hinweg berechnen. Das heißt, an Orten, die an der Sommerzeit teilnehmen, gibt es manchmal 25 Stunden von Mittag bis Mittag am folgenden Tag und manchmal 23 Stunden zwischen Mittag und Mittag am folgenden Tag. Wenn Sie die Anzahl der Stunden ab Zeitpunkt A und Zeitpunkt B korrekt bestimmen möchten, müssen Sie diese zunächst in ihre UTC-Entsprechungen übersetzen, bevor Sie die berechnen TimeSpan.

Dies wird durch einen Blog-Beitrag behandelt, den ich geschrieben habe , der weiter erklärt TimeSpanund der einen Link zu einem noch umfangreicheren MS-Artikel zu diesem Thema enthält.

* Klarstellung: In beiden Zuordnungen wird die aktuelle Uhrzeit gespeichert. Wenn Sie zwei Variablen über DateTime.Now()und die andere über laden würden, wäre DateTime.UtcNow()die TimeSpanDifferenz zwischen den beiden Millisekunden, nicht Stunden, vorausgesetzt, Sie befinden sich in einer Zeitzone, die Stunden von GMT entfernt ist. Wie unten erwähnt, werden beim Ausdrucken ihrer StringWerte unterschiedliche Zeichenfolgen angezeigt.

Carl Kamera
quelle
1
Bezüglich "Laden einer Variablen mit DateTime.Now oder DateTime.UtcNow - die Zuordnung ist identisch": Muss dies möglicherweise geklärt werden? Da ich hier in der EDT-Zeitzone (UTC -4) sitze, habe ich DateTime.UtcNow und DateTime.Now zwei Variablen zugewiesen und ihre Werte dann mit ToString () gedruckt. Die angezeigten Werte lagen 4 Stunden auseinander - nicht "identisch".
Jon Schneider
2
@ JonSchneider, ich glaube du bist richtig. Die Aussage: "Die Zuordnung ist identisch" ist nicht wahr. ToString () ist wahrscheinlich nicht der beste Weg , um Test, der , weil es könnte anders gleich Daten angezeigt werden (wie Java tut). Vergleichsfunktionen sind ein besserer Test und zeigen, dass sie tatsächlich nicht gleich sind.
Ted Bigham
Klarstellung zu meiner "identischen" Anweisung: Laden Sie eine Variable über DateTime.Now und eine andere mit DateTime.UtcNow und drucken Sie dann die TimeSpan-Differenz. Der Unterschied beträgt Millisekunden und nicht Stunden, vorausgesetzt, Sie sind Stunden von GMT entfernt.
Carl Kamera
18

Das ist eine gute Frage. Ich belebe es wieder, um etwas detaillierter zu beschreiben, wie sich .Net mit unterschiedlichen KindWerten verhält . Wie @Jan Zich betont, handelt es sich tatsächlich um eine äußerst wichtige Eigenschaft, die je nach Verwendung Nowoder Verwendung unterschiedlich festgelegt wird UtcNow.

Intern wird das Datum so gespeichert, Ticksdass es (im Gegensatz zur Antwort von @Carl Camera) unterschiedlich ist, je nachdem, ob Sie Nowoder verwenden UtcNow.

DateTime.UtcNowverhält sich wie andere Sprachen. Es wird Ticksein GMT-basierter Wert festgelegt. Es setzt auch Kindauf Utc.

DateTime.Nowändert den TicksWert auf den Wert, der wäre, wenn es Ihre Tageszeit in der GMT-Zeitzone wäre . Es setzt auch Kindauf Local.

Wenn Sie 6 Stunden hinterher sind (GMT-6), erhalten Sie die GMT-Zeit von vor 6 Stunden. .Net ignoriert Kindund behandelt diese Zeit tatsächlich so, als wäre es 6 Stunden her, obwohl es "jetzt" sein soll. Dies bricht noch mehr ab, wenn Sie eine DateTimeInstanz erstellen, dann Ihre Zeitzone ändern und versuchen, sie zu verwenden.

DateTime-Instanzen mit unterschiedlichen 'Kind'-Werten sind NICHT kompatibel.

Schauen wir uns einen Code an ...

    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

Wie Sie hier sehen können, werden Vergleiche und mathematische Funktionen nicht automatisch in kompatible Zeiten konvertiert. Das Timespanhätte fast eine Stunde sein sollen, aber stattdessen war es fast 6. "utc <now" hätte wahr sein sollen (ich habe sogar eine Stunde hinzugefügt, um sicher zu sein), war aber immer noch falsch.

Sie können auch die "Umgehung" sehen, die darin besteht, einfach überall in die Weltzeit umzuwandeln, wo dies Kindnicht dasselbe ist.

Meine direkte Antwort auf die Frage stimmt mit der Empfehlung der akzeptierten Antwort überein, wann sie jeweils verwendet werden soll. Sie sollten immer versuchen , mit DateTimeObjekten zu arbeiten Kind=Utc, außer während der E / A (Anzeigen und Parsen). Dies bedeutet, dass Sie fast immer verwenden sollten DateTime.UtcNow, außer in den Fällen, in denen Sie das Objekt nur erstellen, um es anzuzeigen, und es sofort verwerfen.

Ted Bigham
quelle
7

DateTime hat keine Ahnung, welche Zeitzonen sind. Es wird immer davon ausgegangen, dass Sie zu Ihrer Ortszeit sind. UtcNow bedeutet nur "Subtrahiere meine Zeitzone von der Zeit".

Wenn Sie zeitzonenbezogene Daten verwenden möchten , verwenden Sie DateTimeOffset , das ein Datum / eine Uhrzeit mit einer Zeitzone darstellt. Das musste ich auf die harte Tour lernen.

Omer van Kloeten
quelle
9
Um ganz genau zu sein (und aus Leistungsgründen zu vermeiden, dass Benutzer Now über UtcNow verwenden), ist es umgekehrt: Jetzt wird die Zeitzone zu UtcNow hinzugefügt und ist tatsächlich eine Größenordnung langsamer.
Mafu
5

Die "einfache" Antwort auf die Frage lautet:

DateTime.Now gibt einen DateTime- Wert zurück, der die aktuelle Systemzeit darstellt (in welcher Zeitzone auch immer das System ausgeführt wird). Die DateTime.Kind- Eigenschaft lautet DateTimeKind.Local

DateTime.UtcNow gibt einen DateTime- Wert zurück, der die aktuelle universelle koordinierte Zeit (auch bekannt als UTC) darstellt und unabhängig von der Zeitzone des Systems gleich ist. Die DateTime.Kind- Eigenschaft lautet DateTimeKind.Utc

PapillonUK
quelle
4

Nur eine kleine Ergänzung zu den oben genannten Punkten: Die DateTime-Struktur enthält auch ein wenig bekanntes Feld namens Kind (zumindest wusste ich es lange nicht). Es ist im Grunde nur ein Flag, das angibt, ob die Zeit lokal oder UTC ist. Der tatsächliche Versatz von UTC für Ortszeiten wird nicht angegeben. Neben der Tatsache, dass es angibt, mit welchen Absichten das Konstrukt erstellt wurde, beeinflusst es auch die Funktionsweise der Methoden ToUniversalTime () und ToLocalTime () .

Jan Zich
quelle
1

DateTime.UtcNow ist eine kontinuierliche, einwertige Zeitskala, während DateTime.Now keine kontinuierliche oder einwertige Zeitskala ist. Der Hauptgrund ist die Sommerzeit, die nicht für UTC gilt. UTC springt also niemals eine Stunde vorwärts oder rückwärts, wohingegen die Ortszeit (DateTime.Now) dies tut. Und wenn es rückwärts springt, tritt der gleiche Zeitwert zweimal auf.

user1315023
quelle
1

DateTime.UtcNow ist eine universelle Zeitskala ohne Sommerzeit. UTC ändert sich also nie aufgrund der Sommerzeit.

DateTime.Now ist jedoch nicht kontinuierlich oder einwertig, da es sich je nach Sommerzeit ändert. Dies bedeutet, dass DateTime.Now, der gleiche Zeitwert kann zweimal auftreten und Kunden in einem verwirrten Zustand zurücklassen.

ChaiVan
quelle
0

Wenn Sie eine Ortszeit für den Computer benötigen, auf dem Ihre Anwendung ausgeführt wird (wie MESZ für Europa), verwenden Sie Jetzt. Wenn Sie eine universelle Zeit wollen - UtcNow. Es ist nur eine Frage Ihrer Vorlieben - wahrscheinlich erstellen Sie eine lokale Website / eigenständige Anwendung, die Sie für die Zeit verwenden möchten, die der Benutzer verwendet hat - also beeinflusst von seiner Zeitzoneneinstellung - DateTime.Now.

Denken Sie daran, für eine Website ist es die Zeitzoneneinstellung des Servers. Wenn Sie also die Zeit für den Benutzer anzeigen, rufen Sie entweder seine bevorzugte Zeitzone ab und verschieben Sie die Zeit (speichern Sie dann einfach die Utc-Zeit in der Datenbank und ändern Sie sie) oder geben Sie die UTC an. Wenn Sie dies vergessen, kann der Benutzer Folgendes sehen: Vor 3 Minuten gepostet und dann in der Zukunft in der Nähe :)

Kender
quelle
0

Der große Unterschied :) ist, dass DateTime.Now im SharePoint Workflow nicht unterstützt wird. Sie müssen DateTime.UtcNow verwenden

Michel LAPLANE
quelle