337 votes

Pourquoi est janvier le mois 0 en Java Calendrier?

En java.util.Calendar, janvier est défini comme le mois 0, pas 1 mois. Est-il une raison particulière à cela ?

J'ai vu beaucoup de gens se confondre à ce sujet...

348voto

Jon Skeet Points 692016

C'est juste une partie de l'effroyable gâchis qui est la Java de la date/heure API. La liste de ce qui est mal à cela prendrait un temps très long (et je suis sûr que je ne sais pas la moitié des problèmes). Certes, le travail avec les dates et les heures est délicat, mais aaargh de toute façon.

Faites-vous une faveur et de les utiliser Joda Time à la place, ou, éventuellement, de la JSR-310.

EDIT: pour ce qui est des raisons pour lesquelles - comme indiqué dans d'autres réponses, il pourrait bien être due à des vieux C Api, ou une sensation de démarrage tout à partir de 0... sauf que les jours commencent à 1, bien sûr. Je doute que quiconque à l'extérieur de l'original de l'équipe de mise en œuvre pourrait vraiment de motivation - mais encore une fois, j'avais envie lecteurs de ne pas trop s'inquiéter de la pourquoi de mauvaises décisions ont été prises, comme de regarder l'ensemble de la gamme de la malveillance dans java.util.Calendar et de trouver quelque chose de mieux.

Un point, qui est en faveur de l'utilisation de 0 basée sur des indices, c'est qu'il fait des choses comme des "tableaux de noms" plus facile:

// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];

Bien sûr, il échoue dès que vous obtenez un calendrier de 13 mois... mais au moins, la taille indiquée est le nombre de mois que vous attendez.

Ce n'est pas une bonne raison, mais c'est une raison...

EDIT: Comme un commentaire de tri des demandes quelques idées sur ce que je pense est le problème avec Date/Calendrier:

  • Surprenant de bases (1900 comme l'année de base en Date, certes obsolète pour les constructeurs; 0 étant le mois de la base dans les deux)
  • La mutabilité - à l'aide de immuable types rend beaucoup plus simple de travailler avec ce que sont vraiment efficacement les valeurs de
  • Une insuffisance de types: il est agréable d'avoir des Date et Calendar comme des choses différentes, mais la séparation de la "locale" vs "zonage" des valeurs est manquante comme la date/heure vs date vs temps
  • Une API qui conduit à laide de code avec les constantes magiques, au lieu de clairement nommé méthodes
  • Une API qui est très difficile de raisonner sur - tout à propos de quand les choses sont recalculés, etc
  • L'utilisation de sans paramètre constructeurs par défaut à "maintenant", ce qui conduit à un dur-à-code d'essai
  • L' Date.toString() mise en œuvre qui utilise toujours le système de l'heure locale (qui est de la confusion de nombreux Débordement de Pile utilisateurs avant aujourd'hui)

56voto

arucker Points 31

Parce que faire des maths avec mois est beaucoup plus facile.

1 mois après le mois de décembre est le mois de janvier, mais pour comprendre cela, normalement, vous auriez à prendre le numéro du mois et de faire des maths

12 + 1 = 13 // What month is 13?

Je sais! Je peux résoudre ce problème rapidement à l'aide d'un module de 12.

(12 + 1) % 12 = 1

Cela fonctionne bien pour les 11 mois jusqu'en novembre...

(11 + 1) % 12 = 0 // What month is 0?

Vous pouvez faire tout ce travail encore en soustrayant 1 avant d'ajouter le mois, puis faire votre module et enfin ajouter 1 retour... aka contourner un problème sous-jacent.

((11 - 1 + 1) % 12) + 1 = 12 // Lots of magical numbers!

Maintenant, nous allons réfléchir sur le problème avec des mois 0 - 11.

(0 + 1) % 12 = 1 // February
(1 + 1) % 12 = 2 // March
(2 + 1) % 12 = 3 // April
(3 + 1) % 12 = 4 // May
(4 + 1) % 12 = 5 // June
(5 + 1) % 12 = 6 // July
(6 + 1) % 12 = 7 // August
(7 + 1) % 12 = 8 // September
(8 + 1) % 12 = 9 // October
(9 + 1) % 12 = 10 // November
(10 + 1) % 12 = 11 // December
(11 + 1) % 12 = 0 // January

Tous les mois le même et un travail autour n'est pas nécessaire.

45voto

Bombe Points 34185

Le plus important: si les mois sont comptés à partir de 0 (et ils le sont), pourquoi sont des jours comptés à partir de 1?

37voto

stesch Points 5774

C langages basés sur la copie C à un certain degré. L' tm de la structure (définie en time.h) a un champ de type entier tm_mon avec le (commenté) plage de 0 à 11.

C langages basés sur démarrer tableaux à l'indice 0. Donc c'était pratique pour la sortie d'une chaîne dans un tableau de noms de mois, tm_mon l'indice.

26voto

piksel bitworks Points 395

Il y a eu beaucoup de réponses, mais je vais donner mon point de vue sur le sujet de toute façon. La raison derrière ce comportement étrange, comme indiqué précédemment, vient de la POSIX C time.h où les mois où sont stockées dans un int avec la gamme de 0 à 11. Pour expliquer pourquoi, regardez comme ça, les années et les jours sont considérés comme des nombres dans la langue parlée, mais les mois ont leurs propres noms. Donc, parce que janvier est le premier mois, il sera stocké comme l'offset 0, le premier élément du tableau. monthname[JANUARY] serait "January". Le premier mois de l'année, est le premier mois de l'élément de tableau.

Le nombre de jour sur l'autre main, car ils n'ont pas de noms, de les stocker dans un int comme 0-30 serait source de confusion, ajouter beaucoup d' day+1 instructions pour la sortie et, bien sûr, être sujettes à beaucoup de bugs.

Cela étant dit, la contradiction est source de confusion, en particulier dans le javascript (qui a aussi hérité de cette "fonctionnalité"), un langage de script où ce doit être abstrait loin de la langague.

TL;DR: Parce que les mois ont des noms et des jours du mois qui ne le sont pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X