Java 日历返回错误的月份

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1755199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:20:31  来源:igfitidea点击:

Calendar returns wrong month

javacalendar

提问by Hant

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?

执行上述代码段后,month 的值为 10 而不是 11。怎么会呢?

回答by Bozho

They start from 0 - check the docs

它们从 0 开始 - 检查文档

回答by Vincent Ramdhanie

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

月份从 0 而非 1 开始索引,因此 10 是 11 月,11 是 12 月。

回答by Federer

Months start from zero, like indexes for lists.

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

Therefore Jan = 0, Feb = 1, etc.

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

回答by b.roth

From the API:

从API:

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

一年的第一个月是 JANUARY,它是 0;最后一个取决于一年中的月数。

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

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

回答by Bart Kiers

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

从许多答案中可以清楚地看出:月份从 0 开始。

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

这是一个提示:您应该使用 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()));

Output:

输出:

11
Nov
November

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

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

回答by Matt Ryall

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

正如一些人指出的那样,Java 中CalendarDate类返回的月份是从 0 而不是 1 开始索引的。所以 0 是一月,而当前月份,11 月是 10。

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

您可能想知道为什么会这样。起源于 POSIX 标准函数ctime, gmtimeand localtime,它们接受或返回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 */

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.

这个 API 几乎完全复制到 Java 1.0 中的 Java Date 类中,从那里几乎完整地复制到 Java 1.1 中的 Calendar 类中。Sun 在引入 Calendar 时解决了最明显的问题——事实是,公历中的 2001 年由 Date 类中的值 101 表示。但是我不确定他们为什么不将日期和月份值更改为至少在索引中保持一致,无论是从零还是从一。直到今天,这种不一致和相关的混淆在 Java(和 C)中仍然存在。

回答by krishnadhar

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.

上面的语句给出了确切的月份数。当get(Calendar.Month)返回从 0 开始的月份时,将结果加 1 将给出正确的输出。并记住在设置月份时减去1。

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

Or use the constant variables provided.

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

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

回答by Maher Abuthraa

It would be better to use

最好使用

Calendar.JANUARY

which is zero ...

这是零...

回答by Basil Bourque

tl;dr

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.

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.

麻烦的旧日期时间类有许多糟糕的设计选择和缺陷。一种是从零开始计算月份数字 0-11,而不是明显的 1-12。

java.time

时间

The java.timeframework 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.

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

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

现在处于维护模式Joda-Time项目还建议迁移到 java.time。

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

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。

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

多的java.time功能后移植到Java 6和7在ThreeTen-反向移植和在进一步适于到Android ThreeTenABP

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

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

Months 1-12

1-12 个月

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

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

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

LocalDate级表示没有时间一天和不同时区的日期,唯一的价值。

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 Franceis a new day while still “yesterday” in Montréal Québec.

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

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

以、、 或等格式指定正确的时区名称。永远不要使用 3-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST

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 ZonedDateTimeobject in the same way.

如果您想要时区的日期时间,请以ZonedDateTime相同的方式使用object。

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

Convert legacy classes

转换遗留类

If you have a GregorianCalendarobject in hand, convert to ZonedDateTimeusing new toZonedDateTimemethod added to the old class. For more conversion info, see Convert java.util.Date to what “java.time” type?

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

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

Monthenum

Month枚举

The java.time classes include the handy Monthenum, 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.

顺便说一下,java.time 类包括方便的enum。在您的代码中使用此类的实例而不仅仅是整数,以使您的代码更具自文档性、提供类型安全并确保有效值。Month

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

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

Month枚举提供了有用的方法,如产生一个String与当月的本地化名称



About java.time

关于 java.time

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

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

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

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject 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.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多