เหตุใดอาร์กิวเมนต์เดือนจึงอยู่ในช่วง 0 ถึง 11 ในตัวสร้างวันที่ของ JavaScript


128

เมื่อเริ่มต้นDateวัตถุใหม่ใน JavaScript โดยใช้การเรียกด้านล่างฉันพบว่าอาร์กิวเมนต์เดือนนับเริ่มต้นจากศูนย์

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

ทำไมอาร์กิวเมนต์เดือนเริ่มต้นจาก 0? ในทางกลับกันอาร์กิวเมนต์วันของเดือน (วันสุดท้าย) คือตัวเลขตั้งแต่ 1 ถึง 31 มีเหตุผลที่ดีสำหรับสิ่งนี้หรือไม่?


96
มันเป็นเพียงเพื่อให้คุณอยู่เสมอ
SeanJA

4
สิ่งที่จัดทำดัชนีเป็นศูนย์คือthe Day of the week (integer)0-6
SeanJA

เพราะมันถูกเข้ารหัสสำหรับเครื่องจักรไม่ใช่สำหรับมนุษย์ แต่ก็ยังคงเป็นแหล่งที่มาของข้อบกพร่องจำนวนมากเนื่องจากโค้ดจำนวนมาก (ยัง) เขียนโดยมนุษย์ :)
Christophe Roussy

4
@Christophe ข้อโต้แย้งเดียวกันควรใช้กับวันและปีด้วย
Agnel Kurian

2
@ChristopheRoussy ใช่ถ้ามันถูกเข้ารหัสสำหรับเครื่องทำไมดัชนีวันจาก 1 แล้ว?
user151496

คำตอบ:


55

มันเป็นประเพณีเก่าแก่ (อาจโชคร้ายอาจจะตาย) ในโลกการเขียนโปรแกรมดูมาตรฐานเก่า (POSIX) ฟังก์ชันlocaltime C http://linux.die.net/man/3/localtime


14
Dateออบเจ็กต์JS ถูกพอร์ตจาก Java 1.0 นั่นคือเหตุผล สืบทอดทุกข้อบกพร่อง ... stackoverflow.com/questions/344380/…
c69

1
คุณพูดถูกประเพณีมักจะไม่สอดคล้องกันโดยสิ้นเชิงและมักจะไร้เหตุผลและฉันหวังเป็นอย่างยิ่งว่าประเพณีที่ "ไม่ดี" เช่นนี้กำลังจะตายจริงๆ ...
henon

1
คือปี 2019 และฉันกำลังแก้ไขปัญหาที่เกี่ยวข้องกับพฤติกรรมนี้ตราบใดที่เฟรมเวิร์กเป็นเชิงมุมและภาษาเนื่องจากจาวาสคริปต์ไม่เลิกใช้สิ่งนี้จะยังคงเกิดขึ้น - อย่าลังเลที่จะมาในปี 2025 เป็นต้นไป ;-)
Mauricio Gracia Gutierrez

นั่นเป็นประเพณีที่ทำให้ฉันใช้เวลาในการแก้ไขปัญหาเกี่ยวกับวันที่อยู่เสมอ ... สงสัยว่าประเพณีนี้ทำให้เกิดการเสียเวลาทำงานไปกี่ล้าน
Vedmant

102

คำตอบที่แท้จริงสำหรับคำถามนี้คือมันถูกคัดลอกมาจากjava.util.Dateซึ่งก็มีมุมแหลมเช่นกัน หลักฐานสามารถพบได้บน Twitter จาก Brendan Eich ชายผู้ใช้ JavaScript (รวมถึงDateวัตถุ):

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

ทวีตแรก

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

ทวีตที่สอง

เหตุการณ์นี้เกิดขึ้นในปี 1995 และ JDK 1.0 อยู่ในรุ่นเบต้า เปิดตัวในปี 2539 ในปี 1997 JDK 1.1 ได้ออกมาซึ่งยกเลิกการใช้งานฟังก์ชันส่วนใหญ่java.util.Dateโดยย้ายไปที่java.util.Calendarแต่ถึงอย่างนั้นก็ยังมีเดือนที่อิงศูนย์ นักพัฒนาเบื่อหน่ายกับสิ่งนี้ได้สร้างไลบรารีJoda-Timeซึ่งนำไปสู่java.timeแพ็คเกจที่อบใน Java 8 (2014) ในที่สุด

ในระยะสั้น Java ใช้เวลา 18 ปีในการออกแบบวันที่ / เวลา API ในตัวที่ถูกต้อง แต่ JavaScript ยังคงติดอยู่ในยุคมืด เราไม่แน่นอนมีห้องสมุดที่ยอดเยี่ยมเช่นMoment.js , วันที่ FNSและJS-Joda แต่ ณ ตอนนี้ไม่มีอะไรมากไปกว่าDateภาษาในตัว หวังว่าสิ่งนี้จะเปลี่ยนแปลงในอนาคตอันใกล้นี้


24
อ่า ... วิธีการพัฒนา Demo-Driven แบบเก่าที่ดี
ÁlvaroGonzález

@ ÁlvaroGonzálezฉันจะตำหนินักพัฒนา JDK 1.0 ดั้งเดิมที่แนะนำมันตั้งแต่แรก
barell

30

ทุกอย่างยกเว้นวันของเดือนเป็น 0 ดูที่นี่สำหรับรายการทั้งหมดรวมถึงช่วง :)

