为什么 Java 日历中的 1 月是 0 月?
在 java.util.Calendar
中,一月被定义为第 0 个月,而不是第 1 个月.有什么具体原因吗?
In java.util.Calendar
, January is defined as month 0, not month 1. Is there any specific reason to that ?
我看到很多人对此感到困惑......
I have seen many people getting confused about that...
推荐答案
这只是 Java 日期/时间 API 的可怕混乱的一部分.列出它的问题需要很长时间(而且我确信我不知道一半的问题).诚然,处理日期和时间是很棘手的,但无论如何都是 aaargh.
It's just part of the horrendous mess which is the Java date/time API. Listing what's wrong with it would take a very long time (and I'm sure I don't know half of the problems). Admittedly working with dates and times is tricky, but aaargh anyway.
帮自己一个忙,使用 Joda Time 代替,或者可能使用 JSR-310.
Do yourself a favour and use Joda Time instead, or possibly JSR-310.
至于原因 - 正如其他答案中所述,这很可能是由于旧的 C API,或者只是从 0 开始的一般感觉......当然,除了那些日子从 1 开始.我怀疑原始实施团队之外的任何人是否真的可以说明原因 - 但我再次敦促读者不要太担心为什么做出了错误的决定,而是要看看整个肮脏的范围在 java.util.Calendar
中找到更好的东西.
As for the reasons why - as noted in other answers, it could well be due to old C APIs, or just a general feeling of starting everything from 0... except that days start with 1, of course. I doubt whether anyone outside the original implementation team could really state reasons - but again, I'd urge readers not to worry so much about why bad decisions were taken, as to look at the whole gamut of nastiness in java.util.Calendar
and find something better.
赞成使用基于 0 的索引的一点是,它使名称数组"之类的事情变得更容易:
One point which is in favour of using 0-based indexes is that it makes things like "arrays of names" easier:
// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];
当然,一旦你得到一个有 13 个月的日历,这就会失败......但至少指定的大小是你期望的月数.
Of course, this fails as soon as you get a calendar with 13 months... but at least the size specified is the number of months you expect.
这不是一个好的理由,但这是一个的理由......
This isn't a good reason, but it's a reason...
作为评论,请求一些关于我认为日期/日历有问题的想法:
As a comment sort of requests some ideas about what I think is wrong with Date/Calendar:
- 令人惊讶的基数(1900 作为 Date 的年份基数,对于已弃用的构造函数来说是公认的;0 作为两个月份的基数)
- 可变性 - 使用不可变类型可以更加更轻松地处理真正有效的值
- 类型集不足:将
Date
和Calendar
作为不同的东西,这很好,但是缺少本地"与分区"值的分离,日期/时间与日期与时间也是如此 - 一个 API 会导致带有魔法常量的丑陋代码,而不是明确命名的方法
- 一个很难推理的 API - 所有关于何时重新计算事物等的业务
- 使用无参数构造函数默认为现在",导致代码难以测试
Date.toString()
实现总是使用系统本地时区(这让很多 Stack Overflow 用户感到困惑)
- 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
andCalendar
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)
相关文章