Was ist der Unterschied zwischen Instant und LocalDateTime?

256

Ich weiß das:

  • Instant ist eher eine "technische" Zeitstempeldarstellung (Nanosekunden) für die Berechnung.
  • LocalDateTime ist eher eine Datums- / Uhrzeitdarstellung einschließlich Zeitzonen für Menschen.

Letztendlich kann IMO beides als Typ für die meisten Anwendungsfälle verwendet werden. Beispiel: Derzeit führe ich einen Batch-Job aus, bei dem ich einen nächsten Lauf basierend auf Daten berechnen muss, und ich habe Probleme, Vor- / Nachteile zwischen diesen beiden Typen zu finden (abgesehen vom Präzisionsvorteil von Instant im Nanosekundenbereich und dem Zeitzonenteil) von LocalDateTime).

Können Sie einige Anwendungsbeispiele nennen, bei denen nur Instant oder LocalDateTime verwendet werden sollte?

Bearbeiten: Achten Sie auf falsch gelesene Dokumentationen für LocalDateTime in Bezug auf Genauigkeit und Zeitzone

Manuel Aldana
quelle
Instant ist elementarer und umschließt den Standard für die UTC. Für eine Cron-ähnliche Charge ist dies keine so logische Wahl.
Joop Eggen
37
Falsche Definition. LocalDateTimehat keine Zeitzone!
Basil Bourque

Antworten:

830

Tabelle aller Datums- und Uhrzeittypen in Java, sowohl moderne als auch ältere

tl; dr

Instantund LocalDateTimesind zwei völlig verschiedene Tiere: Eines repräsentiert einen Moment, das andere nicht.

  • Instant repräsentiert einen Moment, einen bestimmten Punkt in der Zeitleiste.
  • LocalDateTimerepräsentiert ein Datum und eine Uhrzeit. Ohne eine Zeitzone oder einen Versatz von UTC kann diese Klasse jedoch keinen Moment darstellen . Es repräsentiert potenzielle Momente in einem Bereich von etwa 26 bis 27 Stunden, dem Bereich aller Zeitzonen rund um den Globus.

Falsche Vermutung

LocalDateTime ist eher eine Datums- / Uhrendarstellung einschließlich Zeitzonen für Menschen.

Ihre Aussage ist falsch: A LocalDateTimehat keine Zeitzone . Keine Zeitzone zu haben, ist der ganze Punkt dieser Klasse.

Um diese Klasse zu zitieren 'doc:

Diese Klasse speichert oder repräsentiert keine Zeitzone. Stattdessen handelt es sich um eine Beschreibung des Datums, wie es für Geburtstage verwendet wird, kombiniert mit der Ortszeit, wie sie auf einer Wanduhr angezeigt wird. Es kann keinen Moment auf der Zeitachse ohne zusätzliche Informationen wie einen Versatz oder eine Zeitzone darstellen.

Bedeutet Local…also "nicht in Zonen unterteilt, kein Versatz".

Instant

Geben Sie hier die Bildbeschreibung ein

An Instantist ein Moment auf der Zeitachse in UTC , eine Anzahl von Nanosekunden seit der Epoche des ersten Moments von 1970 UTC (im Grunde genommen siehe Klassendokument für Details). Da der größte Teil Ihrer Geschäftslogik, Datenspeicherung und des Datenaustauschs in UTC erfolgen sollte, ist dies eine praktische Klasse, die häufig verwendet wird.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

OffsetDateTime

Geben Sie hier die Bildbeschreibung ein

Die Klassenklasse OffsetDateTimerepräsentiert einen Moment als Datum und Uhrzeit mit einem Kontext von einigen Stunden-Minuten-Sekunden vor oder hinter UTC. Der Versatzbetrag, die Anzahl der Stunden-Minuten-Sekunden, wird durch die ZoneOffsetKlasse dargestellt.

Wenn die Anzahl der Stunden-Minuten-Sekunden Null ist, OffsetDateTimerepräsentiert a einen Moment in UTC, der mit a identisch ist Instant.

ZoneOffset

Geben Sie hier die Bildbeschreibung ein

Die ZoneOffsetKlasse repräsentiert einen Versatz von UTC , eine Anzahl von Stunden-Minuten-Sekunden vor UTC oder hinter UTC.

