Speichern von DateTime (UTC) vs. Speichern von DateTimeOffset

93

Normalerweise habe ich einen "Interceptor", der unmittelbar vor dem Lesen / Schreiben aus / in die Datenbank die DateTime-Konvertierung (von UTC in Ortszeit und von Ortszeit in UTC) durchführt, sodass ich DateTime.Now(Ableitungen und Vergleiche) im gesamten System verwenden kann, ohne mir Sorgen machen zu müssen über Zeitzonen.

In Bezug auf die Serialisierung und das Verschieben von Daten zwischen Computern besteht kein Grund zur Sorge, da die Datums- und Uhrzeitangabe immer UTC ist.

Soll ich meine Daten (SQL 2008 - datetime) weiterhin im UTC-Format speichern oder stattdessen mit DateTimeOffset(SQL 2008 - datetimeoffset) speichern?

UTC-Daten in der Datenbank (Datum / Uhrzeit-Typ) haben so lange funktioniert und sind bekannt. Warum sollten Sie sie ändern? Was sind die Vorteile?

Ich habe mir bereits Artikel wie diesen angesehen , bin aber nicht zu 100% überzeugt. Irgendwelche Gedanken?

Frederico
quelle
1
Siehe auch: DateTime vs DateTimeOffset - geschrieben für .Net, gilt aber konzeptionell auch für SQL.
Matt Johnson-Pint

Antworten:

131

Es gibt einen großen Unterschied, bei dem Sie UTC nicht alleine verwenden können.

  • Wenn Sie ein solches Szenario haben

    • Ein Server und mehrere Clients (alle geografisch in unterschiedlichen Zeitzonen )
    • Clients erstellen einige Daten mit Datums- / Uhrzeitinformationen
    • Clients speichern alles auf einem zentralen Server
  • Dann:

    • datetimeoffset speichert die Ortszeit des Clients und versetzt AUCH die UTC-Zeit
    • Alle Kunden kennen die UTC-Zeit aller Daten und auch eine Ortszeit an dem Ort, an dem die Informationen entstanden sind
  • Aber:

    • UTC datetime speichert nur UTC datetime , sodass Sie keine Informationen zur Ortszeit am Client-Standort haben, von dem die Daten stammen
    • Andere Clients kennen die Ortszeit des Ortes nicht, von dem Datums- / Uhrzeitinformationen stammen
    • Andere Clients können ihre Ortszeit nur aus der Datenbank (unter Verwendung der UTC-Zeit) berechnen, nicht die Ortszeit des Clients, aus dem die Daten stammen

Ein einfaches Beispiel ist das Reservierungssystem für Flugtickets ... Das Flugticket sollte zwei Mal enthalten: - Startzeit (in der Zeitzone der Stadt "Von") - Landezeit (in der Zeitzone der Stadt "Ziel")

