Von dem JavaDoc von java.sql.Date
:
Ein dünner Wrapper um einen Millisekunden-Wert, mit dem JDBC dies als SQL-DATE-Wert identifizieren kann. Ein Millisekundenwert gibt die Anzahl der Millisekunden an, die seit dem 1. Januar 1970 00: 00: 00.000 GMT vergangen sind.
Um der Definition von SQL DATE zu entsprechen, müssen die von einer
java.sql.Date
-Instanz eingeschlossenen Millisekunden-Werte 'normalisiert' werden, indem die Stunden, Minuten, Sekunden und Millisekunden in der bestimmten Zeitzone, in der sich die Instanz befindet, auf Null gesetzt werden verbunden.
Erläuterung: A java.util.Date
steht für Datum und Uhrzeit, ein java.sql.Date
steht nur für ein Datum (das Komplement von java.sql.Date ist java.sql.Time
, das nur eine Uhrzeit darstellt, aber auch java.util.Date
) erweitert.
Diese Antworten scheinen teilweise veraltet zu sein.
Ich habe gerade ein wenig API Code (Java Version 1.8.0_91) gelesen und in java.sql.Date
gefunden:
Die Methode zur Normalisierung der Zeit ist immer noch da und selbst der Kommentar sagt, dass die Zeit auf 00:00:00 GMT normalisiert wird, aber das tut nichts. Aus irgendeinem Grund haben sie die Normalisierung entfernt, was bedeutet, dass ein java.sql.Date
genau wie ein java.util.Date
nur die Anzahl der Millisekunden seit dem 1.1.1970 enthält. Es gibt also eine Zeitkomponente, die aber nicht extern angezeigt wird.
Zum Beispiel der Code
%Vor%erzeugt die Ausgabe
%Vor%Seien Sie also vorsichtig mit SQL-Daten und behandeln Sie sie nicht so, als würden sie nur eine Datums- und keine Zeitinformation enthalten. Zum Beispiel:
%Vor%druckt:
%Vor%java.sql.Date akzeptiert eine lange Ganzzahl, die die Anzahl der Millisekunden seit dem 1. Januar 1970 darstellt. Wenn die angegebene Zahl negativ ist, bezieht sie sich auf die Zeit vor dem 1. Januar 1970. Denken Sie daran, dass der eingekapselte Wert im Objekt nur Datum darstellt wie 1. Januar 1970 und keine Zeit Informationen gespeichert werden.
java.util.Date speichert sowohl Datums- als auch Zeitinformationen. Es wird häufiger verwendet als java.sql.Date.
java.util.Date
Die java.util.Date
Klasse ist Teil des alten Datums Zeitklassen, die sich als schlecht entworfen, verwirrend und problematisch erwiesen haben. Die Absicht ist, einen Moment ( ein Datum und eine Tageszeit ) auf der Timeline darzustellen.
Die Klasse scheint einen Moment in UTC darzustellen, außer dass ihre Methode toString
stillschweigend die aktuelle Standardzeitzone der JVM anwendet, während sie den String erzeugt, der die Illusion erzeugt, dass java.util.Date eine Zeitzone hat, aber tatsächlich tut nicht. Nun, eigentlich hat eine Zeitzone, die tief im Quellcode zugewiesen ist, die intern für etwas verwendet wird, aber nicht offensichtlich und nicht einstellbar oder getable. Ein verwirrendes Chaos.
java.sql.Date
Die java.sql.Date
macht eine schlechte Situation durch die Darstellung noch schlimmer der a Nur-Datum-Wert (wie in "DATE" in der SQL-Datenbankwelt a>) aber tat dies als ein Hack durch die Erweiterung java.util.Date
. Aber Sie sollten so tun, als wäre es nicht eine Unterklasse, wie in der Klasse doc. Darüber hinaus hat es Tageszeit, täuscht aber vor, nicht auf den ersten Moment des Tages in UTC zu reagieren. Ein verwirrendes Chaos.
Und noch eine Sache ... Die Klasse java.sql.Date
wird in Sekundenbruchteilen mit einer Auflösung von Nanosekunden hinzugefügt. Das geht über die von java.util.Date verwendete Millisekunden Auflösung hinaus. Viele Datenbanken unterstützen feinere Auflösungen wie Mikrosekunde oder Nanosekunde.
In diesen alten Datum-Zeit-Klassen gibt es keine Möglichkeit, einen reinen Datumswert ohne Tages- oder Zeitzone darzustellen.
Das java.time -Framework kommt zur Rettung . Inspiriert von dem äußerst erfolgreichen Projekt Joda-Time . Errichtet in Java 8 und später. Back-portiert nach Java 6 & amp; 7 und außerdem an Android angepasst . Siehe Oracle-Lernprogramm .
Instant
Die Klasse Instant
repräsentiert einen Moment auf der Timeline in UTC mit einer Auflösung von Nanosekunden. Klar und einfach.
instant.toString () → 2016-06-19T02: 34: 55.564Z
Wenn ein java.util.Date
für die Verwendung mit altem Code benötigt wird, können Sie konvertieren. Siehe neue Methoden, die zur alten Klasse hinzugefügt wurden: java.util.Date :: toInstant () und java.util.Date.from (Instant) .
Um die Uhrzeit einer bestimmten Stelle anzupassen, wenden Sie ein offset-from-UTC ( ZoneOffset
), um eine OffsetDateTime
Objekt. Wenn Sie den richtigen Zeitzonennamen kennen, wenden Sie eine ZoneId
ZonedDateTime
zu erhalten.
Zum Beispiel America/Montreal
liegt vier Stunden hinter UTC im Sommer unter Sommerzeit (DST) , so sehen wir 22:00 Uhr am vorherigen Datum im folgenden Code anstatt 2 AM im obigen Beispiel. Zurück gehen vier Stunden über Mitternacht in das vorherige Datum. Aber sowohl das instant
-Objekt, das oben gesehen wurde, als auch das zdt
-Objekt, das als nächstes zu sehen ist, repräsentieren dasselbe gleichzeitige Moment auf der Timeline. Derselbe Moment in der Geschichte, aber ist "morgen" in Paris, Kalkutta und Auckland während "gestern" in Montréal, Mexiko City und Honolulu.
zdt.toString () → 2016-06-18T22: 34: 55.564-04: 00 [Amerika / Montreal]
LocalDate
Verwenden Sie für einen reinen Datumswert die LocalDate
Klasse. Keine Uhrzeit oder Zeitzone wird beibehalten.
Beachten Sie jedoch, dass eine Zeitzone für die Festlegung eines Datums entscheidend ist , da das Datum für jeden beliebigen Zeitpunkt weltweit nach Zeitzone variieren kann. Daher die obige Diskussion über die Angabe einer Zeitzone. Sehen Sie sich zum Beispiel an, wie wir das 18. von Juni statt des 19. erhalten.
localDate.toString () → 2016-06-18
Wenn diese Unterscheidung zwischen Daten nach Zeitzone für Ihr Unternehmen von Bedeutung ist, sollten Sie einen Datum-Uhrzeit-Wert verwenden, der in einem Datenbankspalte-Typ von TIMESTAMP WITH TIME ZONE
gespeichert ist, anstatt von DATE
.
Search Stack Overflow für viel mehr Informationen und viele Beispiele für java.time (tag: java-time
).
Speichern Sie also in einer Datenbank eine JDBC Treiber gemäß JDBC 4.2 Spezifikation (siehe Leitfaden ). Rufen Sie setObject
und getObject
auf PreparedStatement
direkt an Verwenden Sie die Objekte java.time.
Wenn Ihr JDBC-Treiber eine solche direkte Verwendung der java.time-Typen noch nicht unterstützt, verwenden Sie die den alten Klassen hinzugefügten neuen Methoden , um die Konvertierung zu erleichtern. Aber minimieren Sie Ihre Verwendung der alten Klassen; konvertiere sofort in java.time und verwende nur java.time-Objekte in deiner Geschäftslogik.
%Vor%Und die andere Richtung.
%Vor%