Java et les dates. Quelle saga. À l’époque, on croyait tous que la classe Date d’origine allait simplement faire le job — des timestamps basiques, sans chichis. Puis Y2K a tout fait exploser avec ses méthodes farfelues, et les prédécesseurs d’Oracle nous ont balancé Calendar comme sauveur. Un effort honnête, mais lourdingue. Aujourd’hui, java.time.LocalDate débarque en troisième tentative, acclamée comme la solution blindée. Sauf que non. Pas tout à fait.
Ça change la donne ? Pas vraiment. Ça remplace juste un mal de crâne par un autre, en obligeant les codeurs à soustraire 1 à chaque fois qu’ils attrapent un nom de mois. Qui y gagne ? Pas vous, en train de fixer une erreur d’index de tableau à 2 heures du mat’.
Écoutez, je couvre Java depuis les guerres des applet — 20 ans à voir Sun, Oracle et maintenant Eclipse se chamailler sur la gouvernance. Les dates ont toujours été le talon d’Achille du langage. Les fuseaux horaires qui dansent la samba, les secondes intercalaires qui se faufilent, et chaque itération d’API qui prétend dompter le chaos. LocalDate ? Moderne, immutable, compatible ISO. Super sur le papier. Mais ouvrez le capot sur Month.getMonth(), et le cynisme pointe le bout de son nez.
Pourquoi les mois de LocalDate dans Java commencent-ils à 1 ?
Le hic, c’est là. Prenez LocalDate.now() — disons 2026-04-07, comme dans la plainte initiale. Appelez getMonth().getValue(), et bim : 4 pour avril. Logique, non ? Ça colle à ISO 8601, où janvier fait 1. Les non-développeurs hochent la tête. Mais les programmeurs ? On est câblés pour du zéro-based partout depuis le C de K&R.
Votre bon vieux tableau de noms de mois — Enero en 0, Febrero en 1 — se retrouve soudain décalé. Indexez avec getValue() ? Vous tombez sur Mayo au lieu d’Abril. Le classique off-by-one, la peste de notre métier.
Fecha: 2026-04-07 Mes (val): Mayo Mes (ord): Abril
Direct du démo de code de la source. Exécuté le 7 avril, ça affiche bien Avril via ordinal() (zéro-based, index 3). Mais getValue() ? Ça force un bricolage : MESES[fecha.getMonth().getValue() - 1]. Moche. Et maintenant, ça s’incruste dans tous les nouveaux codebases.
Ordinal() marche toujours — Dieu merci — et tient la ligne avec janvier=0. Mais pourquoi ce compromis foireux ? C’est comme refaire le tableau de bord de votre voiture avec un odomètre qui démarre à 1 kilomètre. Intuitif pour les passagers, rageant pour les mécanos.
Mais attendez : le 1-based n’est-il pas finalement mieux ?
Tableau à l’appui. Adapté de l’original :
| Méthode | Basé sur | Exemple | Conception |
|---|---|---|---|
| getValue() | 1 | Janvier == 1 | Intuitive |
| ordinal() | 0 | Janvier == 0 | Habitude |
Point valide. Les humains comptent janvier comme 1. Les gosses l’apprennent comme ça. Mais le code ? Le localtime() de C fourre tm_mon à 0. Date.getMonth() en JavaScript ? Zéro-based, +1 pour l’affichage. Perl, PHP — même combat. Même l’ancien Calendar.get(Calendar.MONTH) allait de 0 à 11.
Cela va-t-il casser votre vieux code Java ?
Réponse courte : si vous migrez vers java.time, oui — en douceur. Ce hack rapide pour les noms de mois que tout le monde a copié-collé pendant des décennies ? Mort. Vous allez débugger des mois espagnols bizarres (ou leurs équivalents anglais) qui poppent dans les logs. Je parie sur une flambée de plaintes Stack Overflow d’ici Q2 2025, quand les équipes upgraderont pour Jakarta EE machin.
Angle inédit que personne n’a creusé : ça rappelle les guerres ordinal() des enums en Java 5. À l’époque, les gens hurlaient quand les enums lâchaient les valeurs numériques pour des tours de passe-passe de réflexion. Oracle n’a rien appris. Ils courent après la ‘pureté’ — conformité ISO — au détriment des cassures pragmatiques. Qui profite ? Les consultants Red Hat qui facturent des audits dates. Le HotSpot JVM d’Oracle ? Se vend pareil dans tous les cas.
Et la correction ? triviale, mais omniprésente. Tous les tutos, tou