Was ist ein gültiger Anwendungsfall für die Verwendung von TIMESTAMP WITHOUT TIME ZONE?

40

Es gibt eine lange und recht verständliche Antwort auf die Unterschiede zwischen

  • TIMESTAMP WITH TIME ZONE -vs-
  • TIMESTAMP WITHOUT TIME ZONE

verfügbar in diesem SO Beitrag . Was ich wissen möchte, ist: Gibt es gültige Anwendungsfälle für die tatsächliche Verwendung TIMESTAMP WITHOUT TIME ZONEoder sollte dies als Antimuster angesehen werden?

Marcus Junius Brutus
quelle
Diese Frage läuft Gefahr, geschlossen zu werden, weil sie "hauptsächlich auf Meinungen basiert". Ich habe versucht, in meiner Antwort unten einige objektive Ansichten zu geben.
Colin 't Hart
2
Dieses Problem ist sehr real und jeder Datentyp hat eine ganz andere Bedeutung. Daher würde ich diese Frage sicherlich nicht als primär meinungsbasiert betrachten.
Basil Bourque

Antworten:

29

Dies wird an vielen Stellen angegeben, aber ich denke, es ist immer erwähnenswert, wenn wir die timestamp with time zonemit timestamp without time zoneTypen vergleichen : Die Zeitzoneninformationen werden nicht zusammen mit dem Zeitstempel timestamp WITH time zonegespeichert . Damit werden alle Daten in der UTC-Zeitzone gespeichert, wie in den Dokumenten angegeben :

Für Zeitstempel mit Zeitzone wird der intern gespeicherte Wert immer in UTC (Universal Coordinated Time, traditionell als Greenwich Mean Time, GMT bezeichnet) angegeben. Ein Eingabewert, für den eine explizite Zeitzone angegeben ist, wird unter Verwendung des entsprechenden Offsets für diese Zeitzone in UTC konvertiert. Wenn in der Eingabezeichenfolge keine Zeitzone angegeben ist, wird davon ausgegangen, dass sie sich in der Zeitzone befindet, die im Parameter TimeZone des Systems angegeben ist, und sie wird mit dem Versatz für die Zeitzone in UTC konvertiert.

Es wird für einige als gültig erachtet timestamp WITHOUT time zone, wenn (1) sich alles in derselben Zeitzone befindet oder (2) die Anwendungsebene die Zeitzone verwaltet und alles in einer bestimmten Zeitzone (normalerweise UTC) speichert. Es wird jedoch auch als Antimuster angesehen, da die richtige Lösung für (1) darin besteht, die Einstellung für die Zeitzone auf die angegebene Zeitzone für das System zu konfigurieren, und (2) bereits gelöst ist, da PostgreSQL bereits alles in derselben Zeitzone speichert (KOORDINIERTE WELTZEIT).

Jetzt, wo die beiden unten sind, kann ich nur einen guten Grund nennen timestamp WITHOUT time zone. In diesem Fall möchten Sie Ereignisse in der Zukunft speichern, und zu diesem Zeitpunkt muss eine Warnung ausgelöst werden. Das könnte nützlich sein, timestamp WITH time zonewenn und nur dann, wenn sich die Regeln, die in den regionalen Gesetzen zur Zeitzone festgelegt sind, nie geändert haben. Die häufigste Regel, die sich ändert, bezieht sich auf die Annahme oder Nichteinhaltung der Sommerzeit.

Stellen Sie sich beispielsweise vor, Sie 2013-06-15planen (noch nicht in der Sommerzeit) ein Ereignis für 2013-01-15 10:00(das sich bereits in der Sommerzeit befindet), und in 2013-06-15Ihrer Region wurde die Einführung der Sommerzeit festgelegt. Aber einige Zeit später änderte die Regierung die Regel und sagte, dass Ihre Region die Sommerzeit nicht mehr verwenden wird, und plötzlich wird Ihre geplante Zeit 2013-01-15 11:00(anstelle von 10:00) diejenige, die Sie verwenden timestamp WITH time zone, und halten Sie Ihre TZ-Konfigurationen auf dem neuesten Stand. Natürlich können Sie auch bemerken, dass es möglich ist, solche Fälle auch mit Zeitzonen zu behandeln, wenn Sie die Regeländerungen in den Regionen / Zeitzonen Ihres Interesses verfolgen und die betroffenen Datensätze aktualisieren.

Erwähnenswert ist, dass einige Regionen diese Regeln häufig ändern (wie in Brasilien, einige Bundesstaaten - nicht das ganze Land - ändern sich häufig), aber in den meisten Fällen ändert es sich sehr viel früher, sodass Ihre Benutzer nur von Ereignissen betroffen sind, die sehr weit entfernt von geplant sind die aktuelle Zeit.