จริงๆแล้วมันเป็น 1 วันตามที่เป็นลูกคี่ที่นี่ ... ทำไมถึงทำเช่นนี้? ฉันไม่รู้ ... แต่อาจเกิดขึ้นในการประชุมเดียวกันกับที่พวกเขาฉาบปูนและตัดสินใจว่าอัฒภาคเป็นทางเลือก


1
ว่า "คนตาม" สิ่งที่วันอาจเป็นเพราะไม่มีใครในใจขวาของพวกเขาเคยจะสร้างอาร์เรย์ของชื่อสตริงสำหรับวัน (เช่น{ "first", "second", "third", ..., "twenty-seventh", ... }) tm_mdayและพยายามที่จะทำดัชนีโดย จากนั้นอีกครั้งบางทีพวกเขาอาจเห็นยูทิลิตี้ที่สมบูรณ์ในการตัดข้อผิดพลาดเพียงครั้งเดียวซึ่งเป็นเหตุการณ์ปกติ
D.Shawley

ทำไมปีไม่อิง 0?
Vedmant

5

ในหนึ่งปีมี 12 เดือนเสมอดังนั้นการใช้งาน C ในช่วงต้นอาจใช้อาร์เรย์ความกว้างคงที่แบบคงที่ที่มีดัชนี 0..11


2
การใช้งาน Java Date / Calendar ยังคงรองรับเดือนพิเศษสำหรับปฏิทินบางรายการ en.wikipedia.org/wiki/Undecimber
Pointy

4

มันเป็นแบบนี้ใน java ด้วย .. น่าจะแปลง int เป็น string (0 - jan, 1-feb) พวกเขาก็เขียนโค้ดด้วยวิธีนี้ .. เพราะมันอาจมีสตริงอาร์เรย์ (ดัชนีจาก 0) ของชื่อเดือนและเดือนนี้ ตัวเลขถ้าเริ่มจาก 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;
}

แต่ใช่ Date มี API ที่ไม่ใช้งานง่ายฉันรู้สึกหัวเราะเมื่ออ่าน Twitter ของ Brendan Eich


2

พวกเขาอาจจะถือว่าเดือนนั้นเป็นการแจงนับ (ดัชนีแรกเป็น 0) และวันที่ไม่ใช่เนื่องจากไม่มีชื่อที่เกี่ยวข้อง

หรือมากกว่านั้นพวกเขาคิดว่าจำนวนวันเป็นตัวแทนที่แท้จริงของวัน (เช่นเดียวกับเดือนที่แสดงเป็นตัวเลขในวันที่เช่น 12/31) ราวกับว่าคุณสามารถแจงนับโดยใช้ตัวเลขเป็นตัวแปร แต่จริงๆแล้ว 0-based

ในความเป็นจริงในช่วงหลายเดือนพวกเขาอาจคิดว่าการแทนค่าการแจงนับที่ถูกต้องคือการใช้ชื่อเดือนแทนตัวเลขและพวกเขาจะทำเช่นเดียวกันหากวันที่มีการแทนชื่อ ลองนึกภาพว่าถ้าเราพูดว่าวันที่ 5 มกราคม, วันที่ 6 มกราคมแทนที่จะเป็น 5 มกราคม, 6 มกราคมเป็นต้นบางทีพวกเขาอาจจะทำการแจงนับเป็น 0 เป็นเวลาหลายวันเช่นกัน ...

บางทีโดยไม่รู้ตัวพวกเขาคิดเกี่ยวกับการแจงนับเป็นเวลาหลายเดือนในวันที่ {มกราคมกุมภาพันธ์ ... } และสำหรับวันที่เป็น {หนึ่งสองสาม ... } ยกเว้นวันที่คุณเข้าถึงวันนั้นเป็นตัวเลขแทนที่จะเป็นชื่อ เช่น 1 for One เป็นต้นจึงเป็นไปไม่ได้ที่จะเริ่มที่ 0 ...


คุณควรเรียนสองชั้นกับนักจิตวิทยา ยังคงเป็นความผิดพลาดที่พวกเขาทำ แต่อย่างน้อยตอนนี้เราก็เข้าใจว่าทำไมพวกเขาถึงทำเช่นนั้น
Zesty

0

อาจเป็นข้อบกพร่อง แต่ก็มีประโยชน์เช่นกันเมื่อคุณต้องการแสดงเดือนหรือวันในสัปดาห์เป็นสตริงคุณสามารถสร้างอาร์เรย์เช่น ['jan,' feb '... etc] [new Date () .getMonth ()] แทน ['', 'jan', feb ... ฯลฯ ] [วันที่ใหม่ (). getMonth ()] หรือ ['jan', 'feb' ... ฯลฯ ] [วันที่ใหม่ ( ) .getMonth () - 1]

วันของเดือนเป็นวันปกติที่ไม่มีชื่อดังนั้นคุณจะไม่สร้างอาร์เรย์ที่มีชื่อสำหรับสิ่งเหล่านั้น ในกรณีนี้ 1-31 จะจัดการได้ง่ายกว่าดังนั้นคุณต้องลบ 1 ทุกครั้ง ...


ไม่จริง คุณสามารถลบออกได้ง่ายๆ มันสร้างปัญหามากกว่าที่จะแก้เพราะตอนนี้เมื่อคุณคำนวณวันที่คุณต้องจัดการกับเดือนนั้นบ่อยครั้ง
Rey
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.