Java: получить месячное целое число от даты


157

Как получить месяц как целое число из объекта Date ( java.util.Date)?


23
фактически getMonth () на Date устарела навсегда;)
Mateusz Dymczyk

6
@slhck: устарел. Начиная с версии 1.1 JDK, заменен на Calendar.get (Calendar.MONTH).
adarshr

3
@Zenzen Я не вижу проблемы в использовании устаревшего метода в основном в устаревшем классе.
Сераб

1
@Muhd, если вы работаете с датами, помогите себе и используйте joda или любую другую библиотеку.
Сераб

1
@Serabe: проблема в том, что есть лучшие решения (которые, по крайней мере, не устарели). И вот уже 14 лет getMonth устарела и по какой-то причине устарела.
Матеуш Дымчик

Ответы:


57

java.time (Java 8)

Вы также можете использовать пакет java.time в Java 8 и преобразовать ваш java.util.Dateобъект в java.time.LocalDateобъект, а затем просто использовать getMonthValue()метод.

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

Обратите внимание, что значения месяца здесь даны от 1 до 12, cal.get(Calendar.MONTH)в отличие от ответа adarshr, который дает значения от 0 до 11.

Но, как сказал в комментариях Василий Бурк, предпочтительным способом является получение Monthобъекта enum с помощью LocalDate::getMonthметода.


1
Хороший ответ. Примечание для читателя: вы можете указать часовой пояс, а не полагаться на вызов по умолчанию, указанный в ответе. Например, в Париже новый день (и месяц) наступает раньше, чем в Монреале. Если вы заботитесь конкретно о Монреале, используйте ZoneId.of( "America/Montreal" ).
Василий Бурк

1
Я просто хочу добавить , что есть большая статья о введении java.time апите oracle.com/technetwork/articles/java/...

Кстати, еще одно замечание для читателя: вы также можете получить Monthобъект enum, а не просто целое число. Month m = localDate.gotMonth();Смотрите LocalDate::getMonthметод. Использование таких объектов делает ваш код самодокументируемым, обеспечивает безопасность типов и гарантирует допустимые значения. См. Учебник по Enum от Oracle.
Василий Бурк

1
если вы используете date.toInstant()и работаете с java.sql.Date(ребенком java.util.Date), вы получите UnsupportedOperationException. Попробуйтеnew java.sql.Date(src.getTime()).toLocalDate()
Адам

1
@ Adam Гораздо проще конвертировать в / из java.sql.Date, используя новые методы конвертации, добавленные в этот старый класс. java.sql.Date.valueOf( myLocalDate )а myJavaSqlDate.toLocalDate() также драйверы JDBC обновлены для JDBC 4.2 или более поздней версии больше не нужны java.sqlтипы, и могут непосредственно адреса java.timeтипов с помощью ResultSet::getObjectи PreparedStatement::setObjectметоды.
Василий Бурк

287
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);

166
Обратите внимание, что Calendar.MONTHбез видимых причин основывается на нуле, то есть в январе == 0. Теперь это хорошо документировано в API, но это все еще чертовски запутанно для начинающих пользователей. Я еще не нашел никого, кто мог бы сказать мне, почему они пошли с этим - возможно, пришло время для нового SO вопроса (хотя я боюсь, что нет большого фона для этого: /)
Voo

5
Метод @Voo Date.getMonth () основывался на нуле, что, вероятно, является основной причиной Calendar.MONTH.
Muhd

1
@Muhd Конечно, в конце концов это была замена. Но это только сдвигает вопрос о том, почему Date.getMonth () был основан на нуле? Imo ужасный дизайн, особенно если учесть, что дни начинаются в один день (по крайней мере, они могут быть последовательными!). Я предполагаю, что для начала это был просто некоторый недосмотр в не очень хорошо разработанном API (как Date, так и Calendar). Но, может быть, есть какой-то прецедент - он просто кажется мне странным и вызвал проблемы у более чем одного новичка в моем опыте.
Во

2
На самом деле это уже было задано здесь, на SO (и не только). Суть в том, что это результат плохо разработанного API. Я имею в виду, как вы упомянули, весь класс Date - это шутка. Интересен тот факт, что не только Java страдает от этой проблемы - iirc JavaScript getMonth () также начинается с 0!
Матеуш Дымчик

1
@ Voo getYear()также, «без видимых причин», вычитается к 1900 году.
Hele

17

Если вы используете Java 8 date api, вы можете получить его в одну строку!

LocalDate today = LocalDate.now();
int month = today.getMonthValue();

7

Joda времени

Кроме того, с классом Joda-Time DateTime .

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

…или…

int month = dateTime.getMonthOfYear();

2
Еще проще, просто спросите у DateTimeобъекта месяц. int month = dateTime.getMonthOfYear();
Василий Бурк

Добрый звонок, Василий, я обновил код. Тем не менее, мне нравится, .toString("MM")как это показывает, что есть больше возможностей, чем просто «ММ».
ssoward

1
Этот ответ игнорирует критическую проблему часового пояса. Смотрите мои комментарии на вопрос и ответ родного брата. Я предлагаю пропускание DateTimeZoneобъекта к этому DateTime конструктору: DateTimeZone.forID( "America/Montreal" ).
Василий Бурк

6

ТЛ; др

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 подробности

Ответ Ортомалы Локни за использование java.time правильный. И вы должны использовать java.time, поскольку это гигантское улучшение по сравнению со старыми классами java.util.Date/.Calendar. Смотрите руководство по Oracle на java.time.

Я добавлю код, показывающий, как использовать java.time без учета java.util.Date, когда вы начинаете со свежим кодом.

Использование java.time в двух словах ... Это Instantмомент времени на UTC. Примените часовой пояс ( ZoneId), чтобы получить ZonedDateTime.

MonthКласс представляет собой сложное перечисление для представления в месяц в целом. Это перечисление имеет удобные методы, такие как получение локализованного имени. И будьте уверены, номер месяца в java.time является нормальным, 1-12, а не бессмысленной ерундой (0-11), найденной в java.util.Date/.Calendar.

Чтобы получить текущую дату и время, часовой пояс имеет решающее значение. В любой момент дата не одинакова во всем мире. Поэтому месяц не одинаков во всем мире, если он близок к концу / началу месяца.

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

О java.time

Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые устаревшие классы даты и времени , такие как java.util.Date, Calendar, и SimpleDateFormat.

Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, смотрите Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии . Нет необходимости в строках, нет необходимости в java.sql.*классах.

Где взять классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 и более поздние версии
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java.time.
    • Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP… .

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как Interval, YearWeek, YearQuarter, и более .


4

Если вы не можете использовать время Joda и все еще живете в темном мире :) (Java 5 или ниже), вы можете наслаждаться этим:

Примечание. Убедитесь, что дата уже указана в формате: дд / мм / гггг

/**
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));
}

Ты мать! / Είσαι η μάνα!
Цегенос

0
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

Возвращаемое значение начинается с 0, поэтому вы должны добавить его к результату.


6
2 проблемы с вашим ответом: во-первых, вы можете сделать дату с текущим временем, new Date()обходясь без System.currentTimeMillis. Другая причина в том, что getMonth устарела.
Мухд

@Muhd Так, что является лучшим решением?
twlkyao

@Muhd System.currentTimeMillis (), который я добавил здесь, должен был указать, что здесь длинный тип, и вы можете указать дату.
twlkyao

4
Date :: getMonth уже устарел в Java 1.1 ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ортомала Локни,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.