tl;dr
myPreparedStatement
.setObject(
… , // Specify which placeholder `?` in your SQL statement.
OffsetDateTime.now( ZoneOffset.UTC ) // Capture the current moment as seen in the wall-clock time of UTC (an offset-from-UTC of zero).
) ;
Vermeiden Sie veraltete Datums-/Uhrzeitklassen
Sie verwenden schreckliche Date-Time-Klassen, die vor Jahren durch java.time ersetzt wurden Klassen.
Verwenden Sie niemals Date
oder Timestamp
.
UTC
Erfassen Sie den aktuellen Moment in UTC. Die meisten Datenbanken speichern einen Moment in UTC. Und im Allgemeinen sollten Sie den Großteil Ihrer Geschäftslogik, Fehlersuche, Protokollierung, Speicherung und des Datenaustauschs in UTC durchführen.
OffsetDateTime
Stellen Sie einen Moment mit einem Offset von UTC dar, indem Sie den treffend benannten OffsetDateTime
verwenden Klasse.
Wir wollen UTC selbst oder einen Offset von Null. Dafür können wir eine Konstante verwenden, ZoneOffset.UTC
.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ) ;
JDBC 4.2
Ab JDBC 4.2 können wir java.time direkt austauschen Objekte mit der Datenbank.
Um diesen Moment in einer Spalte eines Datentyps zu speichern, der dem SQL-Standard TIMESTAMP WITH TIME ZONE
ähnelt :
myPreparedStatement.setObject( … , odt ) ;
Abruf:
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZonedDateTime
Um diesen abgerufenen Moment dem Benutzer zu präsentieren, möchten Sie möglicherweise die erwartete/gewünschte Zeitzone des Benutzers anpassen.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Verlassen Sie sich nie auf die Standardzeitzone
Beachten Sie im obigen Code, dass wir immer den gewünschten/erwarteten Offset oder die Zone angegeben haben.
Wenn Sie nichts angeben, wird ein Offset oder eine Zone stillschweigend implizit angewendet. Es ist besser, Ihre Absichten explizit anzugeben, da der aktuelle Standard Ihrer JVM, Datenbank und Ihres Host-Betriebssystems nicht in Ihren Händen als Programmierer liegt. Das bedeutet, dass sich Code, der sich auf die Standardeinstellung stützt, zur Laufzeit im Verhalten ändert.
Java 6 &7
Derselbe Mann, Stephen Colebourne, der JSR 310 und die java.time leitet Implementierung sowie die berühmte Joda-Time Projekt, leitet auch ein anderes Projekt, ThreeTen-Backport . Die meiste Zeit java.time Die Funktionalität ist in dieser Bibliothek auf Java 6 &7 zurückportiert, mit nahezu identischer API.
Erledigen Sie also Ihre ganze Arbeit in Back-Port-Klassen. Konvertieren Sie dann im letzten Moment nach/von java.sql.Timestamp
über DateTimeUtils
Klasse.
Diese Konvertierungsmethoden verwenden meistens Instant
Objekte. Ein Instant
ist ein Moment in UTC, immer in UTC. Sie können Ihre OffsetDateTime
anpassen in UTC durch Extrahieren eines Instant
. Der Instant
class ist die grundlegende Bausteinklasse in java.time , mit OffsetDateDate
mehr Flexibilität, wie z. B. alternative Formatierungsmuster beim Generieren einer Zeichenfolge. Aber beide Instant
und OffsetDateTime
repräsentieren einen Moment, einen Punkt auf der Zeitachse.
Instant instant = odt.toInstant() ;
java.sql.Timestamp ts = org.threeten.bp.DateTimeUtils.toSqlTimestamp( instant ) ;
In die andere Richtung gehen und einen Timestamp
abrufen aus Ihrer Datenbank und wird dann sofort in einen Instant
umgewandelt .
java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;
Instant instant = org.threeten.bp.DateTimeUtils.toInstant( ts ) ;
Über java.time
Der java.time
Framework ist in Java 8 und höher integriert. Diese Klassen ersetzen das lästige alte Legacy
Datumszeitklassen wie java.util.Date
, Calendar
, &SimpleDateFormat
.
Die Joda-Time Projekt, jetzt im Wartungsmodus , empfiehlt die Migration zu java.time Klassen.
Weitere Informationen finden Sie im Oracle-Tutorial . Und durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .
Sie können java.time austauschen Objekte direkt mit Ihrer Datenbank. Verwenden Sie einen JDBC-Treiber
kompatibel mit JDBC 4.2
oder später. Keine Notwendigkeit für Strings, keine Notwendigkeit für java.sql.*
Klassen.
Wo erhalte ich die java.time-Klassen?
- Java SE 8
, Java SE 9
, Java SE 10
, Java SE 11
, und höher – Teil der Standard-Java-API mit einer gebündelten Implementierung.
- Java 9 fügt einige kleinere Funktionen und Korrekturen hinzu.
- Java SE 6
und Java SE 7
- Die meiste Zeit java.time Die Funktionalität wird in ThreeTen-Backport auf Java 6 &7 zurückportiert .
- Android
- Spätere Versionen von Android-Bundle-Implementierungen von java.time Klassen.
- Für früheres Android (<26), ThreeTenABP Projekt adaptiert ThreeTen-Backport (oben erwähnt). Siehe How to use ThreeTenABP… .
Das ThreeTen-Extra
project erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen zu java.time. Möglicherweise finden Sie hier einige nützliche Klassen wie Interval
, YearWeek
, YearQuarter
, und mehr
.