2016-01-13 14 views
7

Nếu bạn đi như sau:Tại sao ngày 2/8888/2016 là ngày hợp lệ trong IE và Firefox?

var s = "2/8888/2016"; 
var d = new Date(s); 
alert(d); 

Trong Chrome, bạn sẽ nhận được:

Ngày không hợp lệ

Nhưng trong IE và Firefox, bạn sẽ nhận được:

Fri Jun 01 2040 00:00:00 GMT-0500 (Giờ ban ngày trung tâm)

Dường như chỉ cần thêm 8888 ngày vào ngày 01 tháng 2. Thay vào đó, tôi cho rằng ngày được coi là không hợp lệ. Có cách nào tôi có thể làm cho FireFox và IE nghĩ chuỗi ngày này không hợp lệ?

+0

Bạn luôn có thể kiểm tra số bằng cách tách chuỗi và kiểm tra xem '8888' có lớn hơn 31 – Derek

+0

cũng không, bởi vì các vấn đề 'thời gian' trong javascript (cũng khủng khiếp như java, lol), tôi sử dụng: http://momentjs.com/ để thu hẹp khoảng cách. – Derek

+0

@DerekPollard không thành công vào ngày 11 tháng 31 và là phần thưởng bạn có thể viết lôgic năm nhuận của riêng bạn. – djechlin

Trả lời

3

Câu trả lời ngắn:

Đó là một misbehaviuor trong những trình duyệt bạn đang nhắc đến.

Bạn phải tự kiểm tra ngày có định dạng chính xác không.Nhưng nó khá tầm thường, tôi đề nghị phương pháp này:

Chia ngày trong năm y, tháng m, ngày d và tạo đối tượng Date:

var date = new Date(y, m - 1, d); // note that month is 0 based 

Sau đó so sánh các giá trị ban đầu với các giá trị logic thu được bằng cách sử dụng phương pháp Date:

var isValid = date.getDate() == d && 
       date.getMonth() == m-1 && 
       date.getFullYear() == y; 

Trước khi làm tất cả những điều bạn có thể muốn kiểm tra nếu chuỗi ngày có hiệu lực trong bất kỳ trình duyệt:

Detecting an "invalid date" Date instance in JavaScript



dài câu trả lời:

Firefox (và IE) chấp nhận "2/8888/2016 "dưới dạng định dạng chuỗi chính xác có vẻ là lỗi/hành vi sai trái.

Trong thực tế theo ECMAScript 2015 Language Specification khi Date() được gọi với một đối số chuỗi duy nhất nên cư xử giống như Date.parse()

http://www.ecma-international.org/ecma-262/6.0/#sec-date-value

Sau

nỗ lực để phân tích định dạng của chuỗi theo các quy tắc (bao gồm cả các năm mở rộng) được gọi trong Định dạng chuỗi ngày giờ (20.3.1.16)

..that được quy định ở đây

http://www.ecma-international.org/ecma-262/6.0/#sec-date-time-string-format

nơi bạn có thể đọc

Cấu trúc của nó như sau: YYYY-MM-DDThh: mm: ss.sssZ

[...]

MM là tháng của năm từ 01 (tháng 1) t o 12 (tháng 12).

DD là ngày của tháng từ 01 đến 31.


Dường như Firefox được giải thích các chuỗi giá trị như khi Date() được gọi với nhiều tranh cãi.

Từ

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Lưu ý: đâu ngày được gọi là một nhà xây dựng với nhiều hơn một đối số, nếu giá trị lớn hơn phạm vi hợp lý của họ (ví dụ 13 được cung cấp như là giá trị tháng hoặc 70 cho giá trị phút), giá trị liền kề sẽ được điều chỉnh. Ví dụ. Ngày mới (2013, 13, 1) tương đương với Ngày mới (2014, 1, 1), cả hai tạo ngày cho 2014-02-01 (lưu ý rằng tháng là 0-based). Tương tự đối với các giá trị khác: ngày mới (2013, 2, 1, 0, 70) tương đương với ngày mới (2013, 2, 1, 1, 10), cả hai đều tạo ngày cho 2013-03-01T01: 10: 00.

Điều này có thể giải thích như thế nào "2/8888/2016" biến thành 2040-05-31T22:00:00.000Z

+0

Bạn đã hiểu sai bài viết MDN đó. Trong trường hợp này, * Ngày * đang được gọi với một đối số chuỗi, do đó, nó là các quy tắc cho [* Date.parse *] (http://www.ecma-international.org/ecma-262/6.0/#sec- date.parse) được sử dụng: "* Nếu Type (v) là String, thì hãy để tv là kết quả của việc phân tích cú pháp v là một ngày, theo cách tương tự như đối với phương thức phân tích cú pháp ... *". – RobG

+0

"'* 2/8888/2016' là định dạng đúng để tạo đối tượng Ngày *" có hiệu quả nhất gây hiểu nhầm.Nó sẽ gây ra hành vi phụ thuộc thực hiện (như OP đã phát hiện ra) và không phù hợp với bất kỳ định dạng nào được chỉ định trong ECMA-262 hoặc được chấp nhận bởi các trình duyệt đang sử dụng. Cũng không phải là chuỗi ngày hợp lệ là 8888 cũng không phải là số tháng hoặc ngày hợp lệ. Do đó rất khó để biện minh cho việc gọi nó là "đúng" trong bất kỳ ngữ cảnh nào. – RobG

+0

@RobG bạn nói đúng. Tôi gần như viết lại câu trả lời của mình. Cảm ơn bạn đã chỉ cho tôi thông số kỹ thuật ngôn ngữ ECMA. – Paolo

1

Không có cách nào để làm cho IE và FF nghĩ đó là không hợp lệ, ngoại trừ:

  • bạn có thể thay đổi hiện thực javascript họ
  • bạn sử dụng một thư viện thay vì để đối phó với điều đó.

Chúng tôi cũng có thể mong đợi Javascript, như một ngôn ngữ, phát triển và chúng tôi có thể vượt qua các ngón tay của mình mà các trình duyệt quyết định tuân theo đặc điểm kỹ thuật nghiêm ngặt hơn. Vấn đề tất nhiên là mỗi "sửa chữa" cũng phải tương thích ngược với các phiên bản trước của ngôn ngữ (không xảy ra luôn luôn, Perl chẳng hạn).

Vì vậy, điều tốt nhất hiện nay là sử dụng một số thư viện giống như momentjs theo đề xuất của Derek trong bài đăng nhận xét.

+0

Đó là những gì tôi đã giả định, nhưng muốn kiểm tra xem không có điều gì rõ ràng tôi đã bỏ lỡ hoặc có thể làm. Cảm ơn! – lhan

0

Bạn đã tình cờ được nêu ra một lý do tại sao bạn nên tự phân tích chuỗi ngày.

Khi Date được cung cấp một đối số chuỗi đơn, nó được coi là chuỗi ngày và được phân tích cú pháp theo các quy tắc trong Date.parse. Các quy tắc đầu tiên cố gắng phân tích cú pháp đó dưới dạng ISO 8601 format string. Nếu điều đó không hoạt động, nó có thể rơi trở lại bất kỳ thuật toán phân tích cú pháp nào nó muốn.

Trong trường hợp "2/8888/2016", trước tiên trình duyệt sẽ cố gắng phân tích cú pháp dưới dạng định dạng ISO và không thành công. Có vẻ như từ thực nghiệm rằng IE và Firefox xác định rằng chuỗi là theo định dạng tháng/ngày/năm và có hiệu quả gọi Ngày constructor với:

new Date(2016,1,8888); 

Tuy nhiên, các trình duyệt khác có thể cố gắng để xác nhận các giá trị và quyết định rằng 8888 là không phải là ngày hoặc tháng hợp lệ, vì vậy hãy trả lại ngày không hợp lệ. Cả hai câu trả lời đều tương thích với ECMA-262. Lời khuyên tốt nhất là luôn phân tích cú pháp chuỗi ngày theo cách thủ công (thư viện có thể trợ giúp, nhưng thông thường không cần thiết như chức năng phân tích cú pháp riêng biệt với xác thực là 3 dòng mã), sau đó bạn có thể chắc chắn về kết quả nhất quán trong bất kỳ trình duyệt nào hoặc môi trường máy chủ.

Các vấn đề liên quan