A ZoneOffsetist nur eine Anzahl von Stunden-Minuten-Sekunden, nichts weiter. Eine Zone ist viel mehr und hat einen Namen und eine Historie von Änderungen am Versatz. Die Verwendung einer Zone ist daher immer der Verwendung eines bloßen Versatzes vorzuziehen.

ZoneId

Geben Sie hier die Bildbeschreibung ein

Eine Zeitzone wird durch die ZoneIdKlasse dargestellt.

In Paris bricht beispielsweise früher ein neuer Tag an als in Montréal . Wir müssen also die Zeiger der Uhr bewegen, um den Mittag (wenn die Sonne direkt über uns steht) für eine bestimmte Region besser wiederzugeben . Je weiter von der UTC-Linie in Westeuropa / Afrika nach Osten / Westen entfernt, desto größer ist der Versatz.

Eine Zeitzone ist ein Satz von Regeln für den Umgang mit Anpassungen und Anomalien, wie sie von einer lokalen Gemeinde oder Region praktiziert werden. Die häufigste Anomalie ist der allzu beliebte Wahnsinn, der als Sommerzeit (DST) bekannt ist .

In einer Zeitzone wird die Geschichte vergangener Regeln, gegenwärtiger Regeln und Regeln für die nahe Zukunft bestätigt.

Diese Regeln ändern sich häufiger als erwartet. Stellen Sie sicher, dass Sie die Regeln Ihrer Datums- / Uhrzeitbibliothek, normalerweise eine Kopie der 'tz'-Datenbank , auf dem neuesten Stand halten. In Java 8 ist es jetzt einfacher als je zuvor, auf dem neuesten Stand zu bleiben, da Oracle ein Timezone Updater Tool veröffentlicht .

Geben Sie einen richtigen Zeitzonennamen im Format Continent/Region, wie zum Beispiel America/Montreal, Africa/Casablancaoder Pacific/Auckland. Verwenden Sie niemals die Abkürzung für 2-4 Buchstaben wie ESToder, ISTda es sich nicht um echte Zeitzonen handelt, die nicht standardisiert und nicht einmal eindeutig (!) Sind.

Zeitzone = Versatz + Anpassungsregeln

ZoneId z = ZoneId.of( Africa/Tunis ) ; 

ZonedDateTime

Geben Sie hier die Bildbeschreibung ein

Stellen Sie sich ZonedDateTimekonzeptionell als Instantmit einem zugewiesenen vor ZoneId.

ZonedDateTime = (Instant + ZoneId)

So erfassen Sie den aktuellen Moment in der Wanduhrzeit, die von den Menschen einer bestimmten Region (einer Zeitzone) verwendet wird:

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 

Fast Ihr gesamtes Backend, Ihre Datenbank, Ihre Geschäftslogik, Ihre Datenpersistenz und Ihr Datenaustausch sollten sich in UTC befinden. Für die Präsentation für Benutzer müssen Sie sich jedoch auf eine vom Benutzer erwartete Zeitzone einstellen. Dies ist der Zweck der ZonedDateTimeKlasse und der Formatierungsklassen, die zum Generieren von String-Darstellungen dieser Datums- / Uhrzeitwerte verwendet werden.

ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ;                 // Standard ISO 8601 format.

Sie können Text in lokalisiertem Format mit generieren DateTimeFormatter.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;

mardi 30 avril 2019 à 23 h 22 min 55 s heure de l'Inde

LocalDate, LocalTime,LocalDateTime

Diagramm, das nur einen Kalender für ein <code> LocalDate </ code> zeigt.

Diagramm, das nur eine Uhr für eine <code> LocalTime </ code> zeigt.

Diagramm mit einem Kalender plus Uhr für eine <code> LocalDateTime </ code>.

Die „local“ Datum Zeitklassen, LocalDateTime, LocalDate, LocalTime, sind eine andere Art von Lebewesen. Sie sind nicht an einen Ort oder eine Zeitzone gebunden. Sie sind nicht an die Zeitachse gebunden. Sie haben keine wirkliche Bedeutung, bis Sie sie auf einen Ort anwenden, um einen Punkt auf der Zeitachse zu finden.

Das Wort "Lokal" in diesen Klassennamen kann für Uneingeweihte kontraintuitiv sein. Das Wort bedeutet jeden Ort oder jeden Ort, aber keinen bestimmten Ort.

