tl; dr
- Verwenden java.time Klassen statt Legacy
java.util.Date
& java.sql.Date
mit JDBC 4.2 oder höher.
- In/aus java.time konvertieren, wenn mit Code interagiert, der noch nicht auf java.time aktualisiert wurde.
Beispielabfrage mit .
myPreparedStatement.setObject(
… , // Specify the ordinal number of which argument in SQL statement.
myJavaUtilDate.toInstant() // Convert from legacy class `java.util.Date` (a moment in UTC) to a modern `java.time.Instant` (a moment in UTC).
.atZone(ZoneId.of("Africa/Tunis")) // Adjust from UTC to a particular time zone, to determine a date. Instantiating a `ZonedDateTime`.
.toLocalDate() // Extract a date-only `java.time.LocalDate` object from the date-time `ZonedDateTime` object.
)
Einzelheiten
Wenn Sie versuchen, mit Datum-Werte nur arbeiten (ohne Zeit-of-Tag, keine Zeitzone), verwenden Sie die LocalDate
Klasse statt java.util.Date
.
java.time
In Java 8 und später haben die lästigen alten Datum Zeitklassen gebündelt mit frühen Versionen von Java durch die neuen java.time package verdrängt worden. Siehe Oracle Tutorial. Ein großer Teil der Funktionalität wurde zurück auf Java 6 & 7 in ThreeTen-Backport und weiter an Android in ThreeTenABP angepasst.
A SQL data typeDATE
ist nur für Datum gedacht, ohne Uhrzeit und ohne Zeitzone. Java hatte nie genau solch eine Klasse † bis java.time.LocalDate
in Java 8. Erstellen wir einen solchen Wert, indem wir das heutige Datum einer bestimmten Zeitzone zuordnen (Zeitzone ist wichtig, um ein Datum zu bestimmen, da ein neuer Tag in Paris früher als in Montréal dämmert.) beispielsweise).
LocalDate todayLocalDate = LocalDate.now(ZoneId.of("America/Montreal")); // Use proper "continent/region" time zone names; never use 3-4 letter codes like "EST" or "IST".
An diesem Punkt können wir fertig sein. Wenn Ihr JDBC driver mit JDBC 4.2 spec übereinstimmt, sollten Sie in der Lage sein, einen LocalDate
über setObject
auf einem PreparedStatement
übergeben, um in einem SQL-DATE-Feld zu speichern.
myPreparedStatement.setObject(1 , localDate);
Ebenso verwenden ResultSet::getObject
aus einer SQL-DATE Spalte zu einem Java-Objekt LocalDate
zu holen. Wenn Sie die Klasse im zweiten Argument angeben, wird Ihr Code type-safe.
LocalDate localDate = ResultSet.getObject(1 , LocalDate.class);
Mit anderen Worten, diese ganze Frage ist unter JDBC 4.2 oder später irrelevant.
Wenn Ihr JDBC-Treiber auf diese Weise nicht funktioniert, müssen Sie auf die Konvertierung in die java.sql-Typen zurückgreifen.
zu java.sql.Date konvertieren
zu konvertieren, zu den alten Datum Zeitklassen haben neue Methoden. Wir können java.sql.Date.valueOf(…)
anrufen, um eine LocalDate
zu konvertieren.
java.sql.Date sqlDate = java.sql.Date.valueOf(todayLocalDate);
Und die andere Richtung gehen.
LocalDate localDate = sqlDate.toLocalDate();
Konvertieren von java.util.Date
Während Sie die alten Datum-Zeit-Klassen vermeiden sollen, können Sie gezwungen werden, wenn sie mit bestehendem Code arbeiten. Wenn ja, können Sie nach java.time konvertieren.
Gehen Sie durch die Instant
Klasse, die einen Moment auf der Timeline in UTC darstellt. Ein Instant
ähnelt in der Idee einem java.util.Date
. Beachten Sie jedoch, dass Instant
eine Auflösung von bis zu nanoseconds hat, während java.util.Date
nur milliseconds Auflösung hat.
Verwenden Sie zum Konvertieren neue Methoden, die zu den alten Klassen hinzugefügt wurden. Zum Beispiel java.util.Date.from(Instant)
und java.util.Date::toInstant
.
Um ein Datum zu bestimmen, benötigen wir den Kontext einer Zeitzone. Für jeden Moment variiert das Datum weltweit nach Zeitzone. Wenden Sie eine ZoneId
an, um eine ZonedDateTime
zu erhalten.
ZoneId zoneId = ZoneId.of ("America/Montreal");
ZonedDateTime zdt = ZonedDateTime.ofInstant (instant , zoneId);
LocalDate localDate = zdt.toLocalDate();
† Die java.sql.Date Klasse gibt vor, ohne Zeit-of-day date-nur zu sein, aber tatsächlich tut ein Time-of-Tag, bis Mitternacht Zeit angepasst. Verwirrend? Ja, die alten Date-Time-Klassen sind ein Durcheinander.
Sie ein ähnliches Problem hier finden http://stackoverflow.com/questions/12131068/error-casting-java-util-date -into-java-sql-date – Lem
Für mich stellte sich heraus, dass ich nicht konvertieren musste. Es gab einen 'import java.sql. *' In meinem Code, der die java.util.date überschrieb und somit Schwierigkeiten bei der Zuweisung von Datumswerten verursachte, die mit letzterem aber nicht dem ersten gut waren. HTH – HumanInDisguise
@DavidAckerman Verstehst du, dass ein java.util.Date ein Datum * und * eine Tageszeit ist, aber ein java.sql.Date ist nur ein Datum * ohne * eine Uhrzeit? (Tatsächlich gibt es eine Tageszeit, aber das wird ignoriert, ein schlechter Hack eines Klassenentwurfs). In SQL bedeutet "DATUM" nur Datum. –