日历返回错误的月份

时间:2009-11-18 10:53:56

标签: java calendar

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

执行上面的代码片段后,month得到的值为10而不是11.为什么?

9 个答案:

答案 0 :(得分:124)

月份的索引是从0而不是1,因此10是11月,11是12月。

答案 1 :(得分:28)

他们从0开始 - 检查the docs

答案 2 :(得分:22)

许多答案清楚地表明:月份从0开始。

这是一个提示:您应该使用SimpleDateFormat来获取月份的字符串表示形式:

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

注意:输出可能会有所不同,它是特定于区域设置的。

答案 3 :(得分:18)

正如几位人士所指出的那样,Java中CalendarDate类返回的月数是从0而不是1索引的。所以0是1月,当月是11月,10

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

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解决了最明显的问题 - 格里高利历中的2001年由他们的日期类中的值101表示。但我不确定为什么他们没有将日期和月份值更改为至少两者在索引中保持一致,无论是从零还是一。到目前为止,这种不一致和相关的混淆仍然存在于Java(和C)中。

答案 4 :(得分:10)

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

因此Jan = 0,Feb = 1等

答案 5 :(得分:8)

来自API:

  

一年中的第一个月是1月   这是0;最后取决于   一年中的月数。

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

答案 6 :(得分:7)

TL;博士

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-11月份的零点计数,而不是明显的1-12。

java.time

java.time框架内置于Java 8及更高版本中。这些类取代了旧的麻烦日期时间类,例如java.util.Date.Calendar和& java.text.SimpleDateFormat

现在在maintenance mode中,Joda-Time项目还建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。

大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport中的7,并在ThreeTenABP中进一步适应Android。

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。

1-12个月

在java.time中,月份数确实是1月到12月的预期1-12。

LocalDate类表示没有时间且没有时区的仅限日期的值。

时区

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

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.

转换旧版

如果您手头有GregorianCalendar个对象,请使用添加到旧类的新toZonedDateTime方法转换为ZonedDateTime。有关更多转化信息,请参阅Convert java.util.Date to what “java.time” type?

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

Month枚举

顺便说一句,java.time类包括方便的Month enum。在代码中使用此类的实例而不仅仅是整数,以使代码更具自我文档,提供type-safety并确保有效值。

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

Month枚举提供了有用的方法,例如使用localized name of the month生成字符串。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 7 :(得分:3)

cal.get(Calendar.MONTH) + 1;

以上陈述给出了月份的确切数字。当get(Calendar.Month)从0开始返回月份时,向结果中添加1会得到正确的输出。并且请记住在设置月份时减去1。

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

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

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

答案 8 :(得分:0)

最好使用

Calendar.JANUARY

这是零...