English 中文(简体)
Calendar returns wrong month [duplicate]
原标题:
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?

问题回答

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

They start from 0 - check the docs

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.

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.

Months start from zero, like indexes for lists.

Therefore Jan = 0, Feb = 1, etc.

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

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.

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

It would be better to use

Calendar.JANUARY

which is zero ...





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签