Nach alledem habe ich nur noch einen Vorschlag. Wenn Sie Benutzer, Protokolle oder andere Elemente in unterschiedlichen Zeitzonen haben, speichern Sie die Zeitzone, aus der sie stammen, und wählen Sie sie aus und verwenden Sie sie timestamp with time zone. Auf diese Weise können Sie (1) Ereignisse, die näher beieinander liegen, für verschiedene Quellen (unabhängig von ihrer Zeitzone) überqueren und (2) die ursprüngliche Zeit (die Uhrzeit) des Ereignisses anzeigen.

MatheusOl
quelle
Sie sagen: "Es gibt nur einen guten Grund, einen Zeitstempel mit Zeitzone zu verwenden." Wenn das kein Tippfehler ist, schlagen Sie dann tatsächlich vor, dass "Zeitstempel ohne Zeitzone" geeigneter ist / weniger zu Missverständnissen neigt als "Zeitstempel mit Zeitzone"? Das erscheint mir kontraintuitiv.
Marcus Junius Brutus
@MarcusJuniusBrutus, tut mir leid, es war in der Tat ein Tippfehler und ich dachte anders herum ... Überprüfen Sie die bearbeitete Antwort.
MatheusOl
codeblog.jonskeet.uk/2019/03/27/… diskutiert genau dieses Szenario der zukünftigen Ereignisregeln, das sich möglicherweise ändert (mit derselben Schlussfolgerung)
Beni Cherniavsky-Paskin,
17

Ja. Es gibt Anwendungsfälle für TIMESTAMP WITHOUT TIME ZONE.

  • In gängigen Geschäftsanwendungen wird dieser Typ nur für Folgendes verwendet:
    • Buchung zukünftiger Termine
    • Darstellung der gleichen Tageszeit in verschiedenen Zeitzonen, z. B. am 23. Mittag in Tokio und in Paris (zwei verschiedene Momente im Abstand, gleiche Tageszeit)
  • Verwenden Sie zum Verfolgen von Momenten bestimmte Punkte auf der Zeitachse immer TIMESTAMP WITH TIME ZONEund nicht WITHOUT.

TIMESTAMP WITHOUT TIME ZONEWerte sind kein Punkt auf der Zeitachse, keine tatsächlichen Momente. Sie geben eine ungefähre Vorstellung von potenziellen Momenten und möglichen Punkten auf der Zeitachse in einem Bereich von etwa 26 bis 27 Stunden (dem Bereich der Zeitzonen rund um den Globus). Sie haben keine wirkliche Bedeutung, bis Sie eine Zeitzone oder einen Versatz von UTC anwenden .

ZB: Weihnachten

Angenommen, Sie müssen den Beginn von Feiertagen / Feiertagen aufzeichnen.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

Um zu erfassen, dass Weihnachten am 25. Dezember dieses Jahres nach Mitternacht beginnt, müssen wir 2016-12-25 00:00:00keine Zeitzone angeben . Früh am Tag des Weihnachtsmanns besucht er kurz nach Mitternacht Auckland, Neuseeland, da dies eine der frühesten Mitternächte der Welt ist. Dann arbeitet er sich nach Westen vor, bis die nächste Mitternacht die Philippinen erreicht. Dann bewegen sich die Rentiere in westlicher Richtung und erreichen Indien um Mitternacht, was einige Stunden nach Mitternacht in Auckland passiert. Viel später ist noch Mitternacht in Paris FR und noch später Mitternacht in Montreal CA. Alle diese Besuche des Weihnachtsmanns finden zu unterschiedlichen Zeitpunkten statt , und doch geschahen alle kurz nach Mitternacht, je nach Lokalität um Mitternacht.

Das Aufnehmen 2016-12-25 00:00:00ohne Zeitzone zu Beginn von Weihnachten ist also informativ und legitim, aber nur vage. Bis Sie "Weihnachten in Auckland" oder "Weihnachten in Montréal" sagen, haben wir keinen bestimmten Zeitpunkt. Wenn Sie bei jedem Aufsetzen des Schlittens den tatsächlichen Moment aufzeichnen, verwenden Sie TIMESTAMP WITH TIME ZONEstatt des WITHOUTTyps.

