日历返回错误的月份
Calendar rightNow = Calendar.getInstance(); String month = String.valueOf(rightNow.get(Calendar.MONTH));
在执行上面的代码片段之后,月份会得到10而不是11的值。怎么回事?
月份索引从0不是1,所以十一月份是十一月份,十一月份是十二月份。
他们从0开始 – 检查文档
许多答案显而易见:月份以0开头。
这里有一个提示:你应该使用SimpleDateFormat获取月份的string表示forms:
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是1月份,11月份是11月份。
你可能想知道为什么这样。 起源在于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 */
这个API几乎完全复制到Java 1.0中的Java Date类中,并从那里完整地复制到Java 1.1中的Calendar类中。 当Sun介绍Calendar时,Sun解决了最明显的问题 – 2001年公历中的年份由Date类中的值101表示。 但我不确定为什么他们没有改变date和月份的值,至less在索引中都是一致的,无论是零还是一。 Java(和C)至今仍然存在这种不一致和相关的混淆。
月份从零开始,就像列表的索引一样。
所以Jan = 0,Feb = 1等
TL;博士
LocalDate.now().getMonthValue() // Returns 1-12 for Jan-Dec.
细节
其他答案是正确的,但过时了。
麻烦的旧dateclass有许多糟糕的deviseselect和缺陷。 一个是从0到11的月份数字,而不是明显的1-12。
java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了旧的麻烦date时间类,如java.util.Date
, .Calendar
和java.text.SimpleDateFormat
。
现在在维护模式下 , Joda-Time项目也build议迁移到java.time。
要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。
大部分的java.timefunction在ThreeTen- Backport中被移植到Java 6&7中,并在ThreeTenABP中进一步适用于Android。
ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。
1-12个月
在java.time中,月份数量确实是1 – 12月份的1-12。
LocalDate
类代表没有时间和没有时区的只有date的值。
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ); int month = today.getMonthValue(); // Returns 1-12 as values.
如果您想要一个时区的date时间,以相同的方式使用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”types?
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime(); int month = zdt.getMonthValue(); // Returns 1-12 as values.
Month
枚举
顺便说一句,java.time类包括方便的Month
枚举 。 在你的代码中使用这个类的实例,而不仅仅是整数,使你的代码更加自我logging,提供types安全性 ,并确保有效的值。
Month month = today.getMonth(); // Returns an instant of `Month` rather than integer.
Month
枚举提供了有用的方法,例如使用本地化的月份名称生成String。
cal.get(Calendar.MONTH) + 1;
以上声明给出了确切的月份数字。 由于get(Calendar.Month)
返回从0开始的月份,因此将结果加1会给出正确的输出。 并记住设置月份时减1。
cal.set(Calendar.MONTH, (8 - 1));
或者使用提供的常量variables。
cal.set(Calendar.MONTH, Calendar.AUGUST);
这将是更好的使用
Calendar.JANUARY
这是零…