为什么 Java 日历中的 1 月是 0?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/344380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is January month 0 in Java Calendar?
提问by Stéphane Bonniez
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...
我看到很多人对此感到困惑......
采纳答案by Jon Skeet
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.
这只是 Java 日期/时间 API 的可怕混乱的一部分。列出它的问题需要很长时间(而且我确定我不知道一半的问题)。不可否认,处理日期和时间是很棘手的,但无论如何都是如此。
Do yourself a favour and use Joda Timeinstead, or possibly JSR-310.
EDIT: 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 whybad decisions were taken, as to look at the whole gamut of nastiness in java.util.Calendar
and find something better.
编辑:至于原因 - 正如其他答案中所述,这很可能是由于旧的 C API,或者只是从 0 开始一切的一般感觉......当然,除了天从 1 开始。我怀疑原始实施团队之外的任何人是否真的能说出原因——但同样,我再次敦促读者不要太担心为什么会做出错误的决定,而是要查看整个令人讨厌的范围java.util.Calendar
并找到更好的东西。
One point which isin favour of using 0-based indexes is that it makes things like "arrays of names" easier:
一个点,这是赞成使用基于0的索引的是,它使事情变得像“名字的阵列”更容易:
// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];
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.
当然,一旦您获得 13 个月的日历,这就会失败……但至少指定的大小是您期望的月数。
This isn't a goodreason, but it's areason...
这不是一个很好的理由,但这是一个理由……
EDIT: As a comment sort of requests some ideas about what I think is wrong with Date/Calendar:
编辑:作为一种评论,请求一些关于我认为日期/日历错误的想法:
- 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 muchsimpler 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)
- 令人惊讶的基数(1900 作为 Date 中的年份基数,对于已弃用的构造函数,无可否认;0 作为两者中的月份基数)
- 可变性-使用不变类型使得很多简单的什么是真正有效的工作值
- 类型集不足:拥有
Date
和Calendar
作为不同的东西很好,但是缺少“本地”与“分区”值的分离,日期/时间与日期与时间也是如此 - 一个 API 会导致带有魔术常量的丑陋代码,而不是明确命名的方法
- 一个很难推理的 API - 所有关于何时重新计算事物的业务等
- 使用无参数构造函数默认为“now”,导致代码难以测试
- 在
Date.toString()
它总是使用系统本地时区(即现在来迷惑许多堆栈溢出用户之前)执行
回答by TheSmurf
I'd say laziness. Arrays start at 0 (everyone knows that); 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.
我会说懒惰。数组从 0 开始(大家都知道);一年中的月份是一个数组,这让我相信 Sun 的一些工程师只是懒得把这个小细节放到 Java 代码中。
回答by Dinah
Because programmers are obsessed with 0-based indexes. 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. But by and large, I'll still stick with my first sentence.
因为程序员痴迷于从 0 开始的索引。好吧,它比那更复杂一点:当您使用较低级别的逻辑来使用基于 0 的索引时,这更有意义。但总的来说,我还是会坚持我的第一句话。
回答by Powerlord
In addition to DannySmurf's answer of laziness, I'll add that it's to encourage you to use the constants, such as Calendar.JANUARY
.
除了 DannySmurf 对懒惰的回答之外,我还要补充一点,它是为了鼓励您使用常量,例如Calendar.JANUARY
.
回答by stesch
C based languages copy C to some degree. The tm
structure (defined in time.h
) has an integer field tm_mon
with the (commented) range of 0-11.
基于 C 的语言在某种程度上复制了 C。该tm
结构(在 中定义time.h
)具有一个整数字段tm_mon
,其(注释)范围为 0-11。
C based languages start arrays at index 0. So this was convenient for outputting a string in an array of month names, with tm_mon
as the index.
基于 C 的语言在索引 0 处开始数组。所以这对于在月份名称数组中输出字符串很方便,tm_mon
作为索引。
回答by Paul Tomblin
Probably because C's "struct tm" does the same.
可能是因为 C 的“struct tm”做了同样的事情。
回答by Paul Brinkley
Personally, I took the strangeness of the Java calendar API as an indication that I needed to divorce myself from the Gregorian-centric mindset and try to program more agnostically in that respect. Specifically, I learned once again to avoid hardcoded constants for things like months.
就我个人而言,我认为 Java 日历 API 的奇怪之处表明我需要摆脱以格里高利为中心的思维方式,并尝试在这方面更加不可知地编程。具体来说,我再次学会了避免像几个月这样的硬编码常量。
Which of the following is more likely to be correct?
以下哪个更可能是正确的?
if (date.getMonth() == 3) out.print("March");
if (date.getMonth() == Calendar.MARCH) out.print("March");
This illustrates one thing that irks me a little about Joda Time - it may encourage programmers to think in terms of hardcoded constants. (Only a little, though. It's not as if Joda is forcingprogrammers to program badly.)
这说明了一件让我对 Joda Time 有点恼火的事情——它可能会鼓励程序员从硬编码常量的角度进行思考。(虽然只是一点点。Joda 并不是在强迫程序员进行糟糕的编程。)
回答by Alex Miller
回答by P?l GD
It isn't exactly defined as zero per se, it's defined as Calendar.January. It is the problem of using ints as constants instead of enums. Calendar.January == 0.
它本身并没有完全定义为零,而是定义为 Calendar.January。这是使用整数作为常量而不是枚举的问题。Calendar.January == 0。
回答by piksel bitworks
There has been alot of answers to this, but I will give my view on the subject anyway.
The reason behind this odd behavior, as stated previously, comes from the POSIX C time.h
where the months where stored in an int with the range 0-11.
To explain why, look at it like this; years and days are considered numbers in spoken language, but months have their own names. So because January is the first month it will be stored as offset 0, the first array element. monthname[JANUARY]
would be "January"
. The first month in the year is the first month array element.
对此已经有很多答案,但无论如何我都会就这个问题发表我的看法。如前所述,这种奇怪行为背后的原因来自 POSIX C time.h
,其中月份存储在范围为 0-11 的 int 中。要解释原因,请这样看;年和日在口语中被认为是数字,但月有自己的名字。因此,因为一月是第一个月,所以它将存储为偏移量 0,即第一个数组元素。monthname[JANUARY]
会"January"
。一年中的第一个月是第一个月数组元素。
The day numbers on the other hand, since they do not have names, storing them in an int as 0-30 would be confusing, add a lot of day+1
instructions for outputting and, of course, be prone to alot of bugs.
另一方面,天数,由于它们没有名称,将它们存储为 0-30 的 int 会令人困惑,添加大量day+1
输出指令,当然,容易出现很多错误。
That being said, the inconsistency is confusing, especially in javascript (which also has inherited this "feature"), a scripting language where this should be abstracted far away from the langague.
话虽如此,这种不一致令人困惑,尤其是在 javascript(它也继承了这个“特性”)中,这是一种脚本语言,它应该远离语言进行抽象。
TL;DR: Because months have names and days of the month do not.
TL;DR:因为月份有名称而月份中的日期没有。