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
Calendar returns wrong month
提问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 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 中Calendar和Date类返回的月份是从 0 而不是 1 开始索引的。所以 0 是一月,而当前月份,11 月是 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):
您可能想知道为什么会这样。起源于 POSIX 标准函数ctime
, gmtime
and 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 LocalDate
class 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 EST
or IST
as they are nottrue time zones, not standardized, and not even unique(!).
以、、 或等格式指定正确的时区名称。永远不要使用 3-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/region
America/Montreal
Africa/Casablanca
Pacific/Auckland
EST
IST
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
相同的方式使用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 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?
如果您GregorianCalendar
手头有对象,请转换为ZonedDateTime
使用toZonedDateTime
添加到旧类的新方法。有关更多转换信息,请参阅将 java.util.Date 转换为什么“java.time”类型?
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime();
int month = zdt.getMonthValue(); // Returns 1-12 as values.
Month
enum
Month
枚举
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.
顺便说一下,java.time 类包括方便的enum。在您的代码中使用此类的实例而不仅仅是整数,以使您的代码更具自文档性、提供类型安全并确保有效值。Month
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.
该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 类?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABPproject adapts ThreeTen-Backport(mentioned above) for Android specifically.
- See How to use ThreeTenABP….
- Java SE 8、Java SE 9及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 所述ThreeTenABP项目适应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. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。