194

How do I get the month as an integer from a Date object (java.util.Date)?

MR AND
  • 376
  • 7
  • 29
Muhd
  • 24,305
  • 22
  • 61
  • 78
  • 25
    actually getMonth() on Date is deprecated since forever ;) – Mateusz Dymczyk Aug 24 '11 at 22:20
  • 6
    @slhck: Deprecated. As of JDK version 1.1, replaced by Calendar.get(Calendar.MONTH). – adarshr Aug 24 '11 at 22:20
  • @adarshr That's why I didn't write an answer. So much for a specific and well-researched question! – slhck Aug 24 '11 at 22:21
  • 4
    @Zenzen I don't see the problem in using a deprecated method in a mostly deprecated class. – Serabe Aug 24 '11 at 22:22
  • 1
    @Muhd if you are working with dates, help yourself and use [joda](http://joda-time.sourceforge.net/) or any other library. – Serabe Aug 24 '11 at 22:23
  • @slhck I like using Stack Overflow as a reference, and this was missing so I asked. – Muhd Aug 24 '11 at 22:25
  • 1
    @Serabe: the problem is that there are better solutions (ones that at least aren't deprecated). And getMonth has been deprecated for like 14 years now and it's been deprecated for a reason. – Mateusz Dymczyk Aug 24 '11 at 22:40
  • 1
    @Zenzen: it was a joke regarding the use of a class whose methods are mostly deprecated (22 out of 33, including constructors). Sorry for the misunderstood. – Serabe Aug 24 '11 at 22:44
  • Seriously, when this question was asked 11 years ago there often was no way around using `Date`, but today no one should. We have [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/index.html). – Ole V.V. Jul 29 '22 at 16:30

8 Answers8

326
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);
SadeepDarshana
  • 1,057
  • 18
  • 34
adarshr
  • 61,315
  • 23
  • 138
  • 167
  • 184
    Note that `Calendar.MONTH` is for no apparent reasons ZERO based, ie January==0. Now that's documented just fine in the API, but it's still confusing as hell for first time users. I've yet to find anyone who could tell me why they went with that - maybe time for a new SO question myself (though I fear there isn't any great background to that :/ ) – Voo Aug 24 '11 at 22:24
  • 5
    @Voo Date.getMonth() method was zero based, which is probably the main reason Calendar.MONTH is as well. – Muhd Aug 24 '11 at 22:37
  • 1
    @Muhd Sure after all it was the replacement. But that only shifts the question around to why was Date.getMonth() zero based? Imo a horrible design, especially since days start at one (they could at least be consistent!). I assume it was just some oversight in a not especially well designed API (both Date and Calendar) to begin with. But maybe there's some precedent - it just seems strange to me and has caused problems to more than one beginner in my experience. – Voo Aug 24 '11 at 22:42
  • 2
    Actually it's been asked already here on SO (and not only). The bottom line is tnat it's a result of badly designed API. I mean as you mentioned the whole Date class is a joke. Fun fact is that not only Java suffers from this problem - iirc JavaScript's Date getMonth() also starts with a 0! – Mateusz Dymczyk Aug 24 '11 at 22:49
  • 1
    @Voo `getYear()` is also, "for no apparent reasons", subtracted by 1900. – Hele Aug 06 '13 at 01:34
  • @MateuszDymczyk Turns out JS's Date [is just a clone of Java's](http://www.jwz.org/blog/2010/10/every-day-i-learn-something-new-and-stupid/#comment-1048) – user123444555621 Aug 20 '14 at 22:23
  • 1
    **CAUTION** This Answer fails to address the issue of time zone. For date-time values around the end of the month, the resulting month number could swing either way to past month or next month depending on the JVM’s current default time zone. Better to explicitly specify the desired/expected time zone. – Basil Bourque Jun 21 '15 at 07:36
  • Best answer for lower api (In my case api 21) – Thomas Pires Oct 17 '20 at 08:46
  • For some reason this returns 7 for september here. Doesn't make sense. If I take a look at the calendar object start date is set for february. Doesn't make sense, no matter how I look at it. – Lavandysh Aug 11 '21 at 14:47
85

java.time (Java 8)

You can also use the java.time package in Java 8 and convert your java.util.Date object to a java.time.LocalDate object and then just use the getMonthValue() method.

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

Note that month values are here given from 1 to 12 contrary to cal.get(Calendar.MONTH) in adarshr's answer which gives values from 0 to 11.

But as Basil Bourque said in the comments, the preferred way is to get a Month enum object with the LocalDate::getMonth method.

Muhd
  • 24,305
  • 22
  • 61
  • 78
Ortomala Lokni
  • 56,620
  • 24
  • 188
  • 240
  • 1
    Good answer. Note to the reader: You may want to specify a time zone rather than rely on the call for default shown in the Answer. A new day (and month) dawns earlier in Paris, for example, than Montréal. If you care specifically about Montréal, the use `ZoneId.of( "America/Montreal" )`. – Basil Bourque Jun 21 '15 at 07:26
  • 1
    I just want to add that there is a great article about the introduction of *java.time* api http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html –  Jun 21 '15 at 07:55
  • By the way, another note to the reader: You can also get a **[`Month`](http://docs.oracle.com/javase/8/docs/api/java/time/Month.html) enum object** rather than a mere integer number. `Month m = localDate.gotMonth();` See [`LocalDate::getMonth`](http://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#getMonth--) method. Using objects such as this makes your code self-documenting, ensures type-safety, and guarantees valid values. See [Enum tutorial](https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html) by Oracle. – Basil Bourque Dec 26 '16 at 22:55
  • 1
    if you use `date.toInstant()` and you happen to be working with a `java.sql.Date` (the child of `java.util.Date`) then you will get an `UnsupportedOperationException`. Try `new java.sql.Date(src.getTime()).toLocalDate()` – Adam Feb 24 '17 at 14:15
  • 1
    @Adam Much easier to convert to/from [`java.sql.Date`](https://docs.oracle.com/javase/8/docs/api/java/sql/Date.html) by using the new conversion methods added to that old class. `java.sql.Date.valueOf( myLocalDate )` and `myJavaSqlDate.toLocalDate()` Also, JDBC drivers updated for JDBC 4.2 or later no longer need `java.sql` types, and can directly address `java.time` types via the `ResultSet::getObject` and `PreparedStatement::setObject` methods. – Basil Bourque Mar 23 '17 at 07:55
  • Good to know about JDBC 4.2 and I agree with you, but the warning about the `UnsupportedOperationException` applies unless you are absolutely sure you're not going to be passed `java.sql.Date` when you use `java.util.Date::toInstant`. A poor implementation when they wrote `java.sql.Date`, IMHO. – Adam Mar 23 '17 at 13:14
21

If you use Java 8 date api, you can directly get it in one line!

LocalDate today = LocalDate.now();
int month = today.getMonthValue();
Xanlantos
  • 887
  • 9
  • 18
Ketan Chitale
  • 331
  • 3
  • 4
9

Joda-Time

Alternatively, with the Joda-Time DateTime class.

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

…or…

int month = dateTime.getMonthOfYear();
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
ssoward
  • 540
  • 5
  • 9
  • 3
    Even simpler, just ask the `DateTime` object’s for its month. `int month = dateTime.getMonthOfYear();` – Basil Bourque Jul 28 '14 at 23:16
  • Good call Basil, I have updated the code. However, I like the `.toString("MM")` as it shows there are more possibilities than just "MM". – ssoward Jul 29 '14 at 22:04
  • 1
    This answer ignores the crucial issue of time zone. See my comments on Question and sibling Answer. I suggest passing a `DateTimeZone` object to that DateTime constructor: `DateTimeZone.forID( "America/Montreal" )`. – Basil Bourque Jun 21 '15 at 07:40
8

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 Details

The Answer by Ortomala Lokni for using java.time is correct. And you should be using java.time as it is a gigantic improvement over the old java.util.Date/.Calendar classes. See the Oracle Tutorial on java.time.

I'll add some code showing how to use java.time without regard to java.util.Date, for when you are starting out with fresh code.

Using java.time in a nutshell… An Instant is a moment on the timeline in UTC. Apply a time zone (ZoneId) to get a ZonedDateTime.

The Month class is a sophisticated enum to represent a month in general. That enum has handy methods such as getting a localized name. And rest assured that the month number in java.time is a sane one, 1-12, not the zero-based nonsense (0-11) found in java.util.Date/.Calendar.

To get the current date-time, time zone is crucial. At any moment the date is not the same around the world. Therefore the month is not the same around the world if near the ending/beginning of the month.

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

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
6

If you can't use Joda time and you still live in the dark world :) ( Java 5 or lower ) you can enjoy this :

Note: Make sure your date is allready made by the format : dd/MM/YYYY

/**
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));
}
Markus Pscheidt
  • 6,853
  • 5
  • 55
  • 76
Badr DRAIFI
  • 335
  • 4
  • 12
1

If we use java.time.LocalDate api, we can get month number in integer in single line:

import java.time.LocalDate;
...
int currentMonthNumber = LocalDate.now().getMonthValue(); //OR
LocalDate scoringDate = LocalDate.parse("2022-07-01").getMonthValue(); //for String date

For example today's date is 29-July-2022, output will be 7.

Shailesh Vikram Singh
  • 1,433
  • 17
  • 26
  • May also use `YearMonth.now()` or `MonthDay.now()`. And may pass a `ZoneId` to the `now` method to make it clear that the operation is time zone dependent. – Ole V.V. Jul 29 '22 at 16:28
0
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

The returned value starts from 0, so you should add one to the result.

twlkyao
  • 14,302
  • 7
  • 27
  • 44