Tại sao đối số tháng nằm trong khoảng từ 0 đến 11 trong hàm tạo Ngày của JavaScript?


128

Khi khởi tạo một Dateđối tượng mới trong JavaScript bằng lệnh gọi bên dưới, tôi phát hiện ra rằng đối số tháng được tính bắt đầu từ 0.

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

Tại sao đối số tháng bắt đầu từ 0? Mặt khác, đối số ngày của tháng (đối số cuối cùng) là một số từ 1 đến 31. Có lý do chính đáng cho việc này không?


96
Nó chỉ là để giữ cho bạn trên ngón chân của bạn.
SeanJA

4
Một cái cũng bằng 0 được lập chỉ mục là the Day of the week (integer)0-6
SeanJA

Bởi vì nó được mã hóa cho máy móc chứ không phải cho con người. Nhưng nó vẫn là một nguồn rất lớn của lỗi vì nhiều mã là (vẫn còn) được viết bởi con người :)
Christophe Roussy

4
@Christophe đối số tương tự cũng nên áp dụng cho ngày và năm.
Agnel Kurian

2
@ChristopheRoussy vâng, nếu nó được mã hóa cho máy móc, tại sao lập chỉ mục ngày kể từ ngày 1?
user151496

Câu trả lời:


55

Đó là một truyền thống cũ (có thể là đáng tiếc, có thể đang chết) trong thế giới lập trình, hãy xem hàm localtime C chuẩn (POSIX) cũ tại http://linux.die.net/man/3/localtime


14
DateĐối tượng JS được chuyển từ Java 1.0, đó là lý do tại sao. Kế thừa tất cả các sai sót của nó ... stackoverflow.com/questions/344380/…
c69

1
Bạn là đúng, truyền thống thường hoàn toàn không phù hợp và thường lần vô lý và tôi thực sự hy vọng rằng đó là truyền thống "xấu" đang thực sự chết ...
HENON

1
là năm 2019 và tôi đang khắc phục sự cố liên quan đến hành vi này, vì vậy, miễn là các khuôn khổ có góc cạnh và ngôn ngữ như javascript không dùng nữa thì điều này sẽ vẫn xảy ra - vui lòng viết vào năm 2025 trở đi ;-)
Mauricio Gracia Gutierrez

Đó là một truyền thống luôn khiến tôi dành thời gian để gỡ lỗi các vấn đề với ngày tháng ... Tự hỏi rằng truyền thống này đã gây ra bao nhiêu phần triệu giờ làm việc lãng phí.
Vedmant

102

Câu trả lời thực sự cho câu hỏi này, là nó đã được sao chép từ java.util.Date, vốn cũng có điều kỳ quặc này. Có thể tìm thấy bằng chứng trên Twitter từ Brendan Eich - người ban đầu triển khai JavaScript (bao gồmDate đối tượng):

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

tweet đầu tiên

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

tweet thứ hai

Điều này xảy ra vào năm 1995 và JDK 1.0 đang trong giai đoạn thử nghiệm. Nó ra mắt vào năm 1996. Vào năm 1997, JDK 1.1 ra mắt đã không còn sử dụng phần lớn các chức năng nữa java.util.Date, chuyển chúng sang java.util.Calendar, nhưng thậm chí vẫn có số tháng dựa trên 0. Các nhà phát triển chán ngấy với điều này đã tạo ra thư viện Joda-Time , cuối cùng dẫn đến java.timegói được đưa vào Java 8 (2014).

Tóm lại, phải mất 18 năm để Java có được một API ngày / giờ được thiết kế chính xác được tích hợp sẵn, nhưng JavaScript vẫn bị mắc kẹt trong thời kỳ đen tối. Chúng tôi thực sự có các thư viện tuyệt vời như Moment.js , date-fnsjs-joda . Nhưng hiện tại, không có gì khác hơn là Dateđược tích hợp sẵn trong ngôn ngữ. Hy vọng rằng điều này sẽ thay đổi trong tương lai gần.


24
Ah ... Phương pháp phát triển theo hướng demo cũ tốt.
Álvaro González

@ ÁlvaroGonzález Tôi sẽ đổ lỗi cho nhà phát triển JDK 1.0 ban đầu, người đã giới thiệu nó ngay từ đầu.
barell

30

Mọi thứ trừ ngày trong tháng đều dựa trên 0, hãy xem ở đây để biết danh sách đầy đủ bao gồm các phạm vi :)

Thực sự là những ngày dựa trên 1 là những điều kỳ lạ ở đây ... đủ kỳ lạ. Tại sao điều này được thực hiện? Tôi không biết ... nhưng có lẽ đã xảy ra cùng một cuộc họp mà họ đã tô trát và quyết định dấu chấm phẩy là tùy chọn.


