La classe Java.util.Date
Possède une méthode appelée toInstant()
qui convertit l'instance Date
en Java.time.Instant
.
La classe Java.sql.Date
Étend la classe Java.util.Date
, Mais lorsque j'essaie d'appeler toInstant()
sur un Java.sql.Date
, Je reçois un UnsupportedOperationException
.
Pourquoi toInstant()
est-elle une opération non prise en charge sur Java.sql.Date
?
Et quelle est la "bonne" façon de convertir un Java.sql.Date
En un Java.time.Instant
?
Vérifiez le JavaDoc
Puisque sql.Date
n'a pas de composante temporelle, il n'est pas possible de le convertir en time.Instant
Cette méthode lève toujours une exception UnsupportedOperationException et ne doit pas être utilisée car les valeurs de date SQL n'ont pas de composant d'heure.
Le mappage correct entre Java.sql.Date
et Java.time
est LocalDate
:
LocalDate date = sqlDate.toLocalDate();
Si vous devez vraiment, vous pouvez alors dériver un Instant
, bien que les informations supplémentaires (temps) seront arbitraires. Par exemple:
Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();
Java.sql.Date n'a que des composants Date (date, mois et année). Il n'a PAS les deux composants Date et heure. toInstant requiert les deux composants Date/Time, donc toInstant sur l'instance Java.sql.Date lève l'exception UnsupportedOperationException.
Java.util.Date OR Java.sql.Timestamp a les deux composants Date/Time donc toInstant () fonctionne!
Vous pouvez faire comme ça:
// Time is 00:00:00.000
new Java.util.Date(sqlDate.getTime()).toInstant()
Mise à jour:
Instant.ofEpochMilli(sqlDate.getTime());
// OR
new Java.util.Date(sqlDate.getTime()).toInstant();
Renvoie le même résultat car toInstant () appelle Instant.ofEpochMilli (getTime ()) en interne.
public Instant toInstant() {
return Instant.ofEpochMilli(getTime());
}
Les réponses données jusqu'à présent se concentrent sur le fait que Java.sql.Date
N'a pas d'informations sur l'heure. C'est correct mais ce n'est pas la raison réelle ou suffisante pour laquelle ce type ne peut pas offrir une conversion directe en Instant
. Malheureusement, la documentation de Java-8 fait la même erreur pour laisser les utilisateurs penser que le problème est simplement dû à des informations temporelles manquantes.
Conceptuellement, le type Java.sql.Date
Représente un type local. Il modélise une date de calendrier qui peut être différente dans n'importe quelle région de notre globe. Mais un Instant
est le même sur notre globe. Les utilisateurs ont donc besoin d'un fuseau horaire ou d'un décalage de fuseau horaire pour effectuer la conversion.
Tragiquement, le type Java.sql.Date
Hérite de Java.util.Date
Qui est un type global (instantané). Cependant, cet héritage dénote vraiment l'héritage d'implémentation, et non l'héritage de type. Une raison de plus pour considérer que la conception de ces anciennes classes JDBC est cassée. Il est donc en effet possible d'utiliser le hack pour encapsuler le Java.sql.Date
Via sa méthode getTime()
à l'intérieur d'une instance de Java.util.Date
Qui permet enfin la conversion directe en un instant. Mais: Cette conversion utilise implicitement le fuseau horaire par défaut du système.
Alors, comment convertir correctement de manière pédante? Considérons à nouveau la documentation de Java-8 qui pointe ici dans la bonne direction:
Java.sql.Date sqlDate = ...;
LocalDate calendarDate = sqlDate.toLocalDate();
ZonedDateTime zdt = calendarDate.atStartOfDay(ZoneId.of("Europe/Paris"));
Instant instant = zdt.toInstant();