Egalité de dates en fonction de l’humeur …

  • Sharebar

Au cours du débogage d’un bout de code j’ai été confronté à une problématique singulière qui, je pense, vaut le coup qu’on s’y attarde un peu.

J’avais le bout de code suivant :

// on obtient la date du jour initialisée à minuit
Calendar todayCal = GregorianCalendar.getInstance();
todayCal.set(Calendar.MILLISECOND, 0);
todayCal.set(Calendar.SECOND, 0);
todayCal.set(Calendar.MINUTE, 0);
todayCal.set(Calendar.HOUR, 0);
Date today = todayCal.getTime();

// on obtient la date du modèle métier persistant provenant
// d'hibernate
// précision : en base la valeur est initialisée à minuit
// pour ne conserver que le jour
Date date1 = objetmetier.getDate();

// les tests
System.out.println("date1.equals(today) =" + date1.equals(today));
System.out.println("today.equals(date1) =" + today.equals(date1));
System.out.println("today.getTime() == date1.getTime() ="
+ Boolean.toString(today.getTime() == date1.getTime()));

En exécutant ce bout de code voila le résultat obtenu :

date1.equals(today) =false
today.equals(date1) =true
today.getTime() == date1.getTime() =true

Quelle ne fut pas ma surprise de découvrir qu’avec une date provenant de la base qui est identique à ma date du jour, la méthode equals n’est pas symétrique sur mes 2 opérandes !!

Je suis donc passé au débogage et après analyse des 2 instances en présence il s’est avéré que la date retournée par hibernate était en fait une instance de java.sql.Timestamp

Or la javadoc de Timestamp stipule ceci concernant la méthode equals(Object) :

Note: This method is not symmetric with respect to the equals(Object) method in the base class

Ok, mais pourquoi ?

Note: This type is a composite of a java.util.Date and a separate nanoseconds value. Only integral seconds are stored in the java.util.Date component. The fractional seconds – the nanos – are separate. The Timestamp.equals(Object) method never returns true when passed a value of type java.util.Date because the nanos component of a date is unknown. As a result, the Timestamp.equals(Object) method is not symmetric with respect to the java.util.Date.equals(Object) method. Also, the hashcode method uses the underlying java.util.Date implementation and therefore does not include nanos in its computation.

Donc moralité de l’histoire, comme on ne sait jamais quelle sera l’instance de java.util.Date obtenue à l’exécution, mieux vaut toujours comparer l’égalité de 2 dates avec leur représentation long obtenue avec la méthode getTime().

This entry was posted in Divers. Bookmark the permalink.

2 Responses to Egalité de dates en fonction de l’humeur …

  1. Romain GERARD says:

    Salut,
    il me semble que todayCal.set(Calendar.HOUR,0); donne la valeur 0h pour le matin ou 12h pour l’après-midi
    todayCal.set(Calendar.HOUR_OF_DAY, 0); pour setter à 0 sur une représentation de 24h

    Romain

  2. Franck says:

    AGIR étant un outil d’affectation et de pointage de personnel nous croulons sous les dates, les horaires, les durées.

    Pour nous prémunir contre les escadrilles de problèmes de dates [celle-ci est effectivement particulièrement gratinée, qui conduit à manipuler des opérateurs d'égalité non symétriques !!!], nous avons fait le choix de manipuler des classes date et time “maison”, de sorte de cantonner les différentes recettes et autres astuces inhérentes aux dates en Java au sein de ces classes.

Leave a Reply