Marcel Toth
quelle
2
Dies ist die beste Erklärung, über die ich gelesen habe, wann es angemessen wäre, und ich habe viel gelesen. Für uns scheint dies nicht der Fall zu sein. Wir erhalten die Zeit in UTC für unsere externen Daten und kennen den Standort bei Bedarf aus einer anderen Quelle (und das war noch nie so). Danke, dass du es so offensichtlich gemacht hast.
Andrew Backer
19
Sie sagten, "datetimeoffset speichert die UTC-Zeit und AUCH die Ortszeit des Clients", aber datetimeoffset speichert die LOKALE Zeit + Versatz oder die UTC-Zeit + Versatz gleich +0.
Serhii Kyslyi
Obwohl Sie das DTO einfach in ein DT umwandeln könnten, da die DT-Basis UTC ist (obwohl dies ein zusätzlicher Schritt für alle
Benutzer
2
Scheint eher so, als ob DateTmeOffset "Ortszeit und UTC-Versatz" speichert, nicht "UTC-Zeit und UTC-Versatz". Wenn Sie in datetime umwandeln oder eine der Datepart-Funktionen verwenden, erhalten Sie die lokalen Datums- und Zeitkomponenten.
Triynko
" Alle Kunden kennen die UTC-Zeit aller Daten und auch die Ortszeit an dem Ort, an dem die Informationen stammen." Die Speicherung als Teil des Datumsfelds fühlt sich in diesem Fall jedoch nicht normal an. Was ist der Anwendungsfall - das heißt, warum würden Sie nicht UTC verwenden und den Offset zu InputLocationId(oder einer ähnlichen normalisierten Entität) herausziehen . Es wäre eine Berechnung erforderlich (Hallo, Ausnahmen ... besonders Sie, Indiana ), aber es ist immer noch ein deterministischer Prozess - und dann ist das Gleichgewicht der Datums- / Uhrzeitlogik der App unkompliziert.
Ruffin
23

Es ist absolut richtig, UTC für alle historischen Zeiten zu verwenden (dh Ereignisse wurden aufgezeichnet). Es ist immer möglich, von UTC zur Ortszeit zu wechseln, aber nicht immer umgekehrt.

Wann sollte die Ortszeit verwendet werden? Beantworte diese Frage:

Wenn die Regierung plötzlich beschließt, die Sommerzeit zu ändern, möchten Sie, dass sich diese Daten ändern?

Speichern Sie die Ortszeit nur, wenn die Antwort "Ja" lautet. Offensichtlich gilt dies nur für zukünftige Daten und normalerweise nur für Daten, die Personen in irgendeiner Weise betreffen.

Warum eine Zeitzone / einen Versatz speichern?

Erstens, wenn Sie aufzeichnen möchten, wie hoch der Versatz für den Benutzer war, der die Aktion ausgeführt hat, ist es wahrscheinlich am besten, dies einfach zu tun, dh beim Anmelden den Ort und die Zeitzone für diesen Benutzer aufzuzeichnen.

Zweitens, wenn Sie für die Anzeige konvertieren möchten, benötigen Sie eine Tabelle aller lokalen Zeitversatzübergänge für diese Zeitzone. Es reicht nicht aus, nur den aktuellen Versatz zu kennen, denn wenn Sie ein Datum / eine Uhrzeit von vor sechs Monaten anzeigen, wird der Versatz angezeigt Sei anders.

Ben
quelle
4
Die Konvertierung von Windows UTC in Ortszeit berücksichtigt, wenn sich die Sommerzeit für historische Daten ändert. Ich verstehe nicht, warum Sie in diesem Fall die Ortszeit speichern möchten.
Jamiegs
1
@Jamiegs Windows kennt nur historisch die "letzten historischen Informationen" (wie in der .NET DateTime-Dokumentation angedeutet / vermerkt). Es ist nicht umfassend.
2
Natürlich müssen Sie auch den Ort des Ereignisses speichern, sonst können Sie nicht sagen, zu welcher "Ortszeit" das Ereignis stattgefunden hat.
KeuleJ
20

Mit einem DATETIMEOFFSET können Sie die Ortszeit und die UTC-Zeit in einem Feld speichern.

Dies ermöglicht eine sehr einfache und effiziente Berichterstellung in lokaler oder UTC-Zeit, ohne dass die Daten für die Anzeige in irgendeiner Weise verarbeitet werden müssen.

Dies sind die beiden häufigsten Anforderungen - Ortszeit für lokale Berichte und UTC-Zeit für Gruppenberichte.

Die Ortszeit wird im DATETIME-Teil des DATETIMEOFFSET gespeichert, und der OFFSET von UTC wird im OFFSET-Teil gespeichert. Die Konvertierung ist daher einfach und kann auf Datenbankebene durchgeführt werden, da keine Kenntnis der Zeitzone erforderlich ist, aus der die Daten stammen .

Wenn Sie keine Zeiten bis zu Millisekunden benötigen, z. B. nur Minuten oder Sekunden, können Sie DATETIMEOFFSET (0) verwenden. Das Feld DATETIMEOFFSET benötigt dann nur 8 Byte Speicher - genau wie ein DATETIME.

Die Verwendung eines DATETIMEOFFSET anstelle eines UTC-DATETIME bietet daher mehr Flexibilität, Effizienz und Einfachheit für die Berichterstellung.

PapillonUK
quelle
Schade, dass das Entity-Framework überhaupt nicht auf die lokale Datums- / Uhrzeitangabe eines Datums- / Uhrzeitversatzfelds zugreifen kann, sodass es unmöglich ist, nach einem bestimmten lokalen Datum abzufragen.
Triynko
@Triynko kannst du erklären was du meinst? Beispiel?
ReidLinden