LocalDateTime zu ZonedDateTime
Ich habe Java 8 Spring-web-app wird die Unterstützung mehrerer Regionen. Ich brauche, um Kalender events für Kunden vor Ort. So können sagen, meine web-und Postgres-server gehostet wird, ist in der Zeitzone MST (aber ich denke, es könnte überall sein, wenn wir gehen, cloud). Aber der Kunde ist in der EST. So, nach einigen best practices, die ich gelesen, ich dachte, ich würde store stammen alle Zeiten in UTC-format. Alle Datum-Zeit-Felder in der Datenbank deklariert sind, die als TIMESTAMP.
Also hier ist, wie ich eine LocalDateTime und konvertieren von UTC:
ZonedDateTime startZonedDT = ZonedDateTime.ofLocal(dto.getStartDateTime(), ZoneOffset.UTC, null);
//appointment startDateTime is a LocalDateTime
appointment.setStartDateTime( startZonedDT.toLocalDateTime() );
Nun , zum Beispiel, wenn eine Suche für ein Datum kommt, muss ich konvertieren vom angeforderten Datum, Uhrzeit in UTC, die Ergebnisse zu erhalten und zu konvertieren, um die Benutzer-Zeitzone (gespeichert in der db):
ZoneId userTimeZone = ZoneId.of(timeZone.getID());
ZonedDateTime startZonedDT = ZonedDateTime.ofLocal(appointment.getStartDateTime(), userTimeZone, null);
dto.setStartDateTime( startZonedDT.toLocalDateTime() );
Nun, ich bin nicht sicher, ob dies der richtige Ansatz. Ich Frage mich auch, wenn ich da bin, geht aus LocalDateTime zu ZonedDateTime und Umgekehrt, ich könnte Sie verlieren timezone info.
Hier bin ich zu sehen, und es scheint nicht richtig zu mir. Wenn ich die LocalDateTime von der Benutzeroberfläche aus, bekomme ich diese:
2016-04-04T08:00
Den ZonedDateTime =
dateTime=2016-04-04T08:00
offset="Z"
zone="Z"
Und wenn ich dann zuweisen, konvertiert werden, Wert zu meinem Termin LocalDateTime ich store:
2016-04-04T08:00
Fühle ich mich wie, weil ich bin die Speicherung in LocalDateTime ich verliere die Zeitzone, die ich umgewandelt in ZonedDateTime.
Sollte ich meine Person (Termin) verwenden ZonedDateTime statt LocalDateTime, so dass Postgres nicht Locker, dass Informationen?
---------------- Bearbeiten ----------------
Nach Basils ausgezeichnete Antwort, ich merkte, dass ich den Luxus haben, nicht die Pflege der Benutzer-Zeitzone - alle Termine sind auf einen bestimmten Ort, damit ich speichern kann, stammen alle Zeiten als UTC und dann konvertieren Sie Sie in das Standort-Zeitzone abgerufen werden. Ich habe die folgenden followup Frage
- Ihre app muss timezone Informationen?
- Bezüglich Ihrer "Bearbeiten" - Abschnitt, wissen, dass Politiker, die Liebe neu zu definieren, Zeitzonen-offsets, Daylight Saving Time (DST), etc. So gehen Sie nie zu weit in die Zukunft mit UTC-Werten. Wenn du meinst, dental-hygiene-Termine weit im Voraus, ex. "3 Uhr am 5. Dezember 2017 später in diesem Jahr", dann können Sie tatsächlich verwenden möchten
LocalDateTime
zu speichern, dass Tat. Der Absicht, es ist 3 Uhr, aber die Politiker haben neu definiert, der moment, indem dann. Für einen Zeitplan, die Sie möglicherweise vorübergehend gelten Zeit-zone, um das PotenzialLocalDateTime
zu generieren, die einen tatsächlichen moment als einZonedDateTime
/Instant
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Postgres hat keine solche Daten geben, wie
TIMESTAMP
. Postgres hat zwei Arten für Datum plus Zeit-von-Tag:TIMESTAMP WITH TIME ZONE
undTIMESTAMP WITHOUT TIME ZONE
. Diese Arten haben sehr unterschiedliche Verhalten in Bezug auf Zeit-zone Informationen.WITH
Typ verwendet eine Aufrechnung oder Informationen Zeitzone einstellen die Datum-Zeit UTC, dann entledigt sich der offset-oder Zeit-zone; Postgres nie speichert den offset - /- zone info.WITHOUT
Typ ignoriert offset-oder zone-info, die vorhanden sein können.Sie fast immer wollen die
WITH
Art, wie hier erklärt - Experte David E. Wheeler. DieWITHOUT
nur Sinn macht, wenn man die vage Idee eines Datum-Zeit eher als einen festen Punkt auf der Zeitleiste. Zum Beispiel, "in diesem Jahr zu Weihnachten beginnt bei 2016-12-25T00:00:00" gespeichert werden würde in derWITHOUT
da es gilt alle Zeit-zone, noch nicht wurde angewendet, um eine einzelne Zeit-zone, um eine tatsächliche moment auf der Zeitachse. Wenn Sie Santa ' s Elfen wurden tracking die Startzeit für Eugene Oregon USA, dann würden Sie denWITH
geben und einen Eingang, der inklusive einer offset-oder Zeit-zone, wie2016-12-25T00:00:00-08:00
welche gespeichert wird in Postgres als2016-12-25T08:00.00Z
(wo dieZ
bedeutet Zulu oder UTC).Den Gegenwert von Postgres'
TIMESTAMP WITHOUT TIME ZONE
in java.Zeit istjava.time.LocalDateTime
. Als Sie Ihre Absicht war, die Arbeit in UTC (was gut ist), sollten Sie nicht werden mitLocalDateTime
(schlecht). Das kann der Haupt-Punkt der Verwirrung und ärger für Sie. Sie denken über die Verwendung vonLocalDateTime
oderZonedDateTime
aber Sie sollten weder; stattdessen sollten Sie mit HilfeInstant
(siehe unten).In der Tat sind Sie. Den ganzen Punkt zu
LocalDateTime
ist verlieren Zeit-zone info. So, das wir selten verwenden diese Klasse in den meisten apps. Wieder, die Weihnachten Beispiel. Oder ein anderes Beispiel, "Gesellschaft-Politik: All unsere Fabriken auf der ganzen Welt nehmen das Mittagessen um 12:30 Uhr". Das wäreLocalTime
, und für ein bestimmtes DatumLocalDateTime
. Aber das hat keine wirkliche Bedeutung, nicht auf einen tatsächlichen Punkt auf der Zeitachse, bis Sie sich ein Zeit-zone, um eineZonedDateTime
. Dass Mittagspause wird an verschiedenen Punkten auf der Zeitachse in der Delhi-Fabrik als das Düsseldorfer Werk-und wieder anders bei den Detroit Fabrik.Das Wort "Lokale" in
LocalDateTime
kann counter-intuitive, wie es heißt keine besonderen Lokalität. Wenn Sie Lesen "Lokal" im name einer Klasse, denke "Nicht einen Augenblick... nicht auf der timeline... nur eine unscharfe Vorstellung über das kinda-sorta-Datum-Zeit".Dein Server sollte man fast immer auf UTC eingestellt, die in Ihrer Betriebssystem-Zeitzone. Aber die Programmierung sollte niemals davon abhängen, diese äußerlichkeit, wie es ist allzu leicht für einen sysadmin, es zu ändern oder für jede andere Java-Anwendung ändern, um die aktuelle Standard-Zeit-zone innerhalb der JVM. So geben Sie immer Ihre gewünschte/erwartete Zeitzone. (Gleiche gilt für
Locale
übrigens.)Fazit:
Während der Arbeit Tag, während das tragen Sie Ihre geek-hart, Hut, denken in UTC. Nur am Ende des Tages, wenn der Wechsel zu Ihrem Laie sollte gehen Sie zurück zu denken, der die lokale Zeit von Ihrer Stadt.
Ihre business-Logik konzentrieren sollte auf UTC. Ihr Datenbank-storage, business-Logik, data exchange, Serialisierung, logging, und Ihre eigenen Gedanken, sollte alles getan werden, in der UTC-Zeitzone (und 24-Stunden-Uhr, durch die Art und Weise). Bei der Darstellung von Daten an Benutzer, die nur dann Anwendung einer bestimmten Zeitzone. Denken Zonen-Datum-Zeiten als eine externe Sache, nicht ein arbeiten, ein Teil Ihrer app-Interna.
Auf der Java-Seite verwenden
java.Zeit.Instant
(einen moment auf der Zeitachse in UTC) in vielen Ihrer business-Logik.Hoffentlich JDBC Treiber eventuell aktualisiert werden, um deal mit java.Zeit-Typen wie
Instant
direkt. Bis dahin müssen wir nutzen java.sql-Typen. Die alten java.sql-Klasse haben neue Methoden für die Konvertierung von/aus java.Zeit.Nun passieren, dass
java.sql.TimeStamp
Objekt übersetTimestamp
auf einePreparedStatement
gespeichert werden, um eine Spalte definiert alsTIMESTAMP WITH TIME ZONE
in Postgres.Gehen in die andere Richtung:
So, dass leicht ist, geht aus
Instant
zujava.sql.Timestamp
zuTIMESTAMP WITH TIME ZONE
alle in UTC. Keine Zeitzonen beteiligt. Die aktuelle Standard-Zeitzone des server-OS, Ihre JVM, und Ihren Kunden, ist alle irrelevant.Präsentieren Sie auf Benutzer anwenden, die eine Zeitzone. Verwenden richtige Zeitzone Namen, nie die 3-4 Buchstaben-codes wie
EST
oderIST
.Können Sie einstellen, in eine andere zone, wie gebraucht.
Zurück zu bekommen, um eine
Instant
, einen moment auf der Zeitachse in UTC sind, können Sie extrahieren aus derZonedDateTime
.Nicht, wo es in Tat verwenden wir
LocalDateTime
.Wenn Sie tun, um ein Stück von Daten ohne offset von UTC oder die Zeitzone, wie
2016-04-04T08:00
, dass die Daten völlig nutzlos für Sie (vorausgesetzt, wir sprechen nicht über die Weihnachts-oder Unternehmen Mittagessen Szenarien diskutiert oben). Eine Datum-Zeit ohne offset/zone info ist wie ein Geldbetrag ohne Angabe Währung:142.70
oder sogar$142.70
-- nutzlos. AberUSD 142.70
oderCAD 142.70
oderMXN 142.70
... die sind nützlich.Wenn Sie tun bekommen, dass
2016-04-04T08:00
Wert, und Sie sind absolut sicher der beabsichtigten offset/zone Kontext, dann:LocalDateTime
.OffsetDateTime
oder (besser) anwenden einer Zeitzone um eineZonedDateTime
.Wie dieser code.
Deine Frage ist wirklich ein Duplikat von vielen anderen. Diese Themen wurden diskutiert, viele Male in anderen Fragen und Antworten. Ich fordere Sie auf Suche und Analyse Stack-Überlauf erfahren Sie mehr zu diesem Thema.
JDBC 4.2
Als der JDBC 4.2 wir können direkt von exchange - java.Zeit Objekte mit der Datenbank. Keine Notwendigkeit, immer verwenden
java.sql.Timestamp
wieder, noch die zugehörigen Klassen.Speicherung, Nutzung
OffsetDateTime
wie definiert in der JDBC-Spezifikation....oder vielleicht verwenden
Instant
direkt, wenn Sie unterstützt von Ihrem JDBC-Treiber.Abrufen.
Über java.Zeit
Den java.Zeit framework ist in Java 8 und höher. Diese Klassen verdrängen die lästige alte legacy Datum-Zeit-Klassen wie
java.util.Date
,Calendar
, &" = SimpleDateFormat
.Den Joda-Time Projekt, jetzt in Wartung-Modus, rät der migration auf die java.Zeit Klassen.
Um mehr zu erfahren, siehe die Oracle Tutorial. Und die Suche Stack Overflow für viele Beispiele und Erklärungen. Spezifikation JSR 310.
Können Sie exchange java.Zeit Objekte direkt mit Ihrer Datenbank. Verwenden Sie eine JDBC-Treiber kompatibel mit JDBC 4.2 oder später. Keine Notwendigkeit für Streicher, keine Notwendigkeit für
java.sql.*
Klassen.Wo erhalten Sie die java.Zeit-Klassen?
Den ThreeTen-Extra Projekt erweitert die java.mal mit zusätzlicher Klassen. Dieses Projekt ist ein Testgelände für mögliche künftige Erweiterungen zu java.Zeit. Sie finden möglicherweise einige nützliche Klassen, die hier wie
Interval
,YearWeek
,YearQuarter
, und mehr.