Calendar rightNow = Calendar.getInstance();
String month = String.valueOf(rightNow.get(Calendar.MONTH));
执行上述代码后,月份的值变为10而不是11。为什么会这样呢?
Calendar rightNow = Calendar.getInstance();
String month = String.valueOf(rightNow.get(Calendar.MONTH));
执行上述代码后,月份的值变为10而不是11。为什么会这样呢?
月份索引从0开始,而不是1,因此10代表十一月,11代表十二月。
众所周知,许多答案表明月份从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
注意:输出可能会有所不同,这取决于区域设置。
正如一些人指出的那样,Java中Calendar和Date类返回的月份是从0开始索引而不是1。因此0代表一月,而当前的月份——十一月——是10。
你可能会想知道为什么会这样。其根源在于POSIX标准函数ctime
、gmtime
和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 */
月份从零开始,就像列表的索引一样。
因此,1月 = 0,2月 = 1,以此类推。
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 8 及更高版本中。这些类取代了旧的麻烦日期时间类,如 java.util.Date
、.Calendar
和 java.text.SimpleDateFormat
。
现在处于维护模式,Joda-Time 项目也建议迁移到 java.time。
要了解更多信息,请参阅 Oracle 教程。并搜索 Stack Overflow 获取许多示例和解释。
Java 6 和 7 中的大部分 java.time 功能都被移植到 ThreeTen-Backport,并进一步适配到 Android 中的 ThreeTenABP。
ThreeTen-Extra项目扩展了java.time的附加类,该项目是java.time可能未来添加内容的试验场。
在java.time中,月份数字确实是预期的1-12,分别对应一月到十二月。
LocalDate
类表示仅包含日期值而不包括时间和时区的值。
时区对于确定日期至关重要。对于任何给定的时刻,日期因时区而异。例如,在法国巴黎的午夜后几分钟是新的一天,而在魁北克蒙特利尔仍然是“昨天”。
请以大陆/地区
的格式指定一个正确的时区名称,例如America/Montreal
、Africa/Casablanca
或Pacific/Auckland
。千万不要使用3-4个字母的缩写,如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
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
。如需更多转换信息,请参见将java.util.Date转换为“java.time”类型?
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime();
int month = zdt.getMonthValue(); // Returns 1-12 as values.
Month
枚举顺便提一下,java.time 类中包括方便的 Month
枚举。在您的代码中使用此类的实例而不是仅仅使用整数,可以使您的代码更具自我说明性,提供类型安全性,并确保有效的值。
Month month = today.getMonth(); // Returns an instant of `Month` rather than integer.
< p > Month
枚举提供了有用的方法,例如生成一个 月份本地化名称 的字符串。
Java 8及更高版本内置java.time框架。这些类替代了麻烦的旧式legacy日期时间类,例如java.util.Date
、Calendar
和SimpleDateFormat
。
Joda-Time项目现在处于维护模式,建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。在Stack Overflow上搜索许多示例和解释。规范为JSR 310。ThreeTen-Extra项目通过增加额外的类,扩展了java.time。该项目是java.time未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如Interval
, YearWeek
, YearQuarter
和更多。
来自API:
一年中的第一个月是JANUARY,对应数字0;最后一个月取决于一年中的月份数量。
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html
cal.get(Calendar.MONTH) + 1;
上述语句给出了确切的月份数字。由于get(Calendar.Month)
返回从0开始计算的月份,因此将结果加1即可得到正确的输出。在设置月份时要记得减去1。
cal.set(Calendar.MONTH, (8 - 1));
cal.set(Calendar.MONTH, Calendar.AUGUST);
<code>
标签。Calendar.JANUARY
which is zero ...