Le bug getValue des mois dans LocalDate de Java, expliqué

Tout le monde pensait que la troisième API de dates de Java allait enfin faire mouche. Que nenni : Month.getValue() de LocalDate balance aux développeurs un nouveau cauchemar d'indexation.

Sortie de l'enum Month de Java LocalDate montrant le décalage d'indexation entre getValue et ordinal

Key Takeaways

  • Month.getValue() de LocalDate est basé sur 1, ce qui casse les traditions d'indexation zéro-based des tableaux.
  • Restez sur ordinal() pour la compatibilité legacy ; soustrayez 1 à getValue() sinon.
  • Les API dates de Java évoluent, mais les standards pragmatiques l'emportent toujours sur les changements 'intuitifs'.

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

Priya Sundaram
Written by

Hardware and infrastructure reporter. Tracks GPU wars, chip design, and the compute economy.

Worth sharing?

Get the best AI stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to