Calendar returns wrong month

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?

73742 次浏览

They start from 0 - check 那些文件

月份指数从0开始,而不是从1开始,所以10是11月,11是12月。

月份从零开始,就像列表的索引一样。

因此 Jan = 0,Feb = 1,等等。

空气污染指数:

一年的第一个月是一月 其值为0; 最后一个值取决于 number of months in a year.

Http://java.sun.com/j2se/1.5.0/docs/api/java/util/calendar.html

从许多答案中可以清楚地看出: 这个月以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()));

产出:

11
Nov
November

注意: 输出可能有所不同,它是特定于语言环境的。

正如一些人指出的那样,Java 中 日历日期类返回的月份的索引值从0而不是1。所以0代表一月,而当前的月份11月是10。

你可能想知道为什么会这样。起源于 POSIX 标准函数 ctimegmtimelocaltime,它们接受或返回具有以下字段(来自 man 3 ctime)的 time_t结构:

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

这个 API 几乎完全复制到 Java 1.0中的 Java Date 类中,并且基本上完整地复制到 Java 1.1中的 Calendar 类中。Sun 在引入 Calendar 时解决了一个最突出的问题——公历中的2001年由 Date 类中的值101表示。但我不确定为什么他们没有将日期和月份的值改为至少两者在索引中是一致的,无论是从0还是1。这种不一致性和相关的混淆至今仍然存在于 Java (和 C)中。

cal.get(Calendar.MONTH) + 1;

上述报表给出了该月份的确切数字。当 get(Calendar.Month)返回从0开始的月份时,将1添加到结果中将得到正确的输出。记住设置月份时要减1。

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

或者使用提供的常量变量。

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

最好还是用

Calendar.JANUARY

which is zero ...

博士

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.

细节

其他的答案是正确的,但是已经过时了。

令人烦恼的旧日期时间类有许多糟糕的设计选择和缺陷。其中之一是从0开始计算月份数字0-11,而不是显而易见的1-12。

爪哇时间

爪哇时间框架内置于 Java8及更高版本中。这些类取代了旧的麻烦的日期时间类,如 java.util.Date.Calendarjava.text.SimpleDateFormat

现在在 维修模式中,Joda 时间项目也建议迁移到 java.time。

要了解更多,请参阅 Oracle 教程。并搜索堆栈溢出许多例子和解释。

Much of the java.time functionality is back-ported to Java 6 & 7 in 310-后端口 and further adapted to Android in 三个十分.

ThreeTen-Extra项目使用其他类扩展 java.time。

Months 1-12

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

LocalDate类表示一个仅限于日期的值,不包含一天中的时间和时区。

时区

时区对确定日期至关重要。对于任何给定的时刻,日期在全球各地区不同。例如,在 法国巴黎中午夜后的几分钟是新的一天,而在 魁北克蒙特利尔中仍然是“昨天”。

指定 continent/region格式的 正确的时区名称,例如 America/MontrealAfrica/CasablancaPacific/Auckland。永远不要使用3-4个字母的缩写,如 ESTIST,因为它们是 没有真正的时区,不标准化,甚至不唯一(!).

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

如果需要时区的日期时间,请以相同的方式使用 ZonedDateTime对象。

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 将 java.util.Date 转换为“ java.time”类型

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

Month枚举

顺便说一下,time 类包括方便的 Month 枚举。在代码中使用这个类的实例,而不仅仅是整数,这样可以使代码更具有自记录性,提供 type-safety,并确保有效值。

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 本地化的月份名称.


关于爪哇时间

爪哇时间框架内置于 Java8及更高版本中。这些类取代了令人讨厌的旧的 legacy日期时间类,如 java.util.DateCalendarSimpleDateFormat

现在在 维修模式中的 Joda-Time项目建议迁移到 爪哇时间类。

要了解更多,请参阅 Oracle 教程。并搜索堆栈溢出许多例子和解释。规范是 JSR 310

从哪里获得 java.time 类?

< strong > Three Ten-Ultra 项目使用其他类扩展 java.time。这个项目是将来可能添加 java.time 的试验场。您可以在这里找到一些有用的类,比如 IntervalYearWeekYearQuarter更多