web-dev-qa-db-fra.com

Le calendrier renvoie un mauvais mois

Calendar rightNow = Calendar.getInstance();
String month = String.valueOf(rightNow.get(Calendar.MONTH));

Après l'exécution de l'extrait ci-dessus, le mois obtient une valeur de 10 au lieu de 11. Comment se fait-il?

94
Hant

Les mois sont indexés de 0 à 1, donc 10 correspond à novembre et 11 à décembre.

126
Vincent Ramdhanie

Ils commencent à partir de 0 - vérifiez les documents

28
Bozho

Comme en témoignent les nombreuses réponses: le mois commence par 0.

Voici un conseil: vous devriez utiliser SimpleDateFormat pour obtenir la représentation String du mois:

Calendar rightNow = Calendar.getInstance();
Java.text.SimpleDateFormat df1 = new Java.text.SimpleDateFormat("MM");
Java.text.SimpleDateFormat df2 = new Java.text.SimpleDateFormat("MMM");
Java.text.SimpleDateFormat df3 = new Java.text.SimpleDateFormat("MMMM");
System.out.println(df1.format(rightNow.getTime()));
System.out.println(df2.format(rightNow.getTime()));
System.out.println(df3.format(rightNow.getTime()));

Sortie:

11
Nov
November

Remarque: la sortie peut varier, elle est spécifique aux paramètres régionaux.

22
Bart Kiers

Comme plusieurs personnes l'ont souligné, les mois retournés par les classes Calendar et Date dans Java sont indexés de 0 au lieu de 1. Donc 0 est janvier et le mois en cours, novembre, est 10.

Vous vous demandez peut-être pourquoi c'est le cas. Les origines résident dans les fonctions standard POSIX ctime, gmtime et localtime, qui acceptent ou renvoient un time_t structure avec les champs suivants (from man 3 ctime ):

int tm_mday;    /* day of month (1 - 31) */
int tm_mon;     /* month of year (0 - 11) */
int tm_year;    /* year - 1900 */

Cette API a été copiée à peu près exactement dans la classe Java Date dans Java 1.0, et à partir de là, presque intacte dans la classe Calendar dans Java 1.1. Sun a résolu le problème le plus flagrant lors de l'introduction de Calendar - le fait que l'année 2001 dans le calendrier grégorien était représentée par la valeur 101 dans leur classe Date. Mais je ne sais pas pourquoi ils n'ont pas changé les valeurs du jour et du mois pour au moins les deux soient cohérentes dans leur indexation, à partir de zéro ou de 1. Cette incohérence et la confusion associée existent toujours dans Java (et C) à ce jour.

18
Matt Ryall

Les mois commencent à zéro, comme les index des listes.

Par conséquent, Jan = 0, Feb = 1, etc.

10
Federer

Depuis l'API:

Le premier mois de l'année est JANVIER qui est 0; le dernier dépend du nombre de mois dans une année.

http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Calendar.html

8
b.roth

tl; dr

LocalDate.now()            // Returns a date-only `LocalDate` object for the current month of the JVM’s current default time zone.
         .getMonthValue()  // Returns 1-12 for January-December.

Détails

Les autres réponses sont correctes mais obsolètes.

Les anciennes classes de date et heure gênantes présentaient de nombreux choix de conception et défauts. L'un était le comptage à base zéro des numéros de mois 0-11 plutôt que le 1-12 évident.

Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes de date-heure gênantes telles que Java.util.Date, .Calendar, & Java.text.SimpleDateFormat.

Désormais en mode maintenance , le projet Joda-Time conseille également la migration vers Java.time.

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications.

Une grande partie de la fonctionnalité Java.time est back-portée vers Java 6 & 7 in ThreeTen-Backport et plus adaptée à Android dans ThreeTenABP .

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour de futurs ajouts possibles à Java.time.

Mois 1-12

Dans Java.time, le numéro du mois est en effet le 1-12 attendu pour janvier-décembre.

La classe LocalDate représente une valeur de date uniquement sans heure et sans fuseau horaire.

Fuseau horaire

Un fuseau horaire est crucial pour déterminer une date. Pour un moment donné, la date varie dans le monde par zone. Par exemple, quelques minutes après minuit à Paris France est un nouveau jour alors qu'encore "hier" à Montréal Québec .

Spécifiez un nom de fuseau horaire correct au format continent/region, tel que America/Montreal , Africa/Casablanca ou Pacific/Auckland. N'utilisez jamais l'abréviation de 3-4 lettres telle que EST ou IST car ils sont pas vrais fuseaux horaires, non standardisés, ni même uniques (!) .

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
int month = today.getMonthValue();  // Returns 1-12 as values.

Si vous voulez une date-heure pour un fuseau horaire, utilisez l'objet ZonedDateTime de la même manière.

ZonedDateTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
int month = now.getMonthValue();  // Returns 1-12 as values.

Convertir les classes héritées

Si vous avez un objet GregorianCalendar en main, convertissez-le en ZonedDateTime en utilisant la nouvelle méthode toZonedDateTime ajoutée à l'ancienne classe . Pour plus d'informations sur la conversion, voir Convertir Java.util.Date en quel type "Java.time"?

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime();
int month = zdt.getMonthValue();  // Returns 1-12 as values.

Month enum

Les classes Java.time incluent la pratique Monthenum , soit dit en passant. Utilisez des instances de cette classe dans votre code plutôt que de simples entiers pour rendre votre code plus auto-documenté, fournissez type-safety et garantissez des valeurs valides.

Month month = today.getMonth();  // Returns an instant of `Month` rather than integer.

L'énumération Month propose des méthodes utiles telles que la génération d'une chaîne avec le nom localisé du mois .


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes --- héritées date-heure telles que - Java.util.Date , Calendar , & SimpleDateFormat .

Le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers les classes Java.time .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 31 .

Où obtenir les classes Java.time?

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour de futurs ajouts possibles à Java.time. Vous pouvez trouver ici des classes utiles telles que Interval , YearWeek , YearQuarter , et plus .

7
Basil Bourque
cal.get(Calendar.MONTH) + 1;

La déclaration ci-dessus donne le numéro exact du mois. Comme get(Calendar.Month) renvoie le mois à partir de 0, l'ajout de 1 au résultat donnerait la sortie correcte. Et n'oubliez pas de soustraire 1 lors du réglage du mois.

cal.set(Calendar.MONTH, (8 - 1));

Ou utilisez les variables constantes fournies.

cal.set(Calendar.MONTH, Calendar.AUGUST);
3
krishnadhar

Il vaudrait mieux utiliser

Calendar.JANUARY

ce qui est nul ...

0
Maher Abuthraa