Quelle est la meilleure façon de convertir un java.util.Date
objet vers le nouveau JDK 8 / JSR-310 java.time.LocalDate
?
Date input = new Date();
LocalDate date = ???
Réponse courte
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
Explication
Malgré son nom, java.util.Date
représente un instant sur la ligne du temps, pas une "date". Les données réelles stockées dans l'objet sont un long
décompte des millisecondes depuis le 1970-01-01T00: 00Z (minuit au début de 1970 GMT / UTC).
La classe équivalente à java.util.Date
JSR-310 est Instant
, il existe donc une méthode pratique toInstant()
pour fournir la conversion:
Date input = new Date();
Instant instant = input.toInstant();
Une java.util.Date
instance n'a pas de concept de fuseau horaire. Cela peut sembler étrange si vous appelez toString()
un java.util.Date
, car le toString
est relatif à un fuseau horaire. Cependant, cette méthode utilise en fait le fuseau horaire par défaut de Java à la volée pour fournir la chaîne. Le fuseau horaire ne fait pas partie de l'état réel de java.util.Date
.
Un Instant
ne contient pas non plus d'informations sur le fuseau horaire. Ainsi, pour convertir une Instant
date en date locale, il est nécessaire de spécifier un fuseau horaire. Il peut s'agir du fuseau par défaut - ZoneId.systemDefault()
- ou il peut s'agir d'un fuseau horaire contrôlé par votre application, tel qu'un fuseau horaire issu des préférences de l'utilisateur. Utilisez la atZone()
méthode pour appliquer le fuseau horaire:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
Un ZonedDateTime
contient un état composé de la date et de l'heure locales, du fuseau horaire et du décalage par rapport à GMT / UTC. En tant que telle, la date - LocalDate
- peut être facilement extraite en utilisant toLocalDate()
:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDate date = zdt.toLocalDate();
Réponse de Java 9
Dans Java SE 9, une nouvelle méthode a été ajoutée qui simplifie légèrement cette tâche:
Date input = new Date();
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
Cette nouvelle alternative est plus directe, créant moins de déchets et devrait donc être plus performante.
LocalDate.from(Instant.ofEpochMilli(date.getTime()))
je pense que c'est équivalent au vôtre, mais plus direct.Date
n'a pas de concept de fuseau horaire,Instant
ne contient pas non plus d'informations sur le fuseau horaire. L'LocalDate
API dit "Une date sans fuseau horaire". Alors pourquoi convertir deDate
àInstant
enLocalDate
besoinsatZone(ZoneId.systemDefault())
?LocalDate
etLocalDateTime
ne pas "stocker ou représenter un fuseau horaire" (ref: javadocs). Bien qu'ils ne les stockent pas, les classes représentent uneLocal
date et / ou une heure, donc la conversion en date / heure locale implique un fuseau horaire.La meilleure façon est:
Avantages de cette version:
fonctionne quelle que soit l'entrée est une instance de
java.util.Date
ou c'est une sous-classe dejava.sql.Date
(contrairement à la manière de @ JodaStephen). Ceci est courant avec les données d'origine JDBC.java.sql.Date.toInstant()
lève toujours une exception.c'est la même chose pour JDK8 et JDK7 avec backport JSR-310
J'utilise personnellement une classe utilitaire (mais elle n'est pas compatible avec le backport):
La
asLocalDate()
méthode ici est null-safe, utilisetoLocalDate()
, si l'entrée estjava.sql.Date
(elle peut être remplacée par le pilote JDBC pour éviter les problèmes de fuseau horaire ou les calculs inutiles), sinon utilise la méthode susmentionnée.la source
DateConvertUtils
.Date.toInstant()
.la source
SimpleDateFormat
instance est limitée au thread actuel. Il est utilisé d'une manière thread-safe. Maintenant,SimpleDateFormat
est réputé être «cher à instancier» (en raison de toutes les structures de données internes dont il a besoin) mais vous ne pouvez pas en partager un en tant que «singleton» (sans synchroniser l'accès à celui-ci), car il n'est en effet pas thread- sûr. (UneThreadLocal
solution peut fonctionner si le code "polluant"Thread
dans celui-ci était responsable du cycle de vie du thread ... mais cela arrive rarement). Gênant. L'évitementSimpleDateFormat
est la raison de l'utilisationjavax.time
.SimpleDateFormat
(qui est jeté), la chaîne intermédiaire (qui est jetée) et le coût de l'analyse. C'est une solution, mais non recommandée.Si vous utilisez Java 8, la réponse de @ JodaStephen est évidemment la meilleure. Cependant, si vous travaillez avec le backport JSR-310 , vous devez malheureusement faire quelque chose comme ceci:
la source
la source
Vous pouvez convertir en une seule ligne:
la source
tout d'abord, il est facile de convertir une date en instantané
Ensuite, vous pouvez convertir l'instantané en n'importe quelle API de date dans jdk 8 en utilisant la méthode ofInstant ():
la source
import java.sql.Date
dans votre dossier: latoInstant()
méthode desjava.sql.Date
toujours lance.L'
Date
instance contient également l'heure ainsi que la date alors que ceLocalDate
n'est pas le cas. Ainsi, vous pouvez d'abord le convertir enLocalDateTime
utilisant sa méthode,ofInstant()
puis si vous le souhaitez sans temps, convertissez l'instance enLocalDate
.la source
ce format est de
Date#tostring
la source
J'ai eu des problèmes avec l'implémentation de @ JodaStephen sur JBoss EAP 6. J'ai donc réécrit la conversion en suivant le tutoriel Java d'Oracle dans http://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html .
la source
Quel est le problème avec cette 1 ligne simple?
la source
J'ai résolu cette question avec la solution ci-dessous
Dans ce cas localDate imprimez votre date dans ce format "aaaa-MM-jj"
la source
java.time
classes en JDK8, pas avec Joda Time.