Java: Obtener mes entero desde la fecha

157

¿Cómo obtengo el mes como un entero de un objeto Date ( java.util.Date)?

Muhd
fuente
23
en realidad getMonth () en Fecha está en desuso desde siempre;)
Mateusz Dymczyk
66
@slhck: en desuso. A partir de JDK versión 1.1, reemplazado por Calendar.get (Calendar.MONTH).
adarshr
3
@Zenzen No veo el problema al usar un método obsoleto en una clase mayormente obsoleta.
Serabe
1
@Muhd si está trabajando con fechas, ayúdese y use joda o cualquier otra biblioteca.
Serabe
1
@Serabe: el problema es que hay mejores soluciones (que al menos no están en desuso). Y getMonth ha estado en desuso durante unos 14 años y ha estado en desuso por una razón.
Mateusz Dymczyk

Respuestas:

57

java.time (Java 8)

También puede usar el paquete java.time en Java 8 y convertir su java.util.Dateobjeto en un java.time.LocalDateobjeto y luego simplemente usar el getMonthValue()método.

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

Tenga en cuenta que los valores del mes se dan aquí del 1 al 12, al contrario de lo que cal.get(Calendar.MONTH)dice la respuesta de adarshr, que da valores del 0 al 11.

Pero como dijo Basil Bourque en los comentarios, la forma preferida es obtener un Monthobjeto enum con el LocalDate::getMonthmétodo.

Ortomala Lokni
fuente
1
Buena respuesta. Nota para el lector: es posible que desee especificar una zona horaria en lugar de confiar en la llamada predeterminada que se muestra en la Respuesta. Un nuevo día (y mes) amanece más temprano en París, por ejemplo, que en Montreal. Si te importa específicamente Montreal, el uso ZoneId.of( "America/Montreal" ).
Basil Bourque
1
Solo quiero agregar que hay un gran artículo sobre la introducción de java.time api oracle.com/technetwork/articles/java/…
Por cierto, otra nota para el lector: también puede obtener un Monthobjeto enum en lugar de un simple número entero. Month m = localDate.gotMonth();Ver LocalDate::getMonthmétodo El uso de objetos como este hace que su código se documente automáticamente, garantiza la seguridad de escritura y garantiza valores válidos. Vea el tutorial de Enum de Oracle.
Basil Bourque
1
si usas date.toInstant()y estás trabajando con un java.sql.Date(el hijo de java.util.Date) entonces obtendrás un UnsupportedOperationException. Pruebanew java.sql.Date(src.getTime()).toLocalDate()
Adam
1
@Adam Es mucho más fácil convertir a / desde java.sql.Dateusando los nuevos métodos de conversión agregados a esa clase anterior. java.sql.Date.valueOf( myLocalDate )y myJavaSqlDate.toLocalDate() Además, los conductores JDBC actualizan para JDBC 4.2 o posterior ya no necesitan java.sqltipos, y directamente puede abordar java.timetipos a través de la ResultSet::getObjecty PreparedStatement::setObjectmétodos.
Basil Bourque
287
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);
adarshr
fuente
166
Tenga en cuenta que Calendar.MONTHno hay razones aparentes basadas en CERO, es decir, enero == 0. Ahora eso está bien documentado en la API, pero sigue siendo confuso para los usuarios nuevos. Todavía tengo que encontrar a alguien que pueda decirme por qué se fueron con eso, tal vez es hora de una nueva pregunta SO (aunque me temo que no hay ningún gran fondo para eso: /)
Voo
55
El método @Voo Date.getMonth () estaba basado en cero, lo que probablemente sea la razón principal por la que Calendar.MONTH también lo es.
Muhd
1
@ Muhd ​​Claro que después de todo fue el reemplazo. Pero eso solo cambia la pregunta de por qué Date.getMonth () está basado en cero. Es un diseño horrible, especialmente porque los días comienzan en uno (¡al menos podrían ser consistentes!). Supongo que para empezar fue solo un poco de supervisión en una API no especialmente bien diseñada (tanto en fecha como en calendario). Pero tal vez haya algún precedente: me parece extraño y ha causado problemas a más de un principiante en mi experiencia.
Voo
2
En realidad ya se ha preguntado aquí en SO (y no solo). La conclusión es que es el resultado de una API mal diseñada. Quiero decir, como mencionaste, toda la clase Date es una broma. Lo curioso es que no solo Java sufre este problema, ¡la fecha getMonth () de iirc JavaScript también comienza con un 0!
Mateusz Dymczyk
1
@Voo getYear()también es, "sin razones aparentes", restado en 1900.
Hele
17

Si usa la API de fecha de Java 8 , ¡puede obtenerla directamente en una línea!

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

Joda-Time

Alternativamente, con la clase Joda-Time DateTime .

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

…o…

int month = dateTime.getMonthOfYear();
ssoward
fuente
2
Aún más simple, solo pregunte al DateTimeobjeto por su mes. int month = dateTime.getMonthOfYear();
Basil Bourque
Buena llamada Basil, he actualizado el código. Sin embargo, me gusta, .toString("MM")ya que muestra que hay más posibilidades que solo "MM".
ssoward
1
Esta respuesta ignora la cuestión crucial de la zona horaria. Vea mis comentarios sobre la pregunta y la respuesta de hermanos. Sugiero hacer pasar un DateTimeZoneobjeto a ese constructor Tiempo: 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 Detalles

La respuesta de Ortomala Lokni para usar java.time es correcta. Y debería usar java.time ya que es una mejora gigantesca sobre las antiguas clases java.util.Date/.Calendar. Consulte el Tutorial de Oracle en java.time.

Agregaré algún código que muestre cómo usar java.time sin tener en cuenta java.util.Date, para cuando comience con un código nuevo.

Usando java.time en pocas palabras ... Un Instantes un momento en la línea de tiempo en UTC. Aplicar una zona horaria ( ZoneId) para obtener a ZonedDateTime.

La Monthclase es una enumeración sofisticada para representar un mes en general. Esa enumeración tiene métodos útiles, como obtener un nombre localizado. Y tenga la seguridad de que el número de mes en java.time es cuerdo, 1-12, no el sinsentido basado en cero (0-11) que se encuentra en java.util.Date/.Calendar.

Para obtener la fecha y hora actual, la zona horaria es crucial. En cualquier momento la fecha no es la misma en todo el mundo. Por lo tanto, el mes no es el mismo en todo el mundo si está cerca del final / comienzo del mes.

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 );

Sobre java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date, Calendar, y SimpleDateFormat.

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de java.sql.*clases.

¿Dónde obtener las clases java.time?

El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más .

Albahaca Bourque
fuente
4

Si no puede usar el tiempo de Joda y aún vive en el mundo oscuro :) (Java 5 o inferior), puede disfrutar esto:

Nota: Asegúrese de que su fecha ya esté hecha con el formato: dd / 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
fuente
Eres la madre! / Είσαι η μάνα!
Tzegenos
0
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

El valor devuelto comienza desde 0, por lo que debe agregar uno al resultado.

twlkyao
fuente
66
2 problemas con su respuesta: uno es que puede hacer una cita con la hora actual new Date()sin hacerlo System.currentTimeMillis. El otro es que getMonth está en desuso.
Muhd
@ Muhd ​​Entonces, ¿cuál es la mejor solución?
twlkyao
@Muhd El System.currentTimeMillis () que agregué aquí era para indicar que aquí hay un tipo largo, y puede especificar la fecha.
twlkyao
44
Fecha :: getMonth ya estaba en desuso en Java 1.1 ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ortomala Lokni