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

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


当前回答

基于C的语言在某种程度上复制了C。tm结构(在time.h中定义)有一个整数字段tm_mon,(注释的)范围为0-11。

基于C的语言从索引0开始数组。因此,这对于以tm_mon作为索引输出月份名称数组中的字符串非常方便。

其他回答

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

这只是Java日期/时间API这一可怕的混乱的一部分。列出它的问题将花费很长时间(而且我确信我不知道一半的问题)。不可否认,处理日期和时间是很棘手的,但不管怎样。

帮自己一个忙,使用Joda Time代替,或者可能使用JSR-310。

编辑:至于原因——正如在其他回答中提到的,这很可能是由于旧的C api,或者只是一种从0开始的感觉……当然,除了一天从1开始。我怀疑原始实现团队之外的任何人都不能真正说出原因——但是,我再次敦促读者不要过于担心为什么做出了糟糕的决定,而是要看看java.util.Calendar中所有糟糕的事情,并找到更好的东西。

支持使用基于0的索引的一点是,它使“名称数组”之类的事情更容易:

// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];

当然,一旦你有了13个月的日历,这种方法就行不通了……但至少指定的大小是您期望的月数。

这不是一个很好的理由,但它是一个理由……

编辑:作为一个评论,请求一些关于我认为日期/日历错误的想法:

Surprising bases (1900 as the year base in Date, admittedly for deprecated constructors; 0 as the month base in both) Mutability - using immutable types makes it much simpler to work with what are really effectively values An insufficient set of types: it's nice to have Date and Calendar as different things, but the separation of "local" vs "zoned" values is missing, as is date/time vs date vs time An API which leads to ugly code with magic constants, instead of clearly named methods An API which is very hard to reason about - all the business about when things are recomputed etc The use of parameterless constructors to default to "now", which leads to hard-to-test code The Date.toString() implementation which always uses the system local time zone (that's confused many Stack Overflow users before now)

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

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

因为所有东西都是从0开始的。这是Java编程的一个基本事实。如果有一件事偏离了这一点,那么就会导致一系列的混乱。让我们不要争论它们的构成和代码。