DateTimeOffset
ist eine Darstellung der momentanen Zeit (auch als absolute Zeit bekannt ). Damit meine ich einen Moment in der Zeit, der für alle universell ist (ohne Berücksichtigung von Schaltsekunden oder den relativistischen Effekten der Zeitdilatation ). Eine andere Möglichkeit, die momentane Zeit darzustellen, ist das DateTime
Wo .Kind
ist DateTimeKind.Utc
.
Dies unterscheidet sich von der Kalenderzeit (auch als Zivilzeit bezeichnet ), die eine Position im Kalender einer Person darstellt, und es gibt weltweit viele verschiedene Kalender. Wir nennen diese Kalender Zeitzonen . Die Kalenderzeit wird durch ein DateTime
Wo .Kind
ist DateTimeKind.Unspecified
oder dargestellt DateTimeKind.Local
. Und .Local
ist nur sinnvoll in Situationen , in denen Sie ein implizites Verständnis davon, wo der Computer, der das Ergebnis verwendet wird , positioniert. (Zum Beispiel die Workstation eines Benutzers)
Warum also DateTimeOffset
statt einer UTC DateTime
? Es geht nur um Perspektive. Verwenden wir eine Analogie - wir geben vor, Fotografen zu sein.
Stellen Sie sich vor, Sie stehen auf einer Kalender-Zeitleiste und richten eine Kamera auf eine Person auf der vor Ihnen liegenden augenblicklichen Zeitleiste. Sie richten Ihre Kamera gemäß den Regeln Ihrer Zeitzone aus - diese ändern sich regelmäßig aufgrund der Sommerzeit oder aufgrund anderer Änderungen an der gesetzlichen Definition Ihrer Zeitzone. (Sie haben keine ruhige Hand, daher ist Ihre Kamera wackelig.)
Die Person, die auf dem Foto steht, sieht den Winkel, aus dem Ihre Kamera stammt. Wenn andere Bilder machen, können sie aus verschiedenen Blickwinkeln sein. Dies ist, was der Offset
Teil der DateTimeOffset
darstellt.
Wenn Sie Ihre Kamera also als "Eastern Time" bezeichnen, zeigen Sie manchmal von -5 und manchmal von -4. Es gibt Kameras auf der ganzen Welt, die alle mit unterschiedlichen Dingen beschriftet sind und aus verschiedenen Winkeln auf dieselbe augenblickliche Zeitachse zeigen. Einige von ihnen befinden sich direkt nebeneinander (oder übereinander). Es reicht also nicht aus, nur den Versatz zu kennen, um festzustellen, auf welche Zeitzone sich die Zeit bezieht.
Und was ist mit UTC? Nun, es ist die einzige Kamera da draußen, die garantiert eine ruhige Hand hat. Es steht auf einem Stativ und ist fest im Boden verankert. Es geht nirgendwo hin. Wir nennen seinen Perspektivwinkel den Nullpunktversatz.
Also - was sagt uns diese Analogie? Es bietet einige intuitive Richtlinien-
Wenn Sie die Zeit relativ zu einem bestimmten Ort darstellen, stellen Sie sie in Kalenderzeit mit a dar DateTime
. Stellen Sie nur sicher, dass Sie niemals einen Kalender mit einem anderen verwechseln. Unspecified
sollte deine Annahme sein. Local
ist nur nützlich, wenn man von kommt DateTime.Now
. Zum Beispiel könnte ich es bekommen DateTime.Now
und in einer Datenbank speichern - aber wenn ich es abrufe, muss ich davon ausgehen, dass es ist Unspecified
. Ich kann mich nicht darauf verlassen, dass mein lokaler Kalender derselbe ist, aus dem er ursprünglich stammt.
Wenn Sie immer sicher sein müssen, stellen Sie sicher, dass Sie die momentane Zeit darstellen. Verwenden DateTimeOffset
Sie diese Option , um sie durchzusetzen, oder verwenden Sie UTC DateTime
gemäß Konvention.
Wenn Sie einen Moment der augenblicklichen Zeit verfolgen müssen, aber auch wissen möchten: "Wann hat der Benutzer gedacht, dass er in seinem lokalen Kalender steht?" - dann müssen Sie a verwenden DateTimeOffset
. Dies ist beispielsweise für Zeitnehmungssysteme sehr wichtig - sowohl aus technischen als auch aus rechtlichen Gründen.
Wenn Sie jemals eine zuvor aufgezeichnete Änderung ändern DateTimeOffset
müssen, verfügen Sie nicht über genügend Informationen allein im Offset, um sicherzustellen, dass der neue Offset für den Benutzer weiterhin relevant ist. Sie müssen auch eine Zeitzonen-ID speichern (denken Sie - ich benötige den Namen dieser Kamera, damit ich ein neues Bild aufnehmen kann, auch wenn sich die Position geändert hat).
Es sollte auch darauf hingewiesen werden, dass Noda Time eine dafür vorgesehene Darstellung ZonedDateTime
hat, während die .Net-Basisklassenbibliothek nichts Ähnliches hat. Sie müssten sowohl einen DateTimeOffset
als auch einen TimeZoneInfo.Id
Wert speichern .
Gelegentlich möchten Sie eine Kalenderzeit darstellen, die lokal für "denjenigen ist, der sie betrachtet" ist. Zum Beispiel bei der Definition dessen, was heute bedeutet. Heute ist immer Mitternacht bis Mitternacht, aber diese repräsentieren eine nahezu unendliche Anzahl überlappender Bereiche auf der augenblicklichen Zeitachse. (In der Praxis haben wir eine endliche Anzahl von Zeitzonen, aber Sie können Offsets bis zum Häkchen ausdrücken.) Stellen Sie in diesen Situationen sicher, dass Sie verstehen, wie Sie entweder das "Wer fragt?" Begrenzen können. Fragen Sie bis zu einer einzelnen Zeitzone oder übersetzen Sie sie gegebenenfalls zurück in die momentane Zeit.
Hier sind ein paar andere Kleinigkeiten DateTimeOffset
, die diese Analogie stützen, und einige Tipps, um sie klar zu halten:
Wenn Sie zwei DateTimeOffset
Werte vergleichen , werden diese vor dem Vergleich zunächst auf Nullversatz normiert. Mit anderen Worten, 2012-01-01T00:00:00+00:00
und 2012-01-01T02:00:00+02:00
beziehen sich auf den gleichen augenblicklichen Moment und sind daher äquivalent.
Wenn Sie einen Komponententest durchführen und den Versatz sicher sein müssen, testen Sie sowohl den DateTimeOffset
Wert als auch die .Offset
Eigenschaft separat.
In das .NET-Framework ist eine implizite Einwegkonvertierung integriert, mit der Sie a an einen DateTime
beliebigen DateTimeOffset
Parameter oder eine beliebige Variable übergeben können. Dabei die es .Kind
ankommt . Wenn Sie eine UTC-Art übergeben, wird diese mit einem Nullpunktversatz übertragen. Wenn Sie jedoch eine .Local
oder übergeben .Unspecified
, wird davon ausgegangen, dass sie lokal ist . Das Framework sagt im Grunde: "Nun, Sie haben mich gebeten, die Kalenderzeit in die Momentanzeit umzuwandeln, aber ich habe keine Ahnung, woher diese stammt, also werde ich nur den lokalen Kalender verwenden." Dies ist ein großes Problem, wenn Sie ein nicht angegebenes Gerät DateTime
auf einen Computer mit einer anderen Zeitzone laden . (IMHO - das sollte eine Ausnahme auslösen - tut es aber nicht.)
Schamloser Stecker:
Viele Leute haben mir mitgeteilt, dass sie diese Analogie äußerst wertvoll finden, deshalb habe ich sie in meinen Pluralsight-Kurs, Datums- und Zeitgrundlagen, aufgenommen . Eine schrittweise Anleitung zur Kameraanalogie finden Sie im zweiten Modul "Context Matters" im Clip "Calendar Time vs. Instantaneous Time".