Mengapa argumen bulan berkisar dari 0 hingga 11 di JavaScript's Date constructor?

128

Saat menginisialisasi Dateobjek baru di JavaScript menggunakan panggilan di bawah ini, saya menemukan bahwa argumen bulan dihitung mulai dari nol.

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

Mengapa argumen bulan dimulai dari 0? Sebaliknya, argumen hari dalam sebulan (yang terakhir) adalah angka dari 1 hingga 31. Apakah ada alasan bagus untuk ini?

Agnel Kurian
sumber
96
Itu hanya untuk membuat Anda tetap waspada.
SeanJA
4
Salah satu yang juga tidak diindeks adalah the Day of the week (integer)0-6
SeanJA
Karena itu dikodekan untuk mesin dan bukan untuk manusia. Tetapi masih merupakan sumber bug yang sangat besar karena banyak kode (masih) ditulis oleh manusia :)
Christophe Roussy
4
@Christophe, argumen yang sama harus diterapkan pada hari dan tahun juga.
Agnel Kurian
2
@ChristopheRoussy ya, jika itu dikodekan untuk mesin, mengapa indeks hari dari 1 lalu?
pengguna151496

Jawaban:

55

Ini adalah tua (mungkin disayangkan, mungkin sekarat) tradisi dalam dunia pemrograman, lihat standar lama (POSIX) localtime C fungsi http://linux.die.net/man/3/localtime

leonbloy.dll
sumber
14
DateObjek JS diporting dari Java 1.0, itu sebabnya. Mewarisi semua kekurangannya ... stackoverflow.com/questions/344380/…
c69
1
Anda benar, tradisi biasanya sama sekali tidak konsisten dan sering kali tidak rasional dan saya sangat berharap tradisi "buruk" seperti itu benar-benar sekarat ...
henon
1
adalah 2019 dan saya sedang memperbaiki masalah terkait perilaku ini, jadi selama kerangka kerja sebagai sudut dan bahasa seperti javascript tidak mengesampingkan hal ini, hal ini masih akan terjadi - silakan koment di tahun 2025 dan seterusnya ;-)
Mauricio Gracia Gutierrez
Itu adalah tradisi yang selalu membuat saya menghabiskan waktu untuk men-debug masalah dengan tanggal ... Bertanya-tanya berapa jutaan jam kerja yang terbuang karena tradisi ini.
Vedmant
102

Jawaban sebenarnya untuk pertanyaan ini, adalah bahwa itu disalin dari java.util.Date, yang juga memiliki keanehan ini. Bukti dapat ditemukan di Twitter dari Brendan Eich - orang yang awalnya menerapkan JavaScript (termasuk Dateobjeknya):

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

tweet pertama

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

tweet kedua

Ini terjadi pada tahun 1995, dan JDK 1.0 masih dalam versi beta. Ini diluncurkan pada tahun 1996. Pada tahun 1997, JDK 1.1 keluar yang menghentikan sebagian besar fungsi java.util.Date, memindahkannya ke java.util.Calendar, tetapi bahkan itu masih memiliki bulan berbasis nol. Pengembang yang bosan dengan hal ini membuat pustaka Joda-Time , yang akhirnya menghasilkan java.timepaket yang dimasukkan ke dalam Java 8 (2014).

Singkatnya, butuh 18 tahun bagi Java untuk mendapatkan API tanggal / waktu yang dirancang dengan benar di dalamnya, tetapi JavaScript masih tertahan di masa kegelapan. Kami memang memiliki pustaka yang sangat baik seperti Moment.js , date-fns , dan js-joda . Tapi sampai sekarang, tidak ada yang lebih dari Datebahasa bawaan. Semoga ini akan berubah dalam waktu dekat.

Matt Johnson-Pint
sumber
24
Ah ... Metodologi Pengembangan Berbasis Demo lama yang bagus.
Álvaro González
@ ÁlvaroGonzález Saya akan menyalahkan pengembang JDK 1.0 asli yang pertama kali memperkenalkannya.
barell
30

Semuanya kecuali hari dalam sebulan berbasis 0, lihat di sini untuk daftar lengkap termasuk rentang :)

Sebenarnya 1 hari berbasis itulah yang aneh di sini ... cukup aneh. Mengapa ini dilakukan? Saya tidak tahu ... tapi mungkin terjadi pada pertemuan yang sama ketika mereka terpampang dan memutuskan titik koma adalah opsional.