Daher werden für Geschäftsanwendungen die "lokalen" Typen nicht häufig verwendet, da sie nur die allgemeine Vorstellung eines möglichen Datums oder einer möglichen Uhrzeit darstellen, nicht eines bestimmten Zeitpunkts auf der Zeitachse. Business-Apps kümmern sich in der Regel um den genauen Zeitpunkt, zu dem eine Rechnung eingeht, ein Produkt für den Transport versendet wird, ein Mitarbeiter eingestellt wurde oder das Taxi die Garage verließ. Daher verwenden Entwickler von Geschäftsanwendungen Instantund ZonedDateTimeKlassen am häufigsten.

Wann würden wir also verwenden LocalDateTime? In drei Situationen: Wenn wir ein bestimmtes Datum und eine bestimmte Uhrzeit auf mehrere Standorte anwenden möchten, wenn wir Termine buchen oder wenn wir eine beabsichtigte, aber unbestimmte Zeitzone haben. Beachten Sie, dass keiner dieser drei Fälle ein bestimmter Punkt auf der Zeitachse ist. Keiner dieser Fälle ist ein Moment.

Eine Tageszeit, mehrere Momente

Manchmal möchten wir eine bestimmte Tageszeit an einem bestimmten Datum darstellen, diese jedoch auf mehrere Orte in verschiedenen Zeitzonen anwenden.

Zum Beispiel ist "Weihnachten beginnt am 25. Dezember 2015 um Mitternacht" ein LocalDateTime. Mitternachtsstreiks in Paris zu anderen Zeitpunkten als in Montréal und wieder anders in Seattle und Auckland .

LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ;   // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ;  // Xmas morning anywhere. 

Ein weiteres Beispiel: "Die Acme Company hat die Richtlinie, dass die Mittagszeit in jeder ihrer Fabriken weltweit um 12:30 Uhr beginnt LocalTime." Um eine echte Bedeutung zu haben, müssen Sie sie auf die Zeitachse anwenden, um den Moment von 12:30 in der Stuttgarter Fabrik oder 12:30 in der Rabat- Fabrik oder 12:30 in der Sydney- Fabrik zu berechnen .

Buchungstermine

Eine andere Situation LocalDateTimeist die Buchung zukünftiger Veranstaltungen (z. B. Zahnarzttermine). Diese Termine könnten in Zukunft weit genug entfernt sein, dass Sie das Risiko eingehen, dass Politiker die Zeitzone neu definieren. Politiker geben oft wenig oder gar keine Warnung. Wenn Sie "15.00 Uhr am 23. Januar" meinen, unabhängig davon, wie die Politiker mit der Uhr spielen, können Sie keinen Moment aufzeichnen - das würde bedeuten, dass 15.00 Uhr zu 14.00 Uhr oder 16.00 Uhr wird, wenn diese Region die Sommerzeit einführt oder fallen lässt. beispielsweise.

Speichern Sie für Termine a LocalDateTimeund a ZoneId, die separat aufbewahrt werden. Später, wenn Sie einen Zeitplan erstellen, bestimmen Sie spontan einen Moment, indem Sie aufrufen LocalDateTime::atZone( ZoneId ), um ein ZonedDateTimeObjekt zu generieren .

ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.

Bei Bedarf können Sie auf UTC einstellen. Extrahieren Sie eine Instantaus dem ZonedDateTime.

Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.

Unbekannte Zone

Einige Personen verwenden sie möglicherweise LocalDateTimein einer Situation, in der die Zeitzone oder der Versatz unbekannt ist.

Ich halte diesen Fall für unangemessen und unklug. Wenn eine Zone oder ein Versatz beabsichtigt, aber unbestimmt ist, haben Sie schlechte Daten. Das wäre so, als würde man einen Produktpreis speichern, ohne die beabsichtigte Währung zu kennen. Keine gute Idee.

Alle Datums- und Uhrzeittypen

Der Vollständigkeit halber finden Sie hier eine Tabelle aller möglichen Datums- und Uhrzeittypen, sowohl moderne als auch ältere in Java, sowie diejenigen, die durch den SQL-Standard definiert sind. Dies kann dazu beitragen, die Instant& LocalDateTimeKlassen in einen größeren Kontext zu stellen.

Tabelle aller Datums- und Uhrzeittypen in Java (sowohl modern als auch Legacy) sowie SQL-Standard.

