Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Zeitzonen für Java-Datum und MySQL-Zeitstempel

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?

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 .