datetime - ทำไมอาร์กิวเมนต์เดือนถึงมีค่าตั้งแต่ 0 ถึง 11 ในตัวสร้าง Date ของ JavaScript?
เมื่อเริ่มต้นวัตถุ Date ใหม่ใน JavaScript โดยใช้คำสั่งด้านล่าง ฉันพบว่าตัวแปรเดือนเริ่มนับจากศูนย์
new Date(2010, 3, 1); // that's the 1st April 2010!
ทำไมอาร์กิวเมนต์เดือนเริ่มจาก 0? ในทางกลับกัน อาร์กิวเมนต์วันของเดือน (ตัวสุดท้าย) เป็นตัวเลขตั้งแต่ 1 ถึง 31 มีเหตุผลที่ดีสำหรับเรื่องนี้หรือไม่?
คำตอบ #1
คำตอบที่แท้จริงสำหรับคำถามนี้ คือ มันถูกคัดลอกมาจาก java.util.Date ซึ่งก็มีข้อพิสดารนี้เช่นกัน หลักฐานสามารถพบได้บน Twitter จาก Brendan Eich - คนที่เป็นผู้พัฒนา JavaScript ดั้งเดิม:
https://twitter.com/BrendanEich/status/481939099138654209
https://twitter.com/BrendanEich/status/771006397886533632
เบรนแดนยังระบุด้วยว่าคนที่ทำการพอร์ตจากจาวาคือเคน สมิธจากเน็ตสเคป
https://twitter.com/BrendanEich/status/771006208949891072
เรื่องนี้เกิดขึ้นในปี 1995 และ JDK 1.0 อยู่ในขั้นเบต้า มันเปิดตัวในปี 1996 ในปี 1997 JDK 1.1 ออกมา ซึ่งยกเลิกการใช้ฟังก์ชันส่วนใหญ่ใน java.util.Date และย้ายไปยัง java.util.Calendar แต่แม้กระนั้นมันก็ยังมีเดือนที่เริ่มจากศูนย์ นักพัฒนาที่เหนื่อยหน่ายกับเรื่องนี้จึงสร้างไลบรารี Joda-Time ขึ้น ซึ่งท้ายที่สุดนำไปสู่แพ็กเกจ java.time ที่รวมมากับ Java 8 (2014)
โดยสรุป มันใช้เวลาถึง 18 ปีที่ Java จะมี API สำหรับวันที่/เวลาที่ถูกออกแบบอย่างถูกต้องในตัว แต่ JavaScript ยังคงติดอยู่ในยุคมืดอยู่ เรามีไลบรารีที่ยอดเยี่ยมเช่น Luxon, Moment.js, date-fns, js-joda และอื่น ๆ แต่ ณ ตอนนี้ ยังไม่มีอะไรนอกจาก Date ที่ฝังอยู่ในภาษา หวังว่าสิ่งนี้จะแก้ไขในอนาคตอันใกล้ด้วยข้อเสนอ TC39 Temporal
คำตอบ #2
มันเป็นประเพณีเก่า (อาจโชคร้าย อาจใกล้ตาย) ในโลกของการเขียนโปรแกรม ดูฟังก์ชัน C มาตรฐานเก่า (POSIX) localtime http://linux.die.net/man/3/localtime
คำตอบ #3
ทุกอย่างนอกจากวันของเดือนนั้นเริ่มจาก 0 ดูที่นี่สำหรับรายการเต็มรวมถึงช่วงต่างๆ :)
จริง ๆ แล้ววันนับจาก 1 เป็นสิ่งที่แปลกประหลาดที่นี่...แปลกพอสมควร ทำไมถึงทำแบบนี้? ฉันไม่รู้...แต่คงเกิดขึ้นในการประชุมเดียวกันที่พวกเขาเมามากแล้วตัดสินใจว่าวงเล็บเซมิโคลอนเป็นสิ่งที่ไม่จำเป็น
คำตอบ #4
ในปี 2024 คำถามที่แท้จริงคือ:
ถ้า
Dateถูกทำให้เสียตั้งแต่วันแรกของ JS ทำไมหลังจาก 29 ปี (28 ถ้านับจากศูนย์) มันยังอยู่ดี?
JS มีหลายส่วน/ลักษณะที่ไม่ดีและสิ่งที่แย่ที่สุดก็คือบางส่วนยังไม่ได้รับการแก้ไขเป็นเวลาหลาย ทศวรรษ (ข้อเท็จจริงที่น่าสนใจ: เรากำลังพูดถึง Date วันที่)
แต่เราก็โชคดี ดูเหมือนว่าจุดสิ้นสุดของ Date จะใกล้เข้ามาแล้ว
สปอยเลอร์
new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26
ชั่วคราว (ข้อเสนอ)
จากบทนำของข้อเสนอ:
Dateเป็นปัญหาที่มีมายาวนานใน ECMAScript นี่เป็นข้อเสนอสำหรับTemporalซึ่งเป็นObjectระดับโลกที่ทำหน้าที่เป็น namespace ชั้นบน (เหมือนกับMath) ที่นำ API วันที่/เวลาแบบสมัยใหม่มาใช้กับภาษา ECMAScript
มันอิงตาม เอกสารรายงานว่า "จากกรณีการใช้งานทั่วไปที่เราตรวจสอบ" และมีหลายประเภทสำหรับข้อมูลชนิดต่าง ๆ:
- ประเภท
Plainไม่มีโซนเวลา - ประเภท
ZonedDateTimeมีเขตเวลา - ประเภทส่วนใหญ่มีปฏิทิน
- หลายประเภทที่มีประโยชน์:
Absolute,DateTime,Date,Time,TimeZone, ...
นี่คือสคีมาที่แสดงประเภท Temporal ต่าง ๆ และความสัมพันธ์ของพวกมัน
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับพวกเขาได้ในเอกสารที่มีอยู่และในหนังสือทำอาหารที่ดี หรือสำรวจปัญหาปัจจุบันสำหรับปัญหาที่เปิดอยู่
เมื่อ Temporal จะพร้อมใช้งาน
ตั้งแต่เดือนมีนาคม 2564 อยู่ใน ขั้นตอน 3/ร่าง (ดูการอ้างอิงขั้นตอน TC39) ดูสไลด์ TC39 เดือนมีนาคม 2564
ตอนนี้มันสามารถถูกรวมเข้าใน TypeScript ได้ในเร็วๆ นี้ เนื่องจากนโยบายของพวกเขาคือ:
เมื่อฟีเจอร์ใหม่ ๆ ถึงขั้นตอนที่ 3 แล้ว ฟีเจอร์เหล่านั้นก็พร้อมที่จะถูกนำเข้าใน TypeScript
น่าจะสำหรับ Node และเบราว์เซอร์หลัก ๆ เราคงต้องรออีกสักหน่อย
เริ่มทดลองวันนี้
ในระหว่างนี้คุณสามารถทดลองใช้งานมันโดยใช้ Temporal polyfill ได้
npm install --save proposal-temporal
// temporal-test.js
const { Temporal } = require('proposal-temporal');
// or as an ES module
// import { Temporal } from 'proposal-temporal/lib/index.mjs';
// 11 means November now!
const date = new Temporal.PlainDate(2020, 11, 26); // => 2020-11-26
const sameDate = Temporal.PlainDate.from(
{year: 2020, month: 11, day: 26}); // => 2020-11-26