Beachten Sie die ungeraden Entscheidungen, die das Java-Team beim Entwerfen von JDBC 4.2 getroffen hat. Sie haben sich dafür entschieden, alle java.time- Zeiten zu unterstützen… mit Ausnahme der beiden am häufigsten verwendeten Klassen: Instant& ZonedDateTime.

Aber keine Sorge. Wir können leicht hin und her konvertieren.

Konvertieren Instant.

// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

Konvertieren ZonedDateTime.

// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ; 

Über java.time

Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie java.util.Date, Calendar, & SimpleDateFormat.

Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .

Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .

Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für java.sql.*Klassen.

Woher bekomme ich die java.time-Klassen?

Tabelle, welche java.time-Bibliothek mit welcher Java- oder Android-Version verwendet werden soll

Das ThreeTen-Extra- Projekt erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von java.time. Sie können einige nützliche Klassen hier wie finden Interval, YearWeek, YearQuarter, und mehr .

Basil Bourque
quelle
39
Gute Antwort. Ich denke, einige Verwirrung (zumindest meine) kommt von der LocalBenennung. Meine Intuition für LocalMittel in Bezug darauf, wo ich bin UND wann ich bin (?!), Was mich glauben lässt, dass es tatsächlich das ZonedDateTimeist , was a ist.
Mkobit
4
Ja, es ist verwirrend. Aus diesem Grund hat java.time dem DateTimeKlassennamen seines Vorgängers Joda-Time (Produzieren ZonedDateTime) geschickt das Wort 'Zoned' hinzugefügt , um den Unterschied zu den "lokalen" Klassen hervorzuheben . Stellen Sie sich den Namen "Lokal" als Abkürzung für "auf einen bestimmten Ort angewendet werden müssen" vor.
Basil Bourque
2
Das Präfixieren des Wortes war Localmöglicherweise auch eine Möglichkeit, sich vom Paket java.util zu unterscheiden, obwohl ich irgendwie der Meinung bin, dass es eine bessere Wortwahl geben könnte.
Vphilipnyc
2
@simonh Im Gegenteil… Wenn dieser neue Mitarbeiter seine Einstellungspapiere unterschreibt, in denen seine Leistungen einschließlich der Lebensversicherung definiert sind, und dann neue Mitarbeiter für einen Kaffee nach draußen gehen, um von einem Lastwagen angefahren und getötet zu werden, wird es viele Menschen wie diese geben als Personalmanager, Versicherungsagenten und Anwälte, die genau wissen möchten, wann diese neue Beschäftigung in Kraft getreten ist.
Basil Bourque
2
@simonh Ja, es gibt Fälle, in denen das "lokale" Datum und die Uhrzeit angemessen sind. Neben den in meiner Antwort erwähnten Fällen besteht ein weiterer häufiger Fall in der Wirtschaft darin, dass Termine mehr als ein paar Monate in der Zukunft vereinbart werden, weit genug entfernt, dass Politiker die Zeitzonenregeln ändern können, normalerweise mit wenig Vorwarnung. Politiker nehmen diese Änderungen häufig vor, z. B. das Ändern der Daten beim Ein- und Ausschalten der Sommerzeit (DST) oder das permanente Ein- und Ausschalten der Sommerzeit.
Basil Bourque
20

Ein Hauptunterschied ist der LocalTeil von LocalDateTime. Wenn Sie in Deutschland leben und eine LocalDateTimeInstanz erstellen und jemand anderes in den USA lebt und im selben Moment eine andere Instanz erstellt (vorausgesetzt, die Uhren sind richtig eingestellt), ist der Wert dieser Objekte tatsächlich unterschiedlich. Dies gilt nicht für Instant, die unabhängig von der Zeitzone berechnet wird.

LocalDateTimespeichert Datum und Uhrzeit ohne Zeitzone, aber der Anfangswert ist zeitzonenabhängig. Instantist nicht.

Darüber hinaus LocalDateTimestellt Methoden zur Manipulation von Datum Komponenten wie Tage, Stunden, Monate. Ein Instantnicht.

Abgesehen von dem Nanosekunden-Präzisionsvorteil von Instant und dem Zeitzonenteil von LocalDateTime

Beide Klassen haben die gleiche Genauigkeit. LocalDateTimespeichert keine Zeitzone. Lesen Sie javadocs gründlich durch, da Sie mit solchen ungültigen Annahmen möglicherweise einen großen Fehler machen: Instant und LocalDateTime .

Dariusz
quelle
Entschuldigung für das falsche Lesen des Teils auf Zone + Präzision. Entschuldigen Sie die Wiederholung des obigen Beitrags: In Anbetracht einer einzelnen Zeitzonenanwendung, in welchen Anwendungsfällen würden Sie LocalDateTime bevorzugen oder umgekehrt?
Manuel Aldana
1
Ich würde LocalDateTime nehmen, wann immer ich Daten und / oder Zeiten benötige. In Stunden, Minuten oder so. Ich würde Instant verwenden, um beispielsweise Ausführungszeiten zu messen oder ein internes Feld von etw zu speichern, das dann und dort passiert. Wie in Ihrem Fall die nächsten Läufe berechnen? LocalDateTime scheint angemessen, aber es ist eine Meinung. Wie Sie sagten, können beide verwendet werden.
Dariusz
Können Sie mehr näher darauf eingehen LocalDateTime stores date and time without timezone, but it's initial value is timezone dependent? Was ist der Anfangswert und wie ist er zeitzonenabhängig? Vielen Dank.
Max
12

Sie irren sich LocalDateTime: Es speichert keine Zeitzoneninformationen und hat eine Nanosekundengenauigkeit. Zitat des Javadoc (Schwerpunkt Mine):

Eine Datums- und Uhrzeit ohne Zeitzone im ISO-8601-Kalendersystem , z. B. 2007-12-03T10: 15: 30.

LocalDateTime ist ein unveränderliches Datums- / Uhrzeitobjekt, das eine Datums- / Uhrzeitdarstellung darstellt und häufig als Jahr-Monat-Tag-Stunde-Minute-Sekunde angesehen wird. Auf andere Datums- und Zeitfelder wie Tag des Jahres, Wochentag und Woche des Jahres kann ebenfalls zugegriffen werden. Die Zeit wird mit Nanosekundengenauigkeit dargestellt . Beispielsweise kann der Wert "2. Oktober 2007 um 13: 45.30.123456789" in einer LocalDateTime gespeichert werden.

Der Unterschied zwischen den beiden besteht darin, dass Instantsie einen Versatz gegenüber der Epoche (01-01-1970) darstellen und als solcher einen bestimmten Zeitpunkt auf der Zeitachse darstellen. Zwei InstantObjekte, die gleichzeitig an zwei verschiedenen Orten der Erde erstellt wurden, haben genau den gleichen Wert.

Tunaki
quelle
In welchen Anwendungsfällen würden Sie in Anbetracht einer einzelnen Zeitzonenanwendung LocalDateTime bevorzugen oder umgekehrt?
Manuel Aldana
3
@manuelaldana Es ist eher Geschmackssache. Ich würde LocalDateTime für alles Benutzerbezogene (Geburtstag ...) und Instant für alles Maschinenbezogene (Ausführungszeit ...) bevorzugen.
Tunaki
2
@manuelaldana Eine einzelne Zeitzonen-App ist selten, wenn nicht gar nicht vorhanden. Sie könnten Zeitzonen für eine kleine App ignorieren, die Sie für Ihren örtlichen Barock-Musikclub entwickelt haben. Sobald Sie jedoch ein Ereignis für Personen veröffentlichen müssen, die reisen (und Zeitzonen überqueren), möchten sie, dass diese Daten an eine Zeitzone gebunden sind, damit sich ihre Kalender-App nach Bedarf anpassen kann. Ich schlage vor, Sie lernen, in all Ihren Apps richtig mit Zeitzonen zu arbeiten.
Basil Bourque
@Tunaki Ihre Verwendung des Wortes "Offset" im letzten Absatz lenkt ab. Dieses Wort hat eine bestimmte Bedeutung in der Datums- und Uhrzeitarbeit, daher könnte seine Verwendung hier in diesem Zusammenhang nicht hilfreich sein.
Basil Bourque
0

Instant entspricht der Zeit auf dem Nullmeridian (Greenwich).

In LocalDateTimeBezug auf die Zeitzoneneinstellungen des Betriebssystems und

kann keinen Moment ohne zusätzliche Informationen wie einen Versatz oder eine Zeitzone darstellen.

user2418306
quelle
2
Instant basiert auf UTC, nicht auf GMT.
Torsten Ojaperv