Ähnlich wie Weihnachten ist Silvester. Wenn der Times Square Ball in New York fällt , kühlen die Leute in Seattle immer noch ihren Champagner und bereiten ihre Partyhörner vor . Dennoch würden wir die Idee des Neujahrsmoments wie 2017-01-01 00:00:00in a TIMESTAMP WITHOUT TIME ZONE. Wenn wir dagegen aufzeichnen möchten, wann der Ball in New York gefallen ist oder wann die Leute in Seattle ihre Hörner geblasen haben, würden wir stattdessen diese tatsächlichen Momente drei Stunden hintereinander aufzeichnen TIMESTAMP WITH TIME ZONE(nicht WITHOUT).

Beispiel: Fabrikschichten

Ein anderes Beispiel könnte das Aufzeichnen einer Richtlinie sein, bei der die Uhrzeit an verschiedenen Orten angezeigt wird. Sagen wir, wir haben Fabriken in Detroit, Düsseldorf und Delhi. Wenn wir sagen, dass in allen drei Fabriken die erste Schicht um 6 Uhr morgens mit einer Mittagspause um 11:30 Uhr beginnt, könnte dies als ein TIMESTAMP WITHOUT TIME ZONE. Auch diese Informationen sind auf vage Weise nützlich, geben jedoch keinen bestimmten Zeitpunkt an, bis wir eine Zeitzone anwenden. Im Osten bricht früher ein neuer Tag an. Das Werk in Delhi wird also um 6 Uhr morgens als erstes eröffnet. Stunden später beginnt das Düsseldorfer Werk um 6 Uhr morgens mit der Arbeit. Die Fabrik in Detroit wird jedoch erst sechs Stunden später, wenn 6 Uhr morgens, eröffnet.

Vergleichen Sie diese Idee (wann die Fabrikschicht im Allgemeinen beginnt) mit der historischen Tatsache, wann jeder Fabrikarbeiter eingewechselt ist, um seine Schicht an einem bestimmten Tag zu beginnen. Das Eintakten ist ein echter Moment, ein tatsächlicher Punkt auf der Timeline. Wir würden das also in einer Spalte vom Typ TIMESTAMP WITH TIME ZONEund nicht vom WITHOUTTyp aufzeichnen .

Also, ja, es gibt legitime Anwendungsfälle für TIMESTAMP WITHOUT TIME ZONE. Nach meiner Erfahrung mit Geschäftsanwendungen sind sie jedoch relativ selten. Im Geschäftsleben kümmern wir uns in der Regel um die tatsächlichen Momente: Wann ist die Rechnung tatsächlich angekommen, wann tritt genau dieser Vertrag in Kraft, zu welchem ​​Zeitpunkt wurde die Banküberweisung ausgeführt. In solchen Situationen wollen wir den TIMESTAMP WITH TIME ZONETyp.

Weitere Informationen finden Sie unter Meine Antwort auf die ähnliche Frage: Soll ich UTC-Zeitstempel oder Ortszeiten für Schichten speichern?

Postgres

Beachten Sie, dass Postgres die beim Einfügen eines Zeitstempels angegebenen Zeitzoneninformationen niemals speichert.

  • TIMESTAMP WITH TIME ZONE
    • Jede angegebene Zeitzone oder jeder Offset in den Eingabedaten wird verwendet, um den Wert auf UTC einzustellen und zu speichern. Die übergebenen Zonen- / Versatzinformationen werden dann verworfen. Denken Sie an TIMESTAMP WITH TIME ZONEals TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • Bei einer Eingabe von 12:00 Uhr am 7. März dieses Jahres in Indien wird die Uhrzeit durch Subtraktion von fünfeinhalb Stunden auf UTC umgestellt: 6:30 Uhr.
  • TIMESTAMP WITHOUT TIME ZONE
    • Alle angegebenen Zeitzonen oder Offsets, die in den Eingabedaten enthalten sind, werden vollständig ignoriert.
    • Eine Eingabe von 12:00 Uhr am 7. März dieses Jahres in Indien wird ohne Anpassung als 12:00 Uhr am 7. März dieses Jahres aufgezeichnet.

Der SQL-Standard geht kaum auf Probleme mit Datums- und Uhrzeitdatentypen und -verhalten ein. So Datenbank variieren weit in den Umgang mit Datum-Zeit.

Basil Bourque
quelle
Bei Fabrik- (oder Krankenhaus-) Schichten werden die Stunden von Personen, die an den Tagen der Sommerzeitumstellung in der Friedhofsschicht arbeiten, fälschlicherweise ohne Zeitzone aufgezeichnet.
Jasen,
Ich denke , es ein Tippfehler im letzten Beispiel ist: ‚Eine Eingabe von 12:00 Uhr am 7. März .. sollte‚ wie aufgezeichnet 12 : 00‘(nicht 21:00)
TmTron
11

