Calendar returns wrong month

JavaCalendar

Java Problem Overview


Calendar rightNow = Calendar.getInstance();
String month = String.valueOf(rightNow.get(Calendar.MONTH));

After the execution of the above snippet, month gets a value of 10 instead of 11. How come?

Java Solutions


Solution 1 - Java

Months are indexed from 0 not 1 so 10 is November and 11 will be December.

Solution 2 - Java

Solution 3 - Java

As is clear by the many answers: the month starts with 0.

Here's a tip: you should be using SimpleDateFormat to get the String-representation of the month:

Calendar rightNow = Calendar.getInstance();
java.text.SimpleDateFormat df1 = new java.text.SimpleDateFormat("MM");
java.text.SimpleDateFormat df2 = new java.text.SimpleDateFormat("MMM");
java.text.SimpleDateFormat df3 = new java.text.SimpleDateFormat("MMMM");
System.out.println(df1.format(rightNow.getTime()));
System.out.println(df2.format(rightNow.getTime()));
System.out.println(df3.format(rightNow.getTime()));

Output:

11
Nov
November

Note: the output may vary, it is Locale-specific.

Solution 4 - Java

As several people have pointed out, months returned by the Calendar and Date classes in Java are indexed from 0 instead of 1. So 0 is January, and the current month, November, is 10.

You might wonder why this is the case. The origins lie with the POSIX standard functions ctime, gmtime and localtime, which accept or return a time_t structure with the following fields (from man 3 ctime):

int tm_mday;    /* day of month (1 - 31) */
int tm_mon;     /* month of year (0 - 11) */
int tm_year;    /* year - 1900 */

This API was copied pretty much exactly into the Java Date class in Java 1.0, and from there mostly intact into the Calendar class in Java 1.1. Sun fixed the most glaring problem when they introduced Calendar – the fact that the year 2001 in the Gregorian calendar was represented by the value 101 in their Date class. But I'm not sure why they didn't change the day and month values to at least both be consistent in their indexing, either from zero or one. This inconsistency and related confusion still exists in Java (and C) to this day.

Solution 5 - Java

Months start from zero, like indexes for lists.

Therefore Jan = 0, Feb = 1, etc.

Solution 6 - Java

From the API:

> The first month of the year is JANUARY > which is 0; the last depends on the > number of months in a year.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html

Solution 7 - Java

tl;dr

LocalDate.now()            // Returns a date-only `LocalDate` object for the current month of the JVM’s current default time zone.
         .getMonthValue()  // Returns 1-12 for January-December.

Details

Other answers are correct but outdated.

The troublesome old date-time classes had many poor design choices and flaws. One was the zero-based counting of month numbers 0-11 rather than the obvious 1-12.

java.time

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

Now in maintenance mode, the Joda-Time project also advises migration to java.time.

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

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.

Months 1-12

In java.time the month number is indeed the expected 1-12 for January-December.

The LocalDate class represents a date-only value without time-of-day and without time zone.

Time zone

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
int month = today.getMonthValue();  // Returns 1-12 as values.

If you want a date-time for a time zone, use ZonedDateTime object in the same way.

ZonedDateTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
int month = now.getMonthValue();  // Returns 1-12 as values.

Convert legacy classes

If you have a GregorianCalendar object in hand, convert to ZonedDateTime using new toZonedDateTime method added to the old class. For more conversion info, see Convert java.util.Date to what “java.time” type?

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime();
int month = zdt.getMonthValue();  // Returns 1-12 as values.

Month enum

The java.time classes include the handy Month enum, by the way. Use instances of this class in your code rather than mere integers to make your code more self-documenting, provide type-safety, and ensure valid values.

Month month = today.getMonth();  // Returns an instant of `Month` rather than integer.

The Month enum offers useful methods such as generating a String with the localized name of the month.


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.

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.

Solution 8 - Java

cal.get(Calendar.MONTH) + 1;

The above statement gives the exact number of the month. As get(Calendar.Month) returns month starting from 0, adding 1 to the result would give the correct output. And keep in mind to subtract 1 when setting the month.

cal.set(Calendar.MONTH, (8 - 1));

Or use the constant variables provided.

cal.set(Calendar.MONTH, Calendar.AUGUST);

Solution 9 - Java

It would be better to use

Calendar.JANUARY

which is zero ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHantView Question on Stackoverflow
Solution 1 - JavaVincent RamdhanieView Answer on Stackoverflow
Solution 2 - JavaBozhoView Answer on Stackoverflow
Solution 3 - JavaBart KiersView Answer on Stackoverflow
Solution 4 - JavaMatt RyallView Answer on Stackoverflow
Solution 5 - JavaFedererView Answer on Stackoverflow
Solution 6 - Javab.rothView Answer on Stackoverflow
Solution 7 - JavaBasil BourqueView Answer on Stackoverflow
Solution 8 - JavakrishnadharView Answer on Stackoverflow
Solution 9 - JavaMaher AbuthraaView Answer on Stackoverflow