1
Điều "dựa trên những ngày" có lẽ là bởi vì không ai trong tâm trí của họ có thể tạo một mảng tên chuỗi cho các ngày (ví dụ { "first", "second", "third", ..., "twenty-seventh", ... }:) và cố gắng lập chỉ mục nó theo tm_mday. Sau đó, một lần nữa, có thể họ chỉ thấy tiện ích tuyệt đối trong việc loại bỏ một lỗi thường xuyên xảy ra.
D.Shawley,

Họ tại sao năm không dựa trên 0?
Vedmant

5

Luôn có 12 tháng trong một năm, do đó, các triển khai C ban đầu có thể đã sử dụng một mảng có chiều rộng cố định tĩnh với các chỉ mục 0..11.


2
Việc triển khai Ngày / Lịch Java duy trì hỗ trợ thêm một tháng cho một số lịch. en.wikipedia.org/wiki/Undecimber
Pointy

4

Nó cũng giống như thế này trong java nữa .. Có lẽ để chuyển đổi int thành chuỗi (0 - jan, 1-feb), họ đã mã hóa theo cách này .. bởi vì họ có thể có một mảng chuỗi (được lập chỉ mục từ 0) tên tháng và tháng này nếu chúng bắt đầu từ 0, sẽ dễ dàng hơn rất nhiều để liên kết với các chuỗi tháng ..


3

Tôi biết nó không thực sự là một câu trả lời cho câu hỏi ban đầu, nhưng tôi chỉ muốn cho bạn thấy giải pháp ưa thích của tôi cho vấn đề này, mà tôi dường như không bao giờ ghi nhớ khi nó xuất hiện theo thời gian.

Hàm nhỏ zerofill thực hiện thủ thuật lấp đầy các số 0 khi cần thiết và tháng chỉ +1được thêm vào:

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

Nhưng đúng vậy, Date có một API khá không trực quan, tôi đã cười khi đọc Twitter của Brendan Eich.


2

Họ có thể coi tháng là một bảng kê (chỉ mục đầu tiên là 0) và không phải ngày vì họ không có tên liên quan.

Hay đúng hơn, họ nghĩ rằng số của ngày là đại diện thực tế của ngày (giống như cách các tháng được biểu thị bằng số trong một ngày như 12/31), như thể bạn có thể lập bảng liệt kê với các số là các biến, nhưng thực tế Dựa trên 0.

Vì vậy, thực tế, trong các tháng, có lẽ họ nghĩ rằng cách biểu diễn liệt kê thích hợp sẽ là sử dụng tên của tháng, thay vì các số và họ sẽ làm như vậy nếu ngày có biểu diễn tên. Hãy tưởng tượng nếu chúng ta nói 5 tháng 1, 6 tháng 1, thay vì 5 tháng 1, 6 tháng 1, v.v., thì có lẽ họ cũng đã thực hiện một bảng liệt kê dựa trên 0 trong nhiều ngày ...

Có lẽ trong tiềm thức họ nghĩ về một bảng liệt kê cho các tháng là {tháng Giêng, tháng Hai, ...} và cho các ngày là {Một, Hai, Ba, ...}, ngoại trừ những ngày bạn truy cập ngày dưới dạng số thay vì tên, như 1 cho Một, v.v., vì vậy không thể bắt đầu từ 0 ...


Bạn nên hai hạng với Nhà tâm lý học. Đó vẫn là một sai lầm mà họ đã mắc phải, nhưng ít nhất bây giờ chúng ta đã hiểu tại sao họ lại mắc phải.
Zesty

0

Nó có thể là một thiếu sót, nhưng nó cũng rất tiện dụng khi bạn muốn biểu diễn các tháng hoặc ngày trong tuần dưới dạng một chuỗi, bạn chỉ cần tạo một mảng như ['jan,' feb '... vv] [new Date () .getMonth ()] thay cho ['', 'jan', feb ... vv] [new Date (). getMonth ()] hoặc ['jan', 'feb' ... vv] [new Date ( ) .getMonth () - 1]

các ngày trong tháng bình thường không được đặt tên nên bạn sẽ không tạo mảng có tên cho những ngày đó. Trong trường hợp này, 1-31 dễ xử lý hơn, vì vậy bạn muốn trừ đi 1 mỗi lần ...


không hẳn vậy. Bạn có thể dễ dàng chỉ cần trừ một. Nó tạo ra nhiều vấn đề hơn là nó giải quyết được vì bây giờ khi bạn làm toán với ngày tháng, bạn phải thực hiện các thao tác cụ thể về tháng khá thường xuyên.
Rey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.