Utilisation de l’API JodaTime pour la gestion des dates en Java

Dernièrement, j'ai été amené à m'intéresser de plus près à l'API de gestion de dates JodaTime. JodaTime a été conçu pour simplifier la gestion des dates en Java,et pour pallier aux insuffisances des librairies JDK de dates traditionnelles : Date et Calendar. L'objectif de ce billet est de montrer au travers de quelques exemples la simplicité d'utilisation de cette API. (La version utilisée ici est la 1.6.2)

Avez-vous déjà eu essayé de calculer le nombre de jours compris entre 2 dates ? Si vous avez utilisez GregorianCalendar pour le faire, alors vous avez dû écrire quelque chose qui ressemble à ceci:

       GregorianCalendar dateDebut = new GregorianCalendar(2011, 1, 1, 0,0);
       GregorianCalendar dateFin = new GregorianCalendar();
       long nbJoursMillisecondes = dateFin.getTimeInMillis() - dateDebut.getTimeInMillis();

Le principal inconvénient avec cette méthode est que vous ne pouvez pas accéder directement au nombre de jours. On ne peut que récupérer le nombre de jours en millisecondes et il faudra encore faire :

       final long MILLISECONDES_PAR_JOURS = 24 * 60 * 60 * 1000;
       int nbJours = (int) (nbJoursMillisecondes / MILLISECONDES_PAR_JOURS) ;

De plus, on ne peut pas accéder directement aux propriétés de cette date (jour, mois, année...). L'API JodaTime résoud ces problèmes en découplant la date à ses propriétés. Ces propriétés de date sont définies comme étant des instances de la classe DateTime.Property. On peut ainsi accéder aux propriétés d'une date et les manipuler comme on veut. Par exemple, avec JodaTime je peux afficher directement le jour de ma date sous plusieurs formes :

       DateTime.Property day = dateDuJour.dayOfWeek() ; // récupération de ma propriété day
       day.get();   // 3
       day.getAsText(); // mer.  
       day.getAsShortText(); // mercredi
       day.getAsText(Locale.ENGLISH); // Wednesday

Reprenons l'exemple de calcul de jours entre 2 dates en utilisant cette fois-ci JodaTime.

       DateTime dateDebut = new DateTime(2011,1,1,0,0,0,0);
       DateTime dateFin =  new DateTime();
       Days d = Days.daysBetween(dateDebut, dateFin);  // récupération du nombre de jours dans une instance de la classe Days.    
       int days = d.getDays();

Plus simple et plus intuitif!

Je peux même aller plus loin et jouer encore plus avec mes dates:

Je veux retourner une copie de mon objet en modifiant le jour à Lundi
       DateTime result1 =  dateDuJour.dayOfMonth().setCopy(DateTimeConstants.MONDAY);  (si le jour était déjà Lundi, alors le même objet est retourné)

Je veux retourner une copie de ma date en lui rajoutant 3 jours

       DateTime result2 =  dateDuJour.monthOfYear().addToCopy(3);

Je peux aussi manipuler directement ma date:

       DateTime result3 =  dateDuJour.plusYears(2);

Conversion des dates en String avec JodaTime

Jettons maintenant un petit coup d'oeil à la conversion avec JodaTime. Pour convertir une date en String, on utilise la classe DateTimeFormatter qui permet d'afficher une date en String et de parser un String en Date.

            DateTime dateDuJour = new DateTime();
            DateTimeFormatter formatter = DateTimeFormat.forPattern("dd MMM yyyy");
            String dateDuJourEnString = formatter.print(dateDuJour);

Le résultat :

            09 mars 2011

On crée notre formatteur grâce à la fabrique DateFormat, en passant en paramètre à la méthode forPattern, le pattern désiré. Ensuite on a plus qu'à utiliser la méthode print() pour effectuer la conversion en String.

Idem, pour parser un String en date, mais cette fois, on utilise la méthode parseDateTime() :

            DateTime date = formatter.parseDateTime(dateduJourEnString)

La fabrique DateFormat permet de créer des formatteurs personnalisés. On a deux autres fabriques: ISODateTimeFormat adapté à l'utilisation de formats ISO8601 et DateTimeFormatter pratique pour l'utilisation de formats complexes.

Par exemple si on veut afficher une date au format standard ISO qui est

"yyyy-MM-dd'T'HH:mm:ss.SSSZZ", on fera :
           DateTimeFormatter ISOFormatter = ISODateTimeFormat.dateTime();
           formatter.print(dateDuJour);

Si on veut représenter une date sous un format qui ne correspond à aucun pattern, par exemple, "09-mars-11" , on fera :

           DateTimeFormatter freakyFormatter = new DateTimeFormatterBuilder().appendDayOfMonth(2).appendLiteral('-')

.appendMonthOfYearShortText().appendLiteral('-').appendTwoDigitYear(1956) // pivot = 1956
.toFormatter();
freakyFormatter.print(dateDuJour);

Interopérabilité JDK

JodaTime est interopérable avec les librairies JDK Date, et Calendar. Vous pourrez donc l'utiliser dans votre projet même si votre code dépend déjà des librairies JDK.

Le passage d'une DateTime à une date d'une des API JDK peut se faire très facilement :

       DateTime jodaDate = new DateTime();
       Date jdkDate = jodaDate.toDate(); // passage de JodaTime à JDK Date
       Calendar jdkCal = jodaDate.toCalendar(Locale.FRENCH); // passage de JodaTime à JDK Calendar
       GregorianCalendar jdkGCal = jodaDate.toGregorianCalendar();	// passage de JodaTime à JDK GregorianCalendar

Obtenir une DateTime à partir d'une des dates JDK est tout aussi simple; il suffit de passer la date JDK au paramètre du constructeur DateTime:

       jodaDate = new DateTime(jdkDate);	// passage de JDK Date à JodaTime
       jodaDate = new DateTime(jdkCal);	// passage de JDK Calendar à JodaTime
       jodaDate = new DateTime(jdkGCal);	// passage de JDK GregorianCalendar à JodaTime

On peut aussi construire une DateTime à partir d'une chaine ISO ou d'un objet Long (représentant la valeur en millisecondes du temps écoulé depuis le 1e Janvier 1970)

       DateTime dateConstruitParISO = new DateTime("2011-03-09T03:13:26.148+01:00");
       DateTime dateConstruitParLong = new DateTime(3000);	// 3 secondes après le 1e Janvier 1970

La liste exhaustive des constructeurs de DateTime est disponible : ici

En somme, on peut dire que JodaTime apporte une simplification énorme à la gestion des dates en Java. Et ce n'est pas tout! Il y a encore d'autres fonctionnalités que je n'ai pas énoncées dans ce billet comme la possibilité de définir une intervalle de temps par exemple. Il semble même qu'au niveau des performances, JodaTime a des longueurs d'avance sur les librairies JDK, mais ça je ne l'ai pas encore testé..

Un commentaire

  1. D’après ce que j’ai compris la librairie JodaTime serait quasiment intégrée dans les prochaines versions du JDK (JSR 310).

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.