2015-04-01 1 views
0

Pouvez-vous me dire pourquoi le code fillowing:comportement étrange de compareTo (GregorianCalendar c)

int a = new GregorianCalendar(2015,3,31,7,45).compareTo(
     new GregorianCalendar(2015,4,1,7,45); 
System.out.println(a); 

imprime 0?

Existe-t-il un moyen de le faire fonctionner correctement?

PS: Je dois trier des chaînes par date et j'utiliser ce comparateur:

array.sort(new Comparator<String>() { 
    @Override 
    public int compare(String o1, String o2) { 
     GregorianCalendar cal1 = new GregorianCalendar(Integer.parseInt(o1.replaceAll(p, "$7")), 
       Integer.parseInt(o1.replaceAll(p, "$6")), Integer.parseInt(o1.replaceAll(p, "$5")), 
       Integer.parseInt(o1.replaceAll(p, "$8")), Integer.parseInt(o1.replaceAll(p, "$9"))); 
     GregorianCalendar cal2 = new GregorianCalendar(Integer.parseInt(o2.replaceAll(p, "$7")), 
       Integer.parseInt(o2.replaceAll(p, "$6")), Integer.parseInt(o2.replaceAll(p, "$5")), 
       Integer.parseInt(o2.replaceAll(p, "$8")), Integer.parseInt(o2.replaceAll(p, "$9"))); 
     return cal1.compareTo(cal2); 
    } 
}); 

Il utilise des expressions régulières, mais il est trié correctement et que les dates fournies ne sont pas triées droit.

Répondre

4

Vous comparez "31 avril" avec le 1er mai. Il est pas le 31 avril, donc c'est de rouler au 1er mai de toute façon. (D'accord, il serait plus logique de simplement jeter une exception, mais bon ... c'est loin d'être la pire morceau de la conception de l'API dans Calendar.)

Je recommande fortement d'utiliser SimpleDateFormat pour analyser des représentations de chaîne de date/heure valeurs, au lieu de le faire vous-même. Mis à part toute autre chose, SimpleDateFormat "sait" que les mois sont basés sur 0 en Java ... qui est le bug de base dont vous êtes responsable. Le code serait aussi beaucoup plus lisible, je suppose.

Avez-vous vraiment besoin de garder la collection comme une collection de cordes de toute façon? Si elles sont juste dates, convertissez-le en une collection de type date (idéalement en utilisant Joda Time ou le package java.time de Java 8). S'ils sont quelque chose comme des entrées de journal qui ont une date mais aussi d'autres informations, convertissez-les en une représentation de cette première. De toute façon, vous avez alors une collection qui représente plus naturellement l'information qu'elle contient.

+0

Oooh, voici l'astuce, les mois en Java sont basés sur 0 ... C'est vraiment bizarre. Merci d'avoir ouvert cette astuce pour moi! –

+0

@DenisYakovenko: C'est le problème immédiat - mais s'il vous plaît ne prenez pas cette leçon. Il y a d'autres façons d'améliorer ce code de façon très significative ... –

+0

Eh bien, le tri des tableaux n'est qu'une petite partie de la tâche, et je suis obligé d'utiliser Java 7, mais je m'en tiendrai à vos conseils) vous voulez dire par "très significativement"? Vous voulez dire que l'utilisation de regex de cette façon est trop chère? –

0

Pourquoi ne pas simplement appeler .getTime() sur les calendriers et trier par dates? ou .getTime().getTime() et trier les longs?