Java: Отримайте цілий місяць із дати


157

Як отримати місяць як ціле число з об’єкта Date ( java.util.Date)?


23
насправді getMonth () на дату застаріло з віком;)
Матеуш Дімчик

6
@slhck: застаріле. Станом на версію 1.1 JDK, замінено на Calendar.get (Calendar.MONTH).
adarshr

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

1
@Muhd, якщо ви працюєте з датами, допоможіть собі та використовуйте joda або будь-яку іншу бібліотеку.
Серабе

1
@Serabe: проблема полягає в тому, що є кращі рішення (ті, які принаймні не застаріли). І getMonth був застарілий, як уже 14 років, і його застаріло не просто так.
Матеуш Димчик

Відповіді:


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об'єкта перерахунку LocalDate::getMonthметодом.


1
Хороша відповідь. Примітка читачеві: можливо, ви хочете вказати часовий пояс, а не покладатися на дзвінок за замовчуванням, показаний у відповіді. Наприклад, новий день (і місяць) світить раніше в Парижі, ніж Монреаль. Якщо ви конкретно переймаєтесь Montréal, використовуйте ZoneId.of( "America/Montreal" ).
Василь Бурк

1
Я просто хочу додати, що є чудова стаття про впровадження java.time api oracle.com/technetwork/articles/java/…

До речі, ще одна примітка для читача: Ви також можете отримати об'єкт Monthenum, а не просто ціле число. 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 () базувався на нулях, що, мабуть, є основною причиною календаря.MONTH.
Muhd

1
@Muhd Звичайно, це була його заміна. Але це лише зміщує питання навколо того, чому на основі нуля Date.getMonth () нульовий? Я жахливий дизайн, тим більше що дні починаються з одного (вони, принаймні, можуть бути послідовними!). Я припускаю, що це був лише деякий нагляд над не особливо добре розробленим API (як датою, так і календарем). Але, можливо, є якийсь прецедент - це мені просто здається дивним і спричиняє проблеми більш ніж одному новачкові в моєму досвіді.
Voo

2
Насправді про це вже просили тут (і не тільки). Суть полягає в тому, що це результат погано розробленого API. Я маю на увазі, як ви згадали, весь клас Дата - це жарт. Цікавим фактом є те, що не тільки Java страждає від цієї проблеми - iirc JavaScript Date getMonth () також починається з 0!
Матеуш Дімчик

1
@Voo getYear()також, "без видимих ​​причин", віднімається до 1900 року.
Hele

17

Якщо ви використовуєте Java 8 date api, ви можете безпосередньо отримати його в одному рядку!

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

7

Joda-Time

Як варіант, з класом 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 . І шукайте переповнення стека за багатьма прикладами та поясненнями. Специфікація - 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 або новішої версії), ви можете насолоджуватися цим:

Примітка. Переконайтеся, що ваша дата вже вказана у форматі: dd / MM / GYYY

/**
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
Дата :: getMonth уже застаріла в Java 1.1 ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ortomala Lokni
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.