Ich möchte dem noch eine andere Ansicht hinzufügen, die gegen vieles verstößt, was in den anderen Antworten geschrieben wurde. Meiner Meinung nach timestamp with time zonehat sehr wenig valide Anwendungsfälle und timestamp without time zonesollte im Allgemeinen bevorzugt werden.

Zunächst müssen Sie das Muster "UTC everywhere" verstehen, das im Allgemeinen für alle Anwendungen empfohlen wird, für die keine besonderen Anforderungen gelten. Das bedeutet einfach, dass Ihre Anwendung alle Zeitstempel in UTC überall und jederzeit darstellen soll. Natürlich werden Sie Benutzern das lokale Datum und die lokale Uhrzeit anzeigen, aber die Idee ist, diese beim Rendern der Ansicht ganz am Rand Ihres Programms zu konvertieren. Dies ist der richtige Ort, um den UTC-Zeitstempel (den Sie möglicherweise aus einer Datenbank geladen haben) und die Zeitzone des Benutzers (die möglicherweise aus dem Browser stammt) in einem lokalen Zeitstempel zu kombinieren.

Wenn Sie diesem Muster folgen, timestamp with time zonehandelt es sich um ein Anti-Muster. Dieser Typ bewirkt lediglich, dass PostgreSQL beim Lesen und Schreiben von Zeitstempeln Zeitzonenkonvertierungen basierend auf Ihrer PostgreSQL- TimeZoneSitzungsvariablen durchführt. Anstatt sich mit Zeitzonen am Rande Ihrer Anwendung zu befassen, haben Sie sie in ihr Herzstück, in die Kommunikation mit Ihrer Datenbank, eingeführt. Sie müssen darauf achten, dass PostgreSQL immer TimeZoneordnungsgemäß konfiguriert ist, um eine weitere unnötige Fehler- und Verwirrungsquelle zu schaffen.

Und wofür? Wenn Sie dem UTC-Überall-Muster folgen, hat Ihre Anwendung sowieso nur UTC-Zeitstempel. Warum also Ihre Datenbank auffordern, Zeitzonen-Konvertierungen für sie durchzuführen? Sie können sie einfach in einer timestamp without time zoneSpalte speichern und so behandeln, als ob es immer UTC ist. Keine Konvertierungen, keine Zeitzonen, keine Komplikationen.

Shay Rojansky
quelle
2
Ich denke, dass die Befürworter des Zeitstempels auch das Muster "UTC everywhere" unterstützen. Es ist nur eine Regel, die nur auf Datenbankebene durchgesetzt wird, anstatt sich nur auf App- / API-Entwickler zu verlassen, um sie durchzusetzen. Wenn Sie diese Praxis durchsetzen können, warum nicht? Sie können auch nur erzwingen, dass alle Postgres-Verbindungen ihre Zeitzone auf UTC setzen. Auch wenn dies nicht der Fall ist, enthält das ISO-Format den tz-Offset. Ist das also nicht überall dasselbe wie UTC, aber durchgesetzt?
Am
3
Erstens liest Ihr Programm Nicht-UTC-Zeitstempel, wenn Ihre PostgreSQL-Zeitzone auf etwas anderes als UTC eingestellt ist und Sie Zeitstempel verwenden. Dies ist einfach nicht das "UTC everywhere" -Muster, und abhängig von Ihrer Client-Sprache können viele Komplikationen auftreten oder auch nicht. Entweder Sie sind überall in UTC oder Sie verwenden lokale Zeitstempel ...
Shay Rojansky
Zweitens: Wenn Sie in Ihrer Anwendung überall in UTC arbeiten, müssen Sie für Ihre Zeitstempel einfach keinen tz-Versatz im ISO-Format senden. Die Besonderheiten variieren von Sprache zu Sprache. InstanceIdealerweise sollten Sie jedoch einen Client-Typ verwenden, der nur einen UTC-Zeitstempel darstellen kann (z. B. einen in NodaTime / JodaTime). Sie beschreiben im Grunde eine Situation, in der "UTC überall" fast verfolgt wird, oder irgendwie gefolgt ...
Shay Rojansky
Auch hier ist es sehr einfach, sich vorzustellen, dass auf einem Server eine neue PostgreSQL-Instanz eingerichtet wird, die versehentlich die standardmäßig konfigurierte Zeitzone des lokalen Computers beibehält. Anwendungen lesen von diesem Server und erhalten lokale Zeitstempel in einer völlig beliebigen Zeitzone (in der sich der Server gerade befindet). Warum sollten wir diese zusätzliche Komplikation wollen?
Shay Rojansky
1
Es könnte, aber dann würde es noch weniger Sinn machen, es zu benutzen timestamptz. Der springende Punkt bei diesem Typ ist die Durchführung von Zeitzonen-Konvertierungen als gelesene und in PostgreSQL geschriebene Werte (intern in der Datenbank wird der Zeitstempel immer als UTC gespeichert). Wenn Sie die Sitzungszeitzone immer auf UTC einstellen, werden diese Konvertierungen deaktiviert. Warum also timestamptzüberhaupt verwenden? Anders ausgedrückt: Wenn die Werte in der Datenbank UTC sind und die in und aus der Datenbank eingehenden Werte immer UTC sind, warum hat Ihre Datenbank dann überhaupt eine Zeitzonenerkennung?
Shay Rojansky
2

