JavaScriptの日付コンストラクターで月引数の範囲が0から11になっているのはなぜですか?


128

Date以下の呼び出しを使用してJavaScriptで新しいオブジェクトを初期化すると、月の引数がゼロから始まることがわかりました。

new Date(2010, 3, 1);  // that's the 1st April 2010!

月の引数が0から始まるのはなぜですか?一方、月の引数(最後の日)は1から31までの数字です。これには正当な理由がありますか?


96
それはあなたをつま先に保つだけです。
SeanJA

4
インデックスも0であるものはthe Day of the week (integer)0-6です
SeanJA 2010年

人間用ではなく、機械用にコーディングされたからです。しかし、多くのコードが(まだ)人間によって記述されているため、依然としてバグの大きな原因です:)
Christophe Roussy

4
@Christophe同じ議論が日にも年にも当てはまるはずです。
Agnel Kurian 2016

2
@ChristopheRoussyええ、それがマシン用にコーディングされたのなら、なぜ1から日数を索引付けするのですか?
user151496 2018年

回答:


55

これは、プログラミングの世界では古い(おそらく不幸な、おそらく死にかけている)伝統です。古い標準(POSIX)のlocaltime C関数http://linux.die.net/man/3/localtimeを参照してください


14
JS DateオブジェクトがJava 1.0から移植されたのはそのためです。そのすべての欠陥を継承... stackoverflow.com/questions/344380/...
C69

1
そうです、伝統は通常完全に一貫性がなく、しばしば不合理であり、私はそのような「悪い」伝統が本当に死んでいることを本当に望んでいます...
henon

1
2019年で、この動作に関連する問題を修正しています。javascriptのようなフレームワークや言語がこれを非推奨にしない限り、これは引き続き発生します-2025年以降は遠慮なくコメントしてください;-)
Mauricio Gracia Gutierrez

それは常に私が日付に関する問題のデバッグに時間を費やすようにする伝統です...この伝統が何時間の無駄な労働時間を生み出したのか疑問に思いました。
Vedmant

102

この質問に対する本当の答えはjava.util.Date、これもからコピーされたものであり、これにもこの癖があったことです。プルーフは、最初にJavaScript(Dateオブジェクトを含む)を実装したBrendan EichのTwitterで見つけることができます。

https://twitter.com/BrendanEich/status/481939099138654209

最初のツイート

https://twitter.com/BrendanEich/status/771006397886533632

2番目のツイート

これは1995年に起こり、JDK 1.0はベータ版でした。それは1996年に発売されました。1997年に、JDK 1.1がリリースされ、ほとんどの機能が非推奨になりjava.util.Date、に移行しましたがjava.util.Calendar、それでもゼロベースの月がありました。これにうんざりしている開発者は、Joda-Timeライブラリを作成し、最終的java.timeにJava 8(2014)に組み込まれたパッケージにつながりました。

つまり、Javaが正しく設計された日付/時刻APIを組み込むのに18年かかりましたが、JavaScriptは依然として暗い時代に立ち往生しています。確かに、Moment.jsdate-fnsjs-jodaなどの優れたライブラリーがあります。しかし、今のDateところ、言語に組み込まれていること以外には何もありません。うまくいけば、これは近い将来に変わるでしょう。


24
ああ...古き良きデモドリブン開発方法論。
アルバロゴンザレス

@ÁlvaroGonzález私は最初にそれを導入したオリジナルのJDK 1.0開発者を責めます。
バレル

30

日を除くすべてが0ベースです。範囲を含む完全なリストについては、こちらをご覧ください :)

ここで実際に奇数ボールであるのは1ベースの日です...奇妙なことに十分です。なぜこれが行われたのですか?わからないけど、たぶん彼らが漆喰になったのと同じ会議で、セミコロンはオプションだと決めた。


1
「1を基にした」日というのは、おそらく、正しい考えの誰もが日ごとに文字列名の配列を作成して(たとえば、{ "first", "second", "third", ..., "twenty-seventh", ... })、それをでインデックス付けしようとしないためtm_mdayです。繰り返しになりますが、たぶん彼らは、1つのエラーを定期的に発生せる絶対的な効用を見ただけかもしれません。
D.Shawley、2010年

彼らはなぜ年が0ベースではないのですか?
Vedmant


4

そのJavaでも同様です.. おそらく intを文字列(0-jan ,, 1-feb)に変換するために、彼らはこのようにコード化しました。数字が0から始まる場合は、月の文字列にマップする方がはるかに簡単です。


3

元の質問に対する答えではないことはわかっていますが、この問題に対する私の好ましい解決策をお見せしたかっただけです。

小さな関数zerofillは、必要に応じてゼロを埋めるトリックを行い、月が+1追加されます。

function zerofill(i) {
    return (i < 10 ? '0' : '') + i;
}

function getDateString() {
    const date = new Date();
    const year = date.getFullYear();
    const month = zerofill(date.getMonth()+1);
    const day = zerofill(date.getDate());
    return year + '-' + month + '-' + day;
}

しかし、はい、日付にはかなり直感的なAPIがあり、ブレンダンアイヒのTwitterを読んでいたとき、私は笑っていました。


2

関連付けられている名前がないため、月は列挙型(最初のインデックスは0)であり、日ではないと見なした可能性があります。

むしろ、彼らはその日の数がその日の実際の表現であると考えました(月が12/31のような日付の数字として表されるのと同じように) 0ベース。

したがって、実際には、月については、適切な列挙表現は数字ではなく月の名前を使用することであると考え、日が名前表現を持っている場合も同じようにしました。1月5日、1月6日、1月5日、1月6日などではなく、1月5日、1日6日と言ったとしたら、おそらく、それらも数日間0ベースの列挙を行っていたでしょう...

おそらく無意識のうちに、数か月の列挙を{January、February、...}として、日を{One、Two、Three、...}として考えました。 1 for Oneなどのように、0から開始することは不可能です...


あなたは心理学者にデュアルクラスすべきです。それは彼らが犯した間違いですが、少なくとも私たちは今、彼らがそれを犯した理由を理解しています。
Zesty

0

これは欠陥かもしれませんが、月または曜日を文字列として表現したい場合にも非常に便利です。['jan、' feb '... etc] [new Date()のような配列を作成できます。 [''、 'jan'、feb ... etc] [new Date()。getMonth()]の代わりに.getMonth()]または['jan'、 'feb' ... etc] [new Date( ).getMonth()-1]

月の日には通常名前が付けられないため、それらの名前で配列を作成することはありません。この場合、1-31の方が扱いやすいので、毎回1を引く必要があります...


あんまり。簡単に1を引くだけです。日付を使用して計算を行う場合、今月は特定の操作を頻繁に行わなければならないため、解決策よりも多くの問題が発生します。
レイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.