Tout le monde s'accorde à trouver le langage Java d'une qualité exceptionnelle. Aujourd'hui, il dépasse les 3500 classes, et pour l'humain moyen des limites sont franchies. Il y a peu de chances que quiconque dépasse jamais la maîtrise de mille classes. Et pour ma part, 500 sera certainement mon maximum.
Pourtant, il me semble que toutes les classes ne se valent pas. Que certaines n'ont pas toujours été bien inspirées. Dites-moi si vous le croyez aussi, et si vous avez quelques exemples à titre d'illustration, mais pour ma part, je voudrais commencer par vous présenter la classe que je trouve d'entre toutes la plus baroque. Celle dont le comportement me semble le plus étrange et criticable: java.util.Calendar (et sa classe d'implémentation java.util.GregorianCalendar).
GregorianCalendar est muni d'un constructeur étrange, qui accepte n'importe quoi, dont un mois basé sur un index 0. Cela fait que
new GregorianCalendar(2007,11,25), c'est noël. Seulement, ce n'est pas intuitif. Notons que les jours, eux, sont basés sur l'index 1: 25 c'est 25.
Le 48/16/2007 (new GregorianCalendar(2007, 15, 48)) c'est une date valide qui passe comme une lettre à la poste. Il s'agit du 18/4/2008.
Donc, si votre programme commet des erreurs et génère des dates invalides, il trouvera avec GregorianCalendar un relais de choix pour le transport de données fausses. L'absence de garde-fou est très étonnante, dans le constructeur et les setters en tout cas.
La soustraction de dates ne conduit pas à une durée. Cela produit des choses étonnantes. Justifiées, mais inattendues par bien des développeurs qui manipulent cette classe.
Produit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 import java.text.*; import java.util.*; public class Essai { public static void main(String[] args) { Calendar dt1 = GregorianCalendar.getInstance(); Calendar dt2 = (Calendar)dt1.clone(); int[] vComposants = {Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND}; String [] vszNoms = {"Année: ", "Mois: ", "Jour: ", "Heure: ", "Minutes: ", "Secondes: ", "Milisecondes: "}; for (int iIndex = 0; iIndex < vComposants.length; iIndex ++) soustraire(dt1, dt2, vComposants[iIndex], vszNoms[iIndex]); Calendar dt3 = new GregorianCalendar(2007, 15, 48); String szFormat2 = "Le 48/16/2007 est une date valide: {0}/{1}/{2}."; Object[] args2 = {String.valueOf(dt3.get(Calendar.DAY_OF_MONTH)), String.valueOf(dt3.get(Calendar.MONTH)), String.valueOf(dt3.get(Calendar.YEAR))}; System.out.println(MessageFormat.format(szFormat2, args2)); System.exit(0); } /** * Soustraire une composante d'une date à une autre. * @param dt1 Date 1. * @param dt2 Date 2. * @param nComposant Composante. */ static private void soustraire(Calendar dt1, Calendar dt2, int nComposant, String szNom) { int nAvant = dt2.get(nComposant); dt2.add(nComposant, -dt1.get(nComposant)); String szFormat = "{3}{0} - {1} = {2}"; Object[] args = {String.valueOf(nAvant), String.valueOf(dt1.get(nComposant)), String.valueOf(dt2.get(nComposant)), szNom}; String szMessage = MessageFormat.format(szFormat, args); System.out.println(szMessage); } }
Année: 2007 - 2007 = 1
Mois: 10 - 10 = 0
Jour: 13 - 13 = 31
Heure: 14 - 14 = 0
Minutes: 47 - 47 = 0
Secondes: 46 - 46 = 0
Milisecondes: 33 - 33 = 0
Le 48/16/2007 est une date valide: 18/4/2008.
Si le 31 pour le jour se justifie, le 1 pour la différence en années est plus difficile à comprendre.
Certainement, le développeur se doit d'être vigilant, de manière générale. Mais cette API me semble une des plus délicate à interpréter et à manipuler.
Partager