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

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


当前回答

因为用月份计算要简单得多。

12月之后的一个月就是1月,但是要算出这个,通常你需要用月份的数字来计算

12 + 1 = 13 // What month is 13?

我知道!我可以通过使用模量12来快速解决这个问题。

(12 + 1) % 12 = 1

在11月之前的11个月里,这一切都很好……

(11 + 1) % 12 = 0 // What month is 0?

你可以在加上月份之前再减去1,然后做模数,最后再加1……也就是解决潜在的问题。

((11 - 1 + 1) % 12) + 1 = 12 // Lots of magical numbers!

现在让我们考虑0 - 11月的问题。

(0 + 1) % 12 = 1 // February
(1 + 1) % 12 = 2 // March
(2 + 1) % 12 = 3 // April
(3 + 1) % 12 = 4 // May
(4 + 1) % 12 = 5 // June
(5 + 1) % 12 = 6 // July
(6 + 1) % 12 = 7 // August
(7 + 1) % 12 = 8 // September
(8 + 1) % 12 = 9 // October
(9 + 1) % 12 = 10 // November
(10 + 1) % 12 = 11 // December
(11 + 1) % 12 = 0 // January

所有月份的工作都是一样的,没有必要进行变通。

其他回答

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

java.time.Month

Java为您提供了另一种使用基于1的索引的方法。使用java.time.Month enum。为12个月中的每个月预定义一个对象。他们在1月到12月之间分别有1-12号;调用getValue获取该号码。

利用Month。七月(给你7分) 而不是日历。七月(给你6分)。

(import java.time.*;)

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

对我来说,没有人比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.

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

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