new Date () được đặt thành 31 tháng 12 năm 2014 nói thay vào đó là ngày 1 tháng 12


80

Tôi đang cố gắng chuyển đổi một chuỗi thành đối tượng Ngày và nó hoạt động trong tất cả các ngày ngoại trừ ngày 31 tháng 12 trong đó đối tượng nói là ngày 1 tháng 12 thay vì ngày 31. Tôi không biết tại sao. Đây là JavaScriptmã của tôi :

var dt = new Date();
dt.setDate("31");
dt.setMonth("11");
dt.setFullYear("2014");

nhưng giá trị biến của tôi là:

Mon Dec 01 2014 11:48:08 GMT+0100 (Paris, Madrid)

Nếu tôi làm tương tự cho bất kỳ ngày nào khác, đối tượng của tôi sẽ trở về giá trị thích hợp. Bạn có biết tôi đã làm gì sai không?


7
Bạn muốn chuyển các số nguyên cho setMonth, v.v., không phải chuỗi.
funkybro

15
bạn có thể sử dụng các Datethông số của constructor trực tiếp:new Date(2014, 11, 31)
pomeh

9
btw. không phải là tháng 11 tháng mười một?
jnovacho


5
@JuhaUntinen Không, ngày bị nhầm lẫn vì tháng hiện tại chỉ có 30 ngày.
Mr Lister

Câu trả lời:


85

setMonth nên trước setDate: ( không an toàn cho Tháng ít hơn 31 ngày )

var dt = new Date();
dt.setFullYear(2014);
dt.setMonth(11);
dt.setDate(31);

setMonththam số thứ hai của cũng có thể được sử dụng để đặt ngày.

var dt = new Date();
dt.setFullYear(2014);
dt.setMonth(11, 31);


Nếu không có đối số nào được cung cấp cho hàm tạo, nó sẽ sử dụng ngày và giờ hiện tại theo cài đặt hệ thống.

Vì vậy, sử dụng setMonthsetDate riêng vẫn sẽ gây ra kết quả bất ngờ.

Nếu các giá trị được đặt lớn hơn phạm vi logic của chúng , giá trị sẽ được tự động điều chỉnh thành giá trị liền kề .

Ví dụ, nếu hôm nay là 2014-09-30, sau đó

var dt = new Date();
dt.setFullYear(2014); /* Sep 30 2014 */
dt.setMonth(1);       /* Mar 02 2014, see, here the auto adjustment occurs! */
dt.setDate(28);       /* Mar 28 2014 */

Để tránh điều này, hãy đặt các giá trị bằng cách sử dụng hàm tạo trực tiếp.

var dt = new Date(2014, 11, 31);

1
Tôi vừa mới phát hiện ra, thực sự, nhưng nó không thực sự có ý nghĩa đối với tôi
user2859409 09/09

15
@ user2859409 nó có thể là bởi vì nếu bạn không đặt tháng đầu tiên phải mất tháng hiện tại và sau đó đôi khi có thể quấn vào tháng tới (như mỗi câu trả lời Jakub của bên dưới)
fbstj

3
Tôi ngần ngại đề xuất khối mã đầu tiên đó trong những tháng có ít hơn 31 ngày. Ví dụ: nếu bạn muốn đặt ngày là ngày 15 tháng 9, nhưng hôm nay là ngày 31 tháng 8, ngày này sẽ chuyển sang tháng tiếp theo và bạn sẽ kết thúc bằng ngày 15 tháng 10. +1 cho khối mã thứ hai: đó là cách tốt hơn để đi. Tôi thậm chí còn không biết dạng setMonthtồn tại của 2 đối số .
Luke Woodward

10
Lưu ý rằng việc đặt tháng trước ngày cũng có thể sai. Tuy nhiên, không phải trong trường hợp này. Nếu là ngày 31 tháng 10, thì setMonth (10) sẽ đặt ngày thành 31 tháng 11, ngày này sẽ chuyển thành ngày 1 tháng 12. setDate (31) thì kết quả là 31 tháng 12. Vì vậy, hãy luôn sử dụng 2 đối số setMonth ().
Florian F

1
+1 nhưng tôi muốn nhấn mạnh rằng tùy chọn hai tháng được ưu tiên hơn để ngăn ngừa các tác dụng phụ.
Brian

120

Vấn đề là, khi bạn đặt một ngày đầu tiên, bạn vẫn đang ở trong tháng hiện tại, vì vậy tháng Chín. Tháng 9 chỉ có 30 ngày nên:

var dt = new Date(); /* today */
dt.setDate("31"); /* 1st Oct 2014 as should be by spec */
dt.setMonth("11"); /* 1st Dec 2014 */
dt.setFullYear("2014"); /* 1st Dec 2014 */

22
1 - Đây là loại lỗi mà sẽ nằm im tất cả tháng Tám, và sau đó cắn bạn trong mông đến tháng chín;)
Niết Dark Absol

19
KHÔNG BAO GIỜ đúng khi đặt ngày cho từng thành phần, vì có những trường hợp thất bại với ngày đầu tiên tháng đầu tiên, có thể với năm đầu tiên vào ngày 29/2. Bạn phải đặt cả ba trường cùng một lúc.
Jim Garrison

5
+1 và nó phải là một câu trả lời được chấp nhận, vì nó giải thích TẠI SAO bạn nên đặt tháng trước. Đó là một WTF rất javascript
Danubian Thủy thủ

2
Phải tương tự trong các ngôn ngữ khác để không phải là "javascript WTF".
Raidri hỗ trợ Monica

Tại sao đối tượng Date không ném ra khi một ngày không chính xác được đặt?
jww

23

Đó là bởi vì điều đầu tiên bạn làm là

dt.setDate(31)

Điều này đặt ngày hiện tại thành 31. Tháng hiện tại là tháng 9, có 30 ngày, vì vậy nó kết thúc tròn.

Nếu bạn in ngày sau thời điểm này, nó sẽ là ngày 1 tháng 10.


12
Điều buồn cười là, điều này chỉ xuất hiện vì anh ấy đã thử nó trong một tháng với 30 ngày. Một tháng sau và nó có vẻ như sẽ hoạt động tốt.
Peter Remmers

13

Giả sử mục đích của bạn là đặt năm, tháng và ngày đồng thời, bạn có thể sử dụng hàm tạo ngày dài hơn :

mới Ngày (năm, tháng, ngày, giờ, phút, giây, mili giây);

[...]

Nếu ít nhất hai đối số được cung cấp, các đối số bị thiếu được đặt thành 1 (nếu thiếu ngày) hoặc 0 cho tất cả các đối số khác.

Vì vậy, bạn sẽ viết:

var dt = new Date(2014, 11, 31);

Như đã được thiết lập, việc đặt một phần ngày tại một thời điểm có thể dẫn đến tràn:

var dt = new Date(2012, 1, 29); // Feb 29 2012
dt.setFullYear(2014);           // Mar 01 2014 instead of Feb 28 2014

Hơn nữa, việc đặt tháng trước ngày vẫn có thể gây tràn không mong muốn (các câu trả lời khuyên bạn nên thay đổi thứ tự của các phương pháp là không chính xác):

var dt = new Date(2014, 0, 31); // Jan 31 2014
dt.setFullYear(2014);           // Jan 31 2014
dt.setMonth(1);                 // Mar 03 2014 instead of Feb 28 2014
dt.setDate(1);                  // Mar 01 2014

i như câu trả lời này, bởi vì nó mang lại cho bạn những giải pháp đúng ở phía trên, sau đó giải thích tại sao các giải pháp phá vỡ không làm việc ...
Kip

7

Lý do tại sao của hành vi và cách tránh nó đã được giải thích.

Nhưng lỗi thực sự trong mã của bạn là bạn không nên sử dụng hàm tạo mặc định: new Date (). Mã của bạn sẽ dẫn đến một Ngày vào ngày 13 tháng 12 với thời gian hiện tại. Tôi nghi ngờ đây là những gì bạn muốn. Bạn nên sử dụng hàm tạo Ngày lấy năm, tháng và ngày làm tham số.


1
Tôi cho rằng nó được dự định là nhận xét về câu trả lời được chấp nhận?
Danubian Sailor,

Không hẳn. Đó là một câu trả lời cho câu hỏi "Tôi đã làm gì sai?"
Florian F

-1

Câu trả lời đã làm rõ rằng thứ tự phù hợp để thiết lập ngày là:

  • setFullYear ()
  • setMonth ()
  • đặt ngày()

Tôi chỉ muốn chỉ ra rằng việc đặt năm đầu tiên cũng rất quan trọng, vì ngày 29 tháng 2 năm nhuận.


1
Không. Đơn đặt hàng không đảm bảo rằng ngày sẽ được đặt chính xác. Xem bình luận bên dưới các câu trả lời được chấp nhận và bình chọn nhiều nhất.
Salman A

1
Nếu ngày bắt đầu của bạn là ngày 31 và bạn đặt nó thành tháng có ít hơn (như 30) ngày, bạn sẽ kết thúc vào tháng tiếp theo. Vì vậy, điều này chỉ là không đủ. Để an toàn, bạn nên đặt ngày không cao hơn 28 trước khi đặt tháng. Và cuối cùng đặt lại ngày về giá trị cuối cùng của nó, nếu giá đó cao hơn.
bart

-3
var dt = new Date();
dt.setFullYear(2014);
dt.setMonth(11);
dt.setDate(31);

Truyền giá trị dưới dạng số nguyên không phải chuỗi .. nó sẽ trả về giá trị đúng của u ..


Cập nhật - mô tả ở trên không đúng .. vấn đề chính là bạn cần phải đặt ba dòng này theo trình tự thích hợp .. Ngay cả khi tôi đã sửa trình tự, tôi đã quên sửa mô tả ..: P


Không, không, đây là thử nghiệm của tôi trong bảng điều khiển chrome: var dt = new Date (); không xác định dt.setDate (31); 1412157761255 dt.setMonth (11); 1417431761255 dt.setFullYear (2014); 1417431761255 dt Thứ Hai, ngày 01 tháng 12 năm 2014 12:02:41 GMT + 0100 (Paris, Madrid)
user2859409

6
Nó không liên quan gì đến loại đối số và mọi thứ liên quan đến trình tự. Bạn đang đề cập đến trình tự như thể nó là thứ phụ ...
dee-see

1
Trong khi mã đó hoạt động , bạn đã đưa ra lời giải thích sai , tại sao.
Danubian Sailor
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.