在java.util。日历中,一月被定义为第0个月,而不是第1个月。这有什么具体原因吗?
我看到很多人对此感到困惑……
在java.util。日历中,一月被定义为第0个月,而不是第1个月。这有什么具体原因吗?
我看到很多人对此感到困惑……
当前回答
对我来说,没有人比mindpro.com更能解释这一点:
Gotchas java.util.GregorianCalendar has far fewer bugs and gotchas than the old java.util.Date class but it is still no picnic. Had there been programmers when Daylight Saving Time was first proposed, they would have vetoed it as insane and intractable. With daylight saving, there is a fundamental ambiguity. In the fall when you set your clocks back one hour at 2 AM there are two different instants in time both called 1:30 AM local time. You can tell them apart only if you record whether you intended daylight saving or standard time with the reading. Unfortunately, there is no way to tell GregorianCalendar which you intended. You must resort to telling it the local time with the dummy UTC TimeZone to avoid the ambiguity. Programmers usually close their eyes to this problem and just hope nobody does anything during this hour. Millennium bug. The bugs are still not out of the Calendar classes. Even in JDK (Java Development Kit) 1.3 there is a 2001 bug. Consider the following code: GregorianCalendar gc = new GregorianCalendar(); gc.setLenient( false ); /* Bug only manifests if lenient set false */ gc.set( 2001, 1, 1, 1, 0, 0 ); int year = gc.get ( Calendar.YEAR ); /* throws exception */ The bug disappears at 7AM on 2001/01/01 for MST. GregorianCalendar is controlled by a giant of pile of untyped int magic constants. This technique totally destroys any hope of compile-time error checking. For example to get the month you use GregorianCalendar. get(Calendar.MONTH)); GregorianCalendar has the raw GregorianCalendar.get(Calendar.ZONE_OFFSET) and the daylight savings GregorianCalendar. get( Calendar. DST_OFFSET), but no way to get the actual time zone offset being used. You must get these two separately and add them together. GregorianCalendar.set( year, month, day, hour, minute) does not set the seconds to 0. DateFormat and GregorianCalendar do not mesh properly. You must specify the Calendar twice, once indirectly as a Date. If the user has not configured his time zone correctly it will default quietly to either PST or GMT. In GregorianCalendar, Months are numbered starting at January=0, rather than 1 as everyone else on the planet does. Yet days start at 1 as do days of the week with Sunday=1, Monday=2,… Saturday=7. Yet DateFormat. parse behaves in the traditional way with January=1.
其他回答
除了DannySmurf关于懒惰的回答之外,我还要补充一句,这是为了鼓励您使用常量,例如Calendar.JANUARY。
因为程序员痴迷于基于0的索引。好吧,实际情况要比这复杂一些:当您使用基于0的索引来处理底层逻辑时,它更有意义。但总的来说,我还是会坚持我的第一句话。
博士tl;
Month.FEBRUARY.getValue() // February → 2.
2
细节
乔恩·斯基特的答案是正确的。
现在我们有了这些麻烦的旧遗留日期-时间类的现代替代品:java。时间类。
java.time.Month
在这些类中有Month枚举。枚举携带一个或多个预定义对象,这些对象在装入类时自动实例化。在Month中,我们有十几个这样的对象,每个对象都有一个名称:JANUARY, FEBRUARY, MARCH,等等。每一个都是一个静态的最终公共类常量。您可以在代码中的任何地方使用和传递这些对象。示例:someMethod(月。8月)
幸运的是,它们有正确的编号,1-12,其中1是一月,12是十二月。
获取特定月份号(1-12)的Month对象。
Month month = Month.of( 2 ); // 2 → February.
向另一个方向,询问Month对象的月号。
int monthNumber = Month.FEBRUARY.getValue(); // February → 2.
这个类上还有很多方便的方法,比如知道每个月有多少天。该类甚至可以生成月份的本地化名称。
您可以获得以各种长度或缩写形式表示的月份的本地化名称。
String output =
Month.FEBRUARY.getDisplayName(
TextStyle.FULL ,
Locale.CANADA_FRENCH
);
2
此外,您应该围绕代码库传递此枚举的对象,而不仅仅是整数。这样做可以提供类型安全,确保值的有效范围,并使代码更具自文档性。如果不熟悉Java中令人惊讶的强大枚举功能,请参阅Oracle教程。
Year和YearMonth类也很有用。
关于java.time
java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。Date, . calendar, & java.text.SimpleDateFormat。
Joda-Time项目现在处于维护模式,建议迁移到java.time。
要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。
从哪里获取java。时间类?
Java SE 8和SE 9及更高版本 内置的。 带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 ThreeTenABP项目将ThreeTen-Backport(上文提到过)专门用于Android。 参见如何使用....
ThreeTen-Extra项目扩展了java。额外的课程时间。这个项目是未来可能添加到java.time的一个试验场。你可以在这里找到一些有用的类,比如Interval、YearWeek、YearQuarter等等。
There has been a lot of answers to this, but I will give my view on the subject anyway. The reason behind this odd behavior, as stated previously, comes from the POSIX C time.h where the months were stored in an int with the range 0-11. To explain why, look at it like this; years and days are considered numbers in spoken language, but months have their own names. So because January is the first month it will be stored as offset 0, the first array element. monthname[JANUARY] would be "January". The first month in the year is the first month array element.
另一方面,由于日期数字没有名称,将它们存储在0-30的int型中会令人困惑,添加大量的day+1指令用于输出,当然,也容易出现很多错误。
也就是说,这种不一致是令人困惑的,特别是在javascript(它也继承了这个“特性”)中,这种脚本语言应该从语言中抽象出来。
因为月份有名称,而月份中的日期没有。
因为所有东西都是从0开始的。这是Java编程的一个基本事实。如果有一件事偏离了这一点,那么就会导致一系列的混乱。让我们不要争论它们的构成和代码。