在java.util。日历中,一月被定义为第0个月,而不是第1个月。这有什么具体原因吗?

我看到很多人对此感到困惑……


当前回答

博士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等等。

其他回答

就我个人而言,我认为Java日历API的奇特之处表明,我需要摆脱以格里高利为中心的思维方式,并尝试在这方面更加不可知论地编程。具体来说,我再次学会了避免对月份之类的常量进行硬编码。

下面哪个选项更可能是正确的?

if (date.getMonth() == 3) out.print("March");

if (date.getMonth() == Calendar.MARCH) out.print("March");

这说明了Joda Time让我有点恼火的一件事——它可能会鼓励程序员从硬编码常数的角度思考问题。(不过只有一点点。Joda并不是在强迫程序员糟糕地编程。)

在Java 8中,有一个新的日期/时间API JSR 310,它更加合理。规范负责人与JodaTime的主要作者相同,他们共享许多相似的概念和模式。

可能是因为C的“struct tm”也有同样的功能。

除了DannySmurf关于懒惰的回答之外,我还要补充一句,这是为了鼓励您使用常量,例如Calendar.JANUARY。

因为语言写作比看起来要难得多,特别是处理时间比大多数人想象的要难得多。关于这个问题的一小部分(在现实中,不是Java),请参阅YouTube视频“时间和时区的问题-计算机爱好者”,网址是https://www.youtube.com/watch?v=-5wpm-gesOY。如果你在困惑中笑掉了头,不要感到惊讶。