为什么1月在Java日历中为0?

本文翻译自:Why is January month 0 in Java Calendar?

In java.util.Calendar , January is defined as month 0, not month 1. Is there any specific reason to that ? java.util.Calendar ,一月被定义为第0个月,而不是第1个月。是否有任何特定原因?

I have seen many people getting confused about that... 我已经看到很多人对此感到困惑...


#1楼

参考:https://stackoom.com/question/1RaW/为什么-月在Java日历中为


#2楼

For me, nobody explains it better than mindpro.com : 对我来说,没有人能比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. java.util.GregorianCalendar有少得多的错误和陷阱比old java.util.Date类,但它仍然是不轻松。

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. 在秋天,当您将时钟设置为凌晨2点一小时时,会有两个不同的时间点,都称为本地时间1:30 AM。 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. 不幸的是,没有办法告诉GregorianCalendar您打算做什么。 You must resort to telling it the local time with the dummy UTC TimeZone to avoid the ambiguity. 您必须使用虚拟UTC TimeZone告诉它当地时间,以避免产生歧义。 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. 这些错误仍然不在Calendar类之外。 Even in JDK (Java Development Kit) 1.3 there is a 2001 bug. 即使在JDK(Java开发工具包)1.3中,也存在2001年的错误。 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. 对于MST,该错误于2001年1月1日上午7点消失。

GregorianCalendar is controlled by a giant of pile of untyped int magic constants. GregorianCalendar由大量未键入的int魔术常数控制。 This technique totally destroys any hope of compile-time error checking. 这种技术完全破坏了编译时错误检查的希望。 For example to get the month you use GregorianCalendar. get(Calendar.MONTH)); 例如,使用GregorianCalendar. get(Calendar.MONTH));获取月份GregorianCalendar. get(Calendar.MONTH)); GregorianCalendar. get(Calendar.MONTH));

GregorianCalendar has the raw GregorianCalendar.get(Calendar.ZONE_OFFSET) and the daylight savings GregorianCalendar. get( Calendar. DST_OFFSET) GregorianCalendar具有原始的GregorianCalendar.get(Calendar.ZONE_OFFSET)和夏时制GregorianCalendar. get( Calendar. DST_OFFSET) GregorianCalendar. get( Calendar. DST_OFFSET) , but no way to get the actual time zone offset being used. GregorianCalendar. get( Calendar. DST_OFFSET) ,但是无法获取正在使用的实际时区偏移量。 You must get these two separately and add them together. 您必须分别获得这两个并将它们添加在一起。

GregorianCalendar.set( year, month, day, hour, minute) does not set the seconds to 0. GregorianCalendar.set( year, month, day, hour, minute)不会将秒设置为0。

DateFormat and GregorianCalendar do not mesh properly. DateFormatGregorianCalendar无法正确啮合。 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. 如果用户未正确配置其时区,它将默认为PST或GMT。

In GregorianCalendar, Months are numbered starting at January=0, rather than 1 as everyone else on the planet does. 在GregorianCalendar中,月份从1月= 0开始编号,而不是地球上其他所有人的月份编号。 Yet days start at 1 as do days of the week with Sunday=1, Monday=2,… Saturday=7. 然而,天数从1开始,而星期几则从1开始,星期一= 2,…星期六= 7。 Yet DateFormat. 但是DateFormat。 parse behaves in the traditional way with January=1. parse的行为与传统方式相同,即January = 1。


#3楼

Because doing math with months is much easier. 因为用数月做数学要容易得多。

1 month after December is January, but to figure this out normally you would have to take the month number and do math 1月是12月之后的1个月,但要正常计算,您必须计算月份数并进行数学运算

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

I know! 我知道! I can fix this quickly by using a modulus of 12. 我可以通过使用12的模数快速解决此问题。

(12 + 1) % 12 = 1

This works just fine for 11 months until November... 直到11月为止,这可以正常工作11个月。

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

You can make all of this work again by subtracting 1 before you add the month, then do your modulus and finally add 1 back again... aka work around an underlying problem. 您可以在添加月份之前先减去1,然后再进行模数运算,最后再加1,即可再次完成所有这些工作...也可以解决一个基本问题。

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

Now let's think about the problem with months 0 - 11. 现在,让我们考虑一下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

All of the months work the same and a work around isn't necessary. 所有月份的工作都是一样的,因此无需解决。


#4楼

Because everything starts with 0. This is a basic fact of programming in Java. 因为一切都以0开头。这是Java编程的基本事实。 If one thing were to deviate from that, then that would lead to a whole slue of confusion. 如果有什么事情与之背道而驰,那将导致一团混乱。 Let's not argue the formation of them and code with them. 我们不要争论它们的形成并与它们一起编码。


#5楼

I'd say laziness. 我会说懒惰。 Arrays start at 0 (everyone knows that); 数组从0开始(每个人都知道); the months of the year are an array, which leads me to believe that some engineer at Sun just didn't bother to put this one little nicety into the Java code. 一年中的几个月是一个数组,这使我相信Sun的某个工程师只是不花心思将这些细节添加到Java代码中。


#6楼

Because programmers are obsessed with 0-based indexes. 因为程序员沉迷于基于0的索引。 OK, it's a bit more complicated than that: it makes more sense when you're working with lower-level logic to use 0-based indexing. 好的,这要复杂得多:在使用低级逻辑使用基于0的索引时,它更有意义。 But by and large, I'll still stick with my first sentence. 但总的来说,我还是会坚持第一句话。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值