Nick Craver
sumber
1
Hal "berbasis satu" mungkin karena tidak ada orang waras yang akan pernah membuat larik nama string selama berhari-hari (misalnya { "first", "second", "third", ..., "twenty-seventh", ... }) dan mencoba mengindeksnya tm_mday. Kemudian lagi, mungkin mereka hanya melihat utilitas mutlak dalam membuat off dengan satu kesalahan kejadian biasa.
D. Shawley
Mereka mengapa tahun tidak berbasis 0?
Vedmant
5

Selalu ada 12 bulan dalam setahun, jadi implementasi C awal mungkin menggunakan array lebar tetap statis dengan indeks 0..11.

Jonathan Julian
sumber
2
Implementasi Tanggal / Kalender Java mempertahankan dukungan untuk satu bulan tambahan untuk beberapa kalender. en.wikipedia.org/wiki/Undecimber
Pointy
4

Ini seperti ini di java juga .. Mungkin untuk mengkonversi int ke string (0 - jan ,, 1-feb), mereka mengkodekan dengan cara ini .. karena mereka mungkin memiliki array string (diindeks dari 0) dari nama bulan dan bulan ini angka jika dimulai dari 0, akan jauh lebih mudah untuk memetakan ke string bulan ..

raj
sumber
3

Saya tahu ini sebenarnya bukan jawaban untuk pertanyaan asli, tetapi saya hanya ingin menunjukkan solusi yang saya sukai untuk masalah ini, yang sepertinya tidak pernah saya ingat karena muncul dari waktu ke waktu.

Fungsi kecil dari nol melakukan trik mengisi nol jika diperlukan, dan bulan baru saja +1ditambahkan:

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;
}

Tapi ya, Date memiliki API yang sangat tidak intuitif, saya tertawa ketika membaca Twitter Brendan Eich.

Christof Kälin
sumber
2

Mereka mungkin menganggap bulan sebagai pencacahan (indeks pertama adalah 0) dan hari bukan karena mereka tidak memiliki nama yang terkait dengannya.

Atau lebih tepatnya, mereka mengira angka hari adalah representasi sebenarnya dari hari itu (dengan cara yang sama bulan direpresentasikan sebagai angka dalam tanggal seperti 31/12), seolah-olah Anda bisa membuat pencacahan dengan angka sebagai variabel, tetapi sebenarnya Berbasis 0.

Jadi sebenarnya, selama berbulan-bulan, mungkin mereka mengira representasi pencacahan yang tepat adalah dengan menggunakan nama bulan, bukan angka, dan mereka akan melakukan hal yang sama jika hari memiliki representasi nama. Bayangkan jika kita mengatakan Lima Januari, Enam Januari, bukannya 5 Januari, 6 Januari, dll., Maka mungkin mereka juga akan membuat pencacahan berbasis 0 selama berhari-hari ...

Mungkin secara tidak sadar mereka berpikir tentang pencacahan selama berbulan-bulan sebagai {Januari, Februari, ...} dan untuk hari-hari sebagai {Satu, Dua, Tiga, ...}, kecuali untuk hari-hari Anda mengakses hari itu sebagai angka dan bukan namanya, seperti 1 untuk Satu, dll., jadi tidak mungkin untuk memulai dari 0 ...

Pat-Laugh
sumber
Anda harus kelas ganda ke Psikolog. Itu masih kesalahan yang mereka buat, tapi setidaknya kita sekarang mengerti mengapa mereka membuatnya.
Zesty
0

Ini mungkin cacat, tapi ini juga sangat berguna ketika Anda ingin merepresentasikan bulan atau hari dalam seminggu sebagai string, Anda bisa membuat array seperti ['jan,' feb '... dll] [new Date () .getMonth ()] sebagai ganti ['', 'jan', feb ... dll] [new Date (). getMonth ()] atau ['jan', 'feb' ... etc] [new Date ( ) .getMonth () - 1]

hari dalam sebulan biasanya tidak dinamai sehingga Anda tidak akan membuat array dengan nama untuk itu. Dalam hal ini 1-31 lebih mudah ditangani, jadi Anda harus mengurangi 1 setiap kali ...

Rogier
sumber
tidak juga. Anda bisa dengan mudah mengurangi satu. Ini menciptakan lebih banyak masalah daripada menyelesaikannya karena sekarang ketika Anda melakukan matematika dengan tanggal, Anda harus melakukan manipulasi khusus pada bulan itu lebih sering.
Rey