UnsupportedOperationException-pourquoi ne pouvez-vous pas appeler toInstant() sur java.SQL.Date?

La classe java.util.Date a une méthode appelée toInstant() qui convertit l'instance Date en java.time.Instant.

Le java.sql.Date classe étend la java.util.Date classe, mais quand je tente d'appeler toInstant() sur java.sql.Date, j'ai un message d' UnsupportedOperationException.

Pourquoi toInstant() est-il une opération non prise en charge sur java.sql.Date?

Et quelle est la "bonne" façon de convertir un java.sql.Date pour un java.time.Instant?

30
demandé sur Andrew Mairose 2016-04-05 22:35:04

4 réponses

Vérifiez le JavaDoc

Puisque sql.Date n'a pas de Composant temps, il n'y a aucune possibilité de le convertir en time.Instant

Cette méthode lance toujours une exception UnsupportedOperationException et devrait ne pas être utilisé car les valeurs de date SQL n'ont pas de Composant time.

14
répondu Yassin Hajaj 2016-04-05 19:44:21

La bonne correspondance entre les java.sql.Date et java.time est LocalDate:

LocalDate date = sqlDate.toLocalDate();

Si vous devez vraiment, vous pouvez alors déduire un Instant, bien que les informations supplémentaires (temps) est arbitraire. Par exemple:

Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();
28
répondu assylias 2016-04-06 07:22:10

Java.SQL.Date n'a que des composants de Date (date, mois et année). Il n'a pas les deux composants Date et heure. toInstant nécessite les deux composants Date / Heure, donc toInstant sur java.SQL.L'instance de Date lance une exception UnsupportedOperationException.

Java.util.Date ou java.SQL.Timestamp a les deux composants Date / Heure donc toInstant () fonctionne!

, Vous pouvez faire comme ceci:

// 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();

Renverra le même résultat car toInstant () appelle Instantané.ofEpochMilli (getTime ()) en interne.

public Instant toInstant() {
    return Instant.ofEpochMilli(getTime());
}
17
répondu Loc 2018-04-23 19:51:05

Les réponses données jusqu'à présent se concentrent sur le détail que java.sql.Date n'a pas d'information temporelle. C'est correct mais 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 juste à cause 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 quel région de notre globe. Mais un Instant est le même sur notre globe autour. 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 {[6] } 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 de considérer que la conception de ces anciennes classes JDBC est brisée. Par conséquent, il est en effet possible d'utiliser le hack pour envelopper le java.sql.Date via son méthode getTime() à l'intérieur d'une instance de java.util.Date qui permet finalement 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();
11
répondu Meno Hochschild 2016-04-06 07:17:50