ค้นหาเว็บไซต์

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

บทความที่เกี่ยวข้อง