La gestion des dates en Java

Je travaille actuellement sur un projet dans lequel nous avons besoin de manipuler des dates. Le projet est assez ancien, il date de plus de quatre ans, et à l’évidence, ceux qui ont écrit cette appli ne maîtrisaient pas très bien la programmation orientée objet. Et comme dans le même temps, très peu de documentation a été rédigée et que le projet a changé de domaine, je me retrouve tout seul à essayer de décrypter des lignes de code absconses et indigestes.

Je souhaite donc vous faire profiter d’un petit retour d’expérience afin d’améliorer la gestion des dates dans vos projets Java.

Petit rappel, il existe deux classes qui permettent de représenter une date dans l’api standard. Il s’agit de Calendar et Date, toutes deux dans le package java.util. Je ne traite pas ici du package java.sql.

Lorsque vous avez besoin de représenter une date en attribut d’une classe, je recommande l’utilisation de Date plutôt que Calendar. En effet, Date est un objet immuable (ou presque), il garanti qu’il ne sera pas modifié par mégarde et élimine les problèmes d’accès concurrent en cas de programmation multithread :

public class Personne {
    public final String nom, prenom;
    public final Date dateDeNaissance;
}

Faites attention lorsque vous initialisez une Date. Si vous utilisez le constructeur par défaut, la date sera initialisée avec pour valeur le nombre de milliseconde depuis le 1er janvier 1970. Le problème est que lorsque vous récupérez une deuxième Date par défaut et que vous les comparez toutes les deux, bien que ces deux dates correspondent au même jour calendaire, la comparaison échouera car la valeur en milliseconde sera différente.

Je recommande donc l’écriture d’une classe d’utilitaire qui permettra de manipuler les dates en adoptant une approche fonctionnelle :

public class CalendarUtil {
    private static final Calendar calendar = Calendar.getInstance();

    public static Date getDate(int jour, int mois, int année) {
    }
    public static Date getDate() {
        //retourne une date correspondant à la date courante (aujourd'hui)
    }
    public static Date incrementer(Date date, int jours) {
    }
    public static boolean equals(Date date1, Date date2) {
        //indique si deux dates correspondent au même jour calendaire
        //sans tenir compte des heures, minutes, secondes
    }
    public static int difference(Date date1, Date date2) {
        //retourne la différence en nombre de jours
    }
    public static boolean isEcheanceEchue(Date date, Periodicite period) {
    }
    public static String format(Date date, String pattern) {
    }
    [...]
}

Comme vous l’aurez constaté, cette classe d’utilitaire ne prend que des Date en paramètre. C’est en effet ma troisième recommandation et sans doute la plus importante. L’usage de Calendar doit être réservé aux calculs sur les dates, et donc être circonscrit à la classe CalendarUtil.

Je ne traite pas de la question des fuseaux et des locales, mais je recommande là encore une approche fonctionnelle

Par ailleurs, les plus perspicaces d’entre vous aurons remarqué que la méthode incrémenter() de CalendarUtil peut entrainer une conflit de signature. C’est le cas si l’on a besoin d’ajouter des mois ou des années à une date.

Dans ce cas, je recommande de suivre les préconisations de Stephan Schmidt :

public static Date incrementer(Date date, NbJours jours) {
}
public static Date incrementer(Date date, NbMois mois) {
}
public static Date incrementer(Date date, NbAnnees annees) {
}
public class NbJours {
    public final int value;
    public Jour(int value) {
        this.value = value;
    }
}
[...]

Ces recommandations, si elles sont suivies à la lettre, vous éviterons bien des soucis tel que je peux en rencontrer actuellement avec mon vieux projet. Dernier conseil qui va de soit, vous devrez évidemment tester unitairement chaque méthode de CalendarUtil.

Publicités

3 Responses to “La gestion des dates en Java”


  1. 1 amertum août 26, 2009 à 5:55

    Pour gérer des dates, il y a commons-lang de apache qui contient DateUtils et autres… Et pour une gestion encore meilleure, il y a JodaTime.
    De plus, quitte à faire un util de date, autant le faire en object plutôt qu’en procédural static.

    je préfère new DateUtil().incrementer(uneDate).de(5).type(JOUR)

  2. 2 hadf août 26, 2009 à 6:05

    Il n’est pas toujours possible de rajouter des dépendances dans un projet, mais il est vrai que dans la mesure du possible, il est préférable d’éviter de réinventer la roue.

    Quant à l’utilisation d’un objet, cela n’apporte rien par rapport à une méthode static étant donné qu’il s’agit d’une classe sans état. En outre, avec les import static, une méthode static peut s’avérer plus pratique d’usage.


Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s





%d blogueurs aiment cette page :