Gestion du temps et des langues

Classes pour gérer le temps et les locales

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Grâce à de multiples classes, Java permet de gérer quasiment tous les aspects de la problématique géo-temporaire auxquels on peut être confrontés en développant une application.

Les dates et le temps peuvent être facilement manipulés avec de telles classes que Date, Calendar, DateFormat. Les classes TimeZone et Locale seront très utiles lors du déploiement de l'application à l’international.

Convertir chaîne de caractères en Date et inversement en Java

Pour jouer avec la conversion des chaînes de caractères en objets Date et inversement on peut utiliser la classe de formatage. Elle s’appelle SimpleDateFormat et traite les données en fonction du format de la date indiquée. Regardons cela sur un exemple :

afficher le code

Voici le résultat :

Converted date (Date) Wed Sep 30 00:00:00 CEST 2009 Converted date (String) 2009-09-30

Manipuler les dates en Java

La manipulation (addition/soustraction des jours) en Java peut être facilement effectuée avec l'utilisation de la classe Calendar. Elle permet, entre autres, de rajouter ou soustraire des jours/mois/années. Les objets de cette classe peuvent aussi servir à comparer des dates. Ils permettent également la récupération directe du numéro de la semaine dans le mois ou du jours dans la semaine. Dans notre exemple on va regarder les exemples sur les opérations de soustraction et addition :

afficher le code

Le résultat obtenu :

Calendar after substracting 9 days Mon Sep 21 00:00:00 CEST 2009 Calendar after adding 9 days and 2 months Mon Nov 30 00:00:00 CET 2009 Calendar on next year Tue Nov 30 00:00:00 CET 2010 Calendar day of week in month 4

L'addition et la soustraction s'effectuent avec la méthode add() qui prend comme valeur le type (une constante de la classe Calendar) et le nombre positif (addition) ou négatif (soustraction) des jours pris dans l'opération. Ensuite on peut obtenir plus d'informations sur la date reçue. On voit cela avec l'appel de la constante Calendar.WEEK_OF_MONTH qui représente le numéro de la semaine dans le mois.

Comparaison des dates en Java

Java offre également une possibilité de comparer les dates, soit via les méthodes correspondantes dans la classe Date, soit via celle de la classe Calendar. Dans nos exemples on utilisera les fonctions de la première classe mentionnée :

afficher le code

Voici le résultat :

Is 2010-03-01 between 2009-09-30 and 2010-09-30 ? true Is 2012-03-01 between 2009-09-30 and 2010-09-30 ? false Is 2012-03-01 the same as 2009-09-30 ? false Is 2009-09-30 the same as 2009-09-30 ? true Difference between 2010-09-30 and 2009-09-30 in days is 365 Difference between 2010-09-30 and 2009-09-30 in hours is 8760

La majorité de méthodes ne nécessitent pas d'explications particulières. Uniquement il faut avoir bien en tête que le calcul de la différence du temps entre deux dates doit s'effectuer sur les milisecondes, pour une meilleure conversion des résultats.

Internationalisation des dates et du temps en Java

L'adaptation d'un programme pour les utilisateurs internationaux peut être synonyme de l'implantation de la filiale d'une entreprise à l'étranger. En Java on peut imiter cette procédure grâce à des classes Locale et TimeZone qui, couplées avec Date ou Calendar, peuvent aider à concevoir une application universelle. Voici quelques exemples de l'utilisation de ces classes :

afficher le code

Voici le résultat :

With default locale septembre With default locale settembre The original default locale is fr_FR Hour for timezone America/Anchorage is 11 Hour for timezone Europe/Tirane is 21

Personne devrait avoir des problèmes à comprendre le code. L'utilisation des getters pour définir de nouvelles propriétés et ensuite la manipulation avec les méthodes disponibles dans Calendar. Cependant, il faut faire attention à quelques dangers.

Pièges dans la manipulation des dates en Java

Malgré cette gestion très intuitivie, des pièges à éviter existent. Ils sont liés à la spécificité des classes évoquées : 1. Locale doit être modifié avant la création de l'objet SimpleDateFormat. Sinon, c'est l'ancienne valeur de Locale qui sera reprise.

On peut également utiliser un constructeur SimpleDateFormat qui prend en paramètres la chaîne de caractères (String - format de la date) et la nouvelle Locale. 2. GregorianCalendar calcule les mois différémment. Les mois dans la classe GregorianCalendar commencent avec 0 (janvier) et se terminent avec 11 (décembre). On peut constater cela sur cet exemple :

afficher le code

Sur l'écran on verra :

Gregorian calendar date Sat Feb 05 00:00:00 CET 2011

La même chose concerne toutes les classes héritantes de Calendar.

3. Certains formats des dates peuvent être validés correctement. Même si une date n'existe pas, elle peut être toujours valable aux yeux de Java. Voici une illustration :

afficher le code

Le résultat affiché sera :

Sun Jan 25 00:00:00 CET 2009

Par défaut, la classe SimpleDateFormat est lenient. Cela veut dire qu'elle accepte certaines erreurs de formattage. Si le pattern de la date correspond à la chaîne de caractères de la date, cette classe va essayer de deviner la date selon quelques régles. Dans notre cas, elle va récupérer le jour 25 (31 jours d'un mois + 25 restants = 56) du premier mois disponible (00 n'existe pas, donc 01 - janvier).

Afin d'éviter les problèmes de ce type, il faut mettre la valeur lenient à false, comme ici :

afficher le code

Ici, le résultat obtenu sera correct (une erreur de parsage) :

An ParseException was caught : Unparseable date: "56/00/2009" null

4. Par défaut, SimpleDateFormat n'est pas thread safe.. Sa création est gourmande en ressources. Une chose qui déchargeant le processus peut être sa déclaration en tant qu'un attribut final.

Les problèmes peuvent apparaître surtout quand on utilisera un Executor qui initialise un pool des Threads basé sur le cache (méthode Executors.newCachedThreadPool()). Sa particularité est que de nouveaux Threads sont créés uniquement s'il y a un tel besoin. Dans le cas contraire, il essaie d'utiliser les Threads déjà conçus, ayant terminé l'exécution du code. Les Threads terminés et pas repris ne sont supprimés qu'au bout d'une minute. Voici l'exemple qui illustre le problème :

afficher le code

En retour on reçoit des résultats incohérents, comme :

Converted and received dates aren't the same 1971/12/04 (received) and 2012/11/12 (converted) Converted and received dates aren't the same 2012/11/12 (received) and 1970/12/12 (converted) Converted and received dates aren't the same 1971/12/04 (received) and 1970/12/12 (converted) Converted and received dates aren't the same 2012/11/12 (received) and 1971/11/12 (converted) Converted and received dates aren't the same 1971/12/04 (received) and 1971/11/04 (converted)

Afin de régler ce problème on peut faire appel à la référence douce (soft reference) qui ne sera jamais réclamée par Garbage Collector. Elle sera par contre nettoyée de la mémoire à partir du moment où elle n'aura plus de référence forte. Cette référence sera pris par un ThreadLocal qui permet à plusieurs Threads d'y accéder et d'avoir sa propre instance. Cela veut dire que ces Threads peuvent modifier la valeur appartenant uniquement à l'instance qu'ils possèdent. Voici comment cela s'applique au code corrigé de la classe ConvertUtil de notre exemple :

afficher le code

Liste des codes pour les dates en Java

Voici une liste qui permet de retrouver rapidement les formats de dates :

FormatExplicationExemple
aaIndiciateur pour le temps avant ou après midi (AM/PM).PM
ddJour dans le mois (de 1 à 31).07
DDDJour dans l'année.251
EEEJour dans la semaine (abbreviations des noms).Fri
EEEEJour dans la semaine (noms sont complets)Friday
FNuméro du jour dans la semaine selon la norme ISO-8601 (1 pour lundi...7 pour dimanche)1
GGL'époque : AD (Anno Domini) ou BC (Before Christ)AD
HHL'heure dans la journée (de 0 à 23)13
hhL'heure dans la journée (de 1 à 12 AM ou PM)01
kkL'heure dans la journée (de 1 à 24)13
KKL'heure dans la journée (de 0 à 11 AM ou PM)01
mmMinute dans l'heure (de 0 à 59)21
MMLe mois dans l'année (de 1 à 12)09
MMMLe mois dans l'année (en abbreviation)Sep
MMMMMLe mois dans l'année (nom completSeptember
ssLes sécondes dans la minute (de 0 à 59)09
SSSLes milisecondes (de 000 à 999)818
WLa semaine dans un mois.2
wwwLa semaine dans l'année selon la norme ISO-8601 (de 01 à 53).036
yyL'année à deux derniers chiffres.12
yyyyyL'année à quatre chiffres.2012
ZLa précision du zone du temps.+0200
zzzLe nom en abbreviation du zone du temps.CEST
zzzzzzzzLe nom complet du zone du temps.Central European Summer Time
télécharger les fichiers d'exemple
Bartosz KONIECZNY Date, temps et localisation

Une question ? Une remarque ?

*

*

Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil JavaScript

Un scroll avec dialog box de jQuery UI ?

Si vous voyez une barre horizontale qui apparaît après l'ouverture d'un dialog box sous IE8, il peut s'agit d'un problème de ce module pour le navigateur en question. Pour y remedier, on peut utiliser la méthode open() et forcer le navigateur à cacher cette bare. Prenons un exemple vivant :

var dialogBox = $(href).dialog({ autoOpen: false, closeOnEscape: true,
  open: function() {  
        $('body').css('overflow-x', 'hidden');
  },
  close: function() {
        $('body').css('overflow-x', 'auto');  
  }
});  
dialogBox.dialog("open");