Der dateZeitstempel enthält auch keine Zeitzoneninformationen, die jedoch von vielen Personen verwendet werden.

Natürlich ist das an sich keine Antwort.

Es ist gültig, timestampund datefür alle Zeitstempel und Datumsangaben zu verwenden, die sich immer in derselben Zeitzone befinden oder relativ zu einer bekannten Zeitzone gespeichert werden.

Wenn die Zeitzone immer gleich oder implizit ist, ist es eher ein Gegenmuster, sie zu speichern, als sie nicht zu speichern (redundante Informationen).

Zeitstempel können auch zum Speichern technischer Informationen verwendet werden, wie sie in Anwendungsprotokollen oder für Leistungsmessungen verwendet werden. In diesem Fall kann die Zeitzone auch unwichtig sein.


Wenn Sie dagegen ein verteiltes System entwerfen oder daran arbeiten oder sich in einem System befinden, in dem Teile des Systems auf verschiedene Zeitzonen verteilt sind, wird dies möglicherweise als nicht zu verwendendes Antimuster angesehen timestamp with timezone, obwohl einige Systeme möglicherweise für die Ausführung ausgelegt sind in einer Zeitzone, zB UTC. In diesem Fall wird die Zeitzonenlogik möglicherweise in die Anwendungsebene verschoben - aber ich würde dies als Anti-Pattern betrachten, ja.

Colin 't Hart
quelle
Ich verstehe, dass es in bestimmten Fällen nicht weh timestamp without timezonetut, es zu benutzen , aber kauft es mir jemals etwas? Ansonsten, warum sollte ich mich darum kümmern, wenn der timestamp with timezone dataTyp immer gleich oder passender ist?
Marcus Junius Brutus
Nicht redundante Informationen zu speichern, wäre mein Hauptargument. Ich nehme an, dass die Datumsberechnung timestamp without timezoneauch schneller ist, aber das ist wahrscheinlich nur wichtig, wenn Sie Milliarden von Zeilen verarbeiten ...
Colin 't Hart
1
@ Colin'tHart timestampund timestamptzwerden beide gleich gespeichert. In a werden keine Zeitzoneninformationen gespeichert timestamptz, sondern zum Speichern in UTC konvertiert. Ich würde sagen, immer verwenden, timestamptzwenn die fraglichen Zeitstempel die absolute Zeit bezeichnen . Das ist alles was timestamptzbedeutet. Ich habe darüber geschrieben hier .
Fphilipe
2

Das Speichern und Verarbeiten von Datums- und Uhrzeitangaben in der Ortszeit erscheint möglicherweise zeitaufwändig, wenn Ihre Bewerbung auf eine einzelne Zeitzone beschränkt ist. Ich halte dies jedoch für einen Fehler.

Beim Zurückschalten von Sommerzeit auf Standardzeit wird eine Stunde in Ortszeit wiederholt (vorausgesetzt, die Differenz beträgt eine Stunde). Wo ich wohne, geschieht dies normalerweise um 2 Uhr morgens, sodass die Ortszeit zwischen 01:58, 01:59 und 01:00 Uhr läuft und erst am Ende der wiederholten Stunde bis 02:00 Uhr vorrückt.

Wenn Sie versuchen, Ereignisse zeitlich nach Ortszeit zu ordnen, bedeutet dies, dass Ereignisse aus zwei verschiedenen Stunden miteinander vermischt werden und nicht in der Reihenfolge angezeigt werden, in der sie tatsächlich stattgefunden haben.

Zum Vergleich: UTC hat dieses Problem nicht und bestellt sauber. Selbst wenn Sie mit nur einer Zeitzone arbeiten, möchten Sie, dass die Datenbank die Zeiten in UTC speichert und verarbeitet und für die Eingabe / Anzeige in / von der Ortszeit konvertiert. Dies ist das Verhalten von TIMESTAMP WITH TIME ZONE.

Steve Fosdick
quelle