Le pourquoi du comment
L'une des grandes nouveautés de Java 8 à ne surtout pas louper est notamment le nouveau package permettant le traitement des Dates. Afin de bien comprendre pourquoi notre traditionnel java.util.Date
a été remplacé, il va falloir ouvrir les yeux sur les défauts qu'on lui a pardonnés pendant des années, sans vraiment oser se l'avouer.
Tout d'abord, la classe java.util.Date
faisait à moitié le travail :
La séparation Jour / Heure n'était pas présente, ce qui posait des soucis lorsque l'on calculait le J-1 d'une date lors d'un changement d'horaire d'été/hiver,
La plupart des méthodes sont
deprecated
, on se sentait à l'étroit.
L'utilisation de la classe java.text.SimpleDateFormat
devenait un véritable supplice... Deux solutions s'offraient à nous :
Déclarer le formateur comme variable membre
static final
, mais seul le vieux sage connaissait sa limitation ThreadSafe,Créer le parseur lors de son utilisation, la rendant ainsi ThreadSafe, mais surchargeant inutilement le tas d'objets à supprimer.
À noter au passage que les packages ne sont pas unifiés. Un coup c'est le package java.util
, un coup c'est le package java.text
. Le petit malin notera qu'il n'est pas évident de savoir que les objets de ces packages sont en relation avec la notion de date.
Vous avez certainement eu d'autres déconvenues avec ces librairies, il était temps que cela change...
La gestion des dates
Pour faire simple et court, la classe java.util.Date
a été découpée en plusieurs classes en fonction des besoins :
java.time.LocalDate
permet de gérer des dates uniquement (pas les heures) et sans gestion de fuseau horaire.java.time.LocalTime
permet de gérer des heures uniquement (sans date) et sans gestion de fuseau horaire.java.time.LocalDateTime
permet de gérer des dates avec heures et sans gestion de fuseau horaire.java.time.Clock
permet de gérer des dates avec heures et avec gestion de fuseau horaire.
Il y a plein d'autres classes, chacune ayant son périmètre fonctionnel : Duration, Period, Year, YearMonth, ZonedDateTime
, etc... Il serait faux de faire une correspondance entre un existant et son équivalent JDK8. Traduire Date
par Clock
serait trop rapide. Il serait souhaitable de prendre en considération l'utilisation réelle que l'on faisait de cette fameuse classe java.util.Date
.
Le formatage des dates
Mais que devient notre java.text.SimpleDateFormat
? Il devient java.time.format.DateTimeFormatter
!
Son utilisation est légèrement différente.
Les différents objets représentant une date possèdent une fonction de parsing et de formatage. Le formateur à utiliser doit être fournit en argument de la fonction et non l'inverse.
Mais surtout, il devient ThreadSafe.
Avant
Après
Remarque intéressante (çà m'arrive !)
Lorsqu'on utilise une formatter
comportant heure et minute dans un objet de type java.time.LocalDate
, voici la belle erreur qui nous est remontée :
Et notre Calendar dans tout çà ?
On avait pris l'habitude d'écrire des lignes et des lignes de code pour ajouter 3 jours à une date, retrancher 2 heures à notre timing, mais sans réellement savoir s'il fallait faire un roll, un add ou encore autre chose....
Bref, c'est désormais réglé, c'est simple, c'est inclus dans chacun des objets de Date.
Attention quand même à un détail : Les classes sont immuables, il faut donc veiller à récupérer la nouvelle instance créée lorsqu'une opération est effectuée. Les instances de ces classes ne sont pas modifiables.
Avant
Après
Trucs & Astuce
La migration des librairies externes risque de prendre du temps... Il existera donc une phase de transition où devront cohabiter ancien et nouveau.
Voici quelques formules de conversion :
Section "Je ronchonne"
La différence entre LocalDateTime
et Instant
est trop mineure. On pourra retenir que si deux instances de Instant
sont créées au même moment à deux endroits de la terre, les valeurs seront identiques car la référence est le 1 janvier 1970 en UTC. L'objet LocalDateTime
se rapproche plus de l'horloge murale que l'on a tous dans notre bureau.
Je n'ai pas de fonction plusMillis(long millisToAdd)
dans la classe LocalDateTime
alors qu'elle est bien présente dans la classe Instant
.
Ces classes sont immuables (aucune propriété ne change après sa création), chaque opération retourne une copie de classe. C'est fabuleux pour faire de jolies expressions inline et cela les rend Thread-Safe par définition. MAIS... à vous de compter le nombre d'instances créées inutilement dans mon petit exemple ci dessous...
En conclusion
C'est quand même beaucoup mieux non ?
Ce n'était pas trop tôt !
La manipulation et le formatage sont maintenant des fonctions inhérentes aux dates... Logique me direz-vous...
L'API JSR-310 permet de régir le tout.
A vos dates ;-)