Java: obtenir un entier du mois à partir de la date

157

Comment obtenir le mois sous forme d'entier à partir d'un objet Date ( java.util.Date)?

Muhd
la source
23
en fait getMonth () on Date est obsolète depuis toujours;)
Mateusz Dymczyk
6
@slhck: obsolète. À partir de la version 1.1 de JDK, remplacé par Calendar.get (Calendar.MONTH).
adarshr
3
@Zenzen Je ne vois pas le problème d'utiliser une méthode obsolète dans une classe principalement obsolète.
Serabe
1
@Muhd si vous travaillez avec des dates, aidez-vous et utilisez joda ou toute autre bibliothèque.
Serabe
1
@Serabe: le problème est qu'il existe de meilleures solutions (celles qui au moins ne sont pas obsolètes). Et getMonth est obsolète depuis environ 14 ans maintenant et il est obsolète pour une raison.
Mateusz Dymczyk

Réponses:

57

java.time (Java 8)

Vous pouvez également utiliser le package java.time dans Java 8 et convertir votre java.util.Dateobjet en java.time.LocalDateobjet, puis simplement utiliser la getMonthValue()méthode.

Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
int month = localDate.getMonthValue();

Notez que les valeurs des mois sont ici données de 1 à 12 contrairement à cal.get(Calendar.MONTH)la réponse d'adarshr qui donne des valeurs de 0 à 11.

Mais comme Basil Bourque l'a dit dans les commentaires, la méthode préférée est d'obtenir un Monthobjet enum avec la LocalDate::getMonthméthode.

Ortomala Lokni
la source
1
Bonne réponse. Remarque pour le lecteur: vous souhaiterez peut-être spécifier un fuseau horaire plutôt que de vous fier à l'appel par défaut indiqué dans la réponse. Un nouveau jour (et un mois) se lève plus tôt à Paris, par exemple, qu'à Montréal. Si vous vous souciez spécifiquement de Montréal, l'utilisation ZoneId.of( "America/Montreal" ).
Basil Bourque
1
Je veux juste ajouter qu'il y a un excellent article sur l'introduction de java.time api oracle.com/technetwork/articles/java
En passant, une autre note au lecteur: vous pouvez également obtenir un Monthobjet enum plutôt qu'un simple nombre entier. Month m = localDate.gotMonth();Voir la LocalDate::getMonthméthode. L'utilisation d'objets tels que celui-ci rend votre code auto-documenté, garantit la sécurité du type et garantit des valeurs valides. Voir le didacticiel Enum d'Oracle.
Basil Bourque
1
si vous utilisez date.toInstant()et que vous travaillez avec un java.sql.Date(l'enfant de java.util.Date), vous obtiendrez un fichier UnsupportedOperationException. Essayernew java.sql.Date(src.getTime()).toLocalDate()
Adam
1
@Adam Il est beaucoup plus facile de convertir vers / depuis java.sql.Dateen utilisant les nouvelles méthodes de conversion ajoutées à cette ancienne classe. java.sql.Date.valueOf( myLocalDate )et myJavaSqlDate.toLocalDate() aussi, les pilotes JDBC mis à jour pour JDBC 4.2 ou version ultérieure ne ont plus besoin java.sqltypes, et peuvent aborder directement les java.timetypes via ResultSet::getObjectet PreparedStatement::setObjectméthodes.
Basil Bourque
287
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);
Adarshr
la source
166
Notez que ce Calendar.MONTHn'est pour aucune raison apparente basée sur ZERO, c'est-à-dire janvier == 0. Maintenant, c'est bien documenté dans l'API, mais c'est toujours déroutant pour les nouveaux utilisateurs. Je n'ai encore trouvé personne qui pourrait me dire pourquoi ils ont opté pour cela - peut-être temps pour une nouvelle question SO moi-même (bien que je crains qu'il n'y ait pas de bon contexte à cela: /)
Voo
5
La méthode @Voo Date.getMonth () était basée sur zéro, ce qui est probablement la principale raison pour laquelle Calendar.MONTH l'est également.
Muhd
1
@Muhd Bien sûr, après tout, c'était le remplacement. Mais cela ne fait que déplacer la question vers pourquoi Date.getMonth () était-il basé sur zéro? Imo un design horrible, d'autant plus que les jours commencent à un (ils pourraient au moins être cohérents!). Je suppose que c'était juste une erreur dans une API pas particulièrement bien conçue (à la fois date et calendrier) pour commencer. Mais peut-être qu'il y a un précédent - cela me semble étrange et a causé des problèmes à plus d'un débutant dans mon expérience.
Voo
2
En fait, il a déjà été demandé ici sur SO (et pas seulement). L'essentiel est que c'est le résultat d'une API mal conçue. Je veux dire, comme vous l'avez mentionné, toute la classe Date est une blague. Le fait amusant est que non seulement Java souffre de ce problème - Date getMonth () de JavaScript iirc commence également par un 0!
Mateusz Dymczyk
1
@Voo getYear()est également, "pour aucune raison apparente", soustrait de 1900.
Hele
17

Si vous utilisez l' API de date Java 8 , vous pouvez l'obtenir directement en une seule ligne!

LocalDate today = LocalDate.now();
int month = today.getMonthValue();
Ketan Chitale
la source
7

Joda-Time

Alternativement, avec la classe Joda-Time DateTime .

//convert date to datetime
DateTime datetime = new DateTime(date);
int month = Integer.parseInt(datetime.toString("MM"))

…ou…

int month = dateTime.getMonthOfYear();
vers
la source
2
Encore plus simple, il suffit de demander à l' DateTimeobjet son mois. int month = dateTime.getMonthOfYear();
Basil Bourque
Bon appel Basil, j'ai mis à jour le code. Cependant, j'aime le .toString("MM")car il montre qu'il y a plus de possibilités que juste "MM".
vers le
1
Cette réponse ignore la question cruciale du fuseau horaire. Voir mes commentaires sur la question et la réponse des frères et sœurs. Je suggère le passage d' un DateTimeZoneobjet à ce constructeur DateTime: DateTimeZone.forID( "America/Montreal" ).
Basil Bourque
6

tl; dr

myUtilDate.toInstant()                          // Convert from legacy class to modern. `Instant` is a point on the timeline in UTC.
          .atZone(                              // Adjust from UTC to a particular time zone to determine date. Renders a `ZonedDateTime` object. 
              ZoneId.of( "America/Montreal" )   // Better to specify desired/expected zone explicitly than rely implicitly on the JVM’s current default time zone.
          )                                     // Returns a `ZonedDateTime` object.
          .getMonthValue()                      // Extract a month number. Returns a `int` number.

java.time Détails

La réponse d'Ortomala Lokni pour l'utilisation de java.time est correcte. Et vous devriez utiliser java.time car il s'agit d'une amélioration gigantesque par rapport aux anciennes classes java.util.Date/.Calendar. Consultez le didacticiel Oracle sur java.time.

J'ajouterai du code montrant comment utiliser java.time sans égard à java.util.Date, lorsque vous commencez avec du nouveau code.

Utiliser java.time en un mot… An Instantest un moment sur la chronologie en UTC. Appliquez un fuseau horaire ( ZoneId) pour obtenir un fichier ZonedDateTime.

La Monthclasse est une énumération sophistiquée pour représenter un mois en général. Cette énumération a des méthodes pratiques telles que l'obtention d'un nom localisé. Et soyez assurés que le numéro du mois dans java.time est un mois sain, 1-12, et non le non-sens de base zéro (0-11) trouvé dans java.util.Date/.Calendar.

Pour obtenir la date-heure actuelle, le fuseau horaire est crucial. A tout moment, la date n'est pas la même dans le monde. Par conséquent, le mois n'est pas le même dans le monde s'il se rapproche de la fin / du début du mois.

ZoneId zoneId = ZoneId.of( "America/Montreal" );  // Or 'ZoneOffset.UTC'.
ZonedDateTime now = ZonedDateTime.now( zoneId );
Month month = now.getMonth(); 
int monthNumber = month.getValue(); // Answer to the Question.
String monthName = month.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH );

À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, et SimpleDateFormat.

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

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

Vous pouvez échanger des objets java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de java.sql.*classes.

Où obtenir les classes java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 et versions ultérieures
    • Intégré.
    • Partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Versions ultérieures des implémentations de bundle Android des classes java.time.
    • Pour les versions antérieures d'Android (<26), le projet ThreeTenABP adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP… .

Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels futurs ajouts à java.time. Vous trouverez peut - être des classes utiles ici, comme Interval, YearWeek, YearQuarteret plus .

Basil Bourque
la source
4

Si vous ne pouvez pas utiliser Joda time et que vous vivez toujours dans le monde sombre :) (Java 5 ou inférieur), vous pouvez en profiter:

Remarque: assurez-vous que votre date est déjà faite au format: jj / MM / AAAA

/**
Make an int Month from a date
*/
public static int getMonthInt(Date date) {

    SimpleDateFormat dateFormat = new SimpleDateFormat("MM");
    return Integer.parseInt(dateFormat.format(date));
}

/**
Make an int Year from a date
*/
public static int getYearInt(Date date) {

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
    return Integer.parseInt(dateFormat.format(date));
}
Badr DRAIFI
la source
Tu es la mère! / Είσαι η μάνα!
Tzegenos
0
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

La valeur renvoyée commence à 0, vous devez donc en ajouter un au résultat.

twlkyao
la source
6
2 problèmes avec votre réponse: l'un est que vous pouvez faire une date avec l'heure actuelle en vous en new Date()passant System.currentTimeMillis. L'autre est que getMonth est obsolète.
Muhd
@Muhd Alors, quelle est la meilleure solution?
twlkyao
@Muhd Le System.currentTimeMillis () que j'ai ajouté ici était pour indiquer qu'il s'agit d'un type long, et vous pouvez spécifier la date.
twlkyao
4
Date :: getMonth était déjà obsolète dans Java 1.1 ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ortomala Lokni