Ngày không hợp lệ ở safari


155
 alert(new Date('2010-11-29'));

chrome, ff không có vấn đề với điều này, nhưng safari khóc "ngày không hợp lệ". Tại sao ?

chỉnh sửa: ok, theo các bình luận bên dưới, tôi đã sử dụng phân tích chuỗi và thử điều này:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

chỉnh sửa ngày 22 tháng 3 năm 2018 : Có vẻ như mọi người vẫn hạ cánh ở đây - Hôm nay, tôi sẽ sử dụng momenthoặc date-fnsđược thực hiện với nó. Date-fns là rất nhiều đau đớn và ánh sáng là tốt.


Chỉ để người khác nhìn vào cùng một vấn đề: Tôi đã kết thúc bằng DateJS, giải quyết vấn đề của tôi một cách tổng thể .. Xem câu trả lời được chấp nhận để biết chi tiết.
Shrinath

2
sử dụng khoảnh khắc.js để phân tích dấu thời gian. Đặc biệt là khi giao dịch với web đa nền tảng
Ming Yuen

1
Đây là một câu hỏi cũ. Kể từ ECMAScript 2015, các chuỗi chỉ ngày tháng theo tiêu chuẩn ISO 8601 được phân tích cú pháp dưới dạng UTC. Tuy nhiên, vẫn có thể có các trình duyệt cũ hơn xung quanh sẽ không phân tích cú pháp nào cả hoặc coi nó là cục bộ.
RobG

Câu trả lời:


166

Mẫu yyyy-MM-ddkhông phải là một định dạng được hỗ trợ chính thức cho nhà Datexây dựng. Firefox dường như hỗ trợ nó, nhưng đừng tin vào các trình duyệt khác cũng làm như vậy.

Dưới đây là một số chuỗi được hỗ trợ:

  • MM-dd-yyyy
  • yyyy / MM / dd
  • MM / dd / yyyy
  • MMMM dd, yyyy
  • MMM dd, yyyy

DateJS có vẻ như là một thư viện tốt để phân tích các định dạng ngày không chuẩn.

Chỉnh sửa : chỉ cần kiểm tra tiêu chuẩn ECMA-262 . Trích dẫn từ phần 15.9.1.15:

Định dạng chuỗi thời gian ngày

ECMAScript xác định định dạng trao đổi chuỗi cho thời gian ngày dựa trên việc đơn giản hóa Định dạng mở rộng ISO 8601. Định dạng như sau: YYYY-MM-DDTHH: mm: ss.sssZ Trong đó các trường như sau:

  • YYYY là chữ số thập phân của năm trong lịch Gregorian.
  • "-" (dấu gạch ngang) xuất hiện hai lần trong chuỗi.
  • MM là tháng trong năm từ 01 (tháng 1) đến 12 (tháng 12).
  • DD là ngày trong tháng từ 01 đến 31.
  • "T" xuất hiện theo nghĩa đen trong chuỗi, để chỉ sự bắt đầu của phần tử thời gian.
  • HH là số giờ hoàn thành đã trôi qua kể từ nửa đêm dưới dạng hai chữ số thập phân.
  • ":" (dấu hai chấm) xuất hiện theo nghĩa đen hai lần trong chuỗi.
  • mm là số phút hoàn thành kể từ đầu giờ là hai chữ số thập phân.
  • ss là số giây hoàn thành kể từ khi bắt đầu phút là hai chữ số thập phân.
  • "." (dấu chấm) xuất hiện theo nghĩa đen trong chuỗi.
  • sss là số mili giây hoàn chỉnh kể từ khi bắt đầu giây là ba chữ số thập phân. Cả "." và trường mili giây có thể được bỏ qua.
  • Z là độ lệch múi giờ được chỉ định là "Z" (đối với UTC) hoặc "+" hoặc "-" theo sau là biểu thức thời gian hh: mm

Định dạng này bao gồm các hình thức chỉ ngày:

  • YYYY
  • YYYY-MM
  • YYYY-MM-DD

Nó cũng bao gồm các biểu mẫu chỉ có thời gian với phần bù múi giờ tùy chọn được nối thêm:

  • THH: mm
  • THH: mm: ss
  • THH: mm: ss.sss

Cũng bao gồm "thời gian ngày" có thể là bất kỳ sự kết hợp nào ở trên.

Vì vậy, có vẻ như YYYY-MM-DD được bao gồm trong tiêu chuẩn, nhưng vì một số lý do, Safari không hỗ trợ nó.

Cập nhật : sau khi xem tài liệu datejs , sử dụng nó, vấn đề của bạn sẽ được giải quyết bằng cách sử dụng mã như thế này:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");

4
Định dạng ISO8601 được sử dụng trong phiên bản thứ 5 của tiêu chuẩn ECMAScript và chưa được hỗ trợ rộng rãi, cách an toàn nhất để đi IMO, phân tích ngày theo cách thủ công :(
CMS

1
Điều đó rất hữu ích anh chàng .. Cảm ơn bạn .. :) Cuối cùng đã kết thúc bằng cách sử dụng datejs để định dạng.
Shrinath

đối với những người trong tương lai, xin lưu ý rằng mặc dù datejs rất tuyệt vời ở hầu hết các khía cạnh, nhưng nó không giải quyết được tất cả các vấn đề định dạng ngày, đặc biệt là với safari. đó là Pita nhưng tốt nhất nên làm thủ công nếu bạn vẫn gặp sự cố.
hoàn toàn không phải là

@darioo Vì vậy, tôi đã thử câu trả lời của bạn như sau: "var start = Date.parseExact (dấu thời gian," YYYY-DD-MM HH: mm: SS ");" dấu thời gian là "2016-01-28 00:00:00". Tuy nhiên, bây giờ tôi gặp lỗi, "Date.parseExact không phải là một hàm". Bạn có biết, những gì đang xảy ra ở đây?
threxx

5
Vấn đề tương tự của tôi là do Safari không biết cách đọc múi giờ theo định dạng múi giờ RFC 822. Tôi đã có thể khắc phục điều này bằng cách sử dụng định dạng ISO 8601. Nếu bạn có quyền kiểm soát định dạng ngày, tôi sẽ làm việc với "yyyy-MM-dd'T'HH: mm: ss.sssXXX" tạo ra nghĩa là. "2018-02-06T20: 00: 00.000 + 00: 00". Vì bất kỳ lý do gì, Safari không thể đọc "2018-02-06T20: 00: 00.000 + 0000", chú ý việc thiếu dấu hai chấm ở định dạng múi giờ.
Olmstov

223

Đối với tôi, việc triển khai một thư viện mới chỉ vì Safari không thể làm điều đó một cách chính xác là quá nhiều và một regex là quá mức cần thiết. Đây là oneliner :

console.log (new Date('2011-04-12'.replace(/-/g, "/")));

Nếu nhận được một dấu gạch chéo chỉ là vấn đề của tôi, thì tôi đã 'chấp nhận' câu trả lời của bạn (mặc dù đó là mục đích duy nhất của tôi khi tôi hỏi câu hỏi này). Bây giờ tôi đã tìm thấy dateJS, tôi đã triển khai định dạng MMM DD, YYYY để có trải nghiệm thân thiện hơn với người dùng !!!
Shrinath

13
Sự giúp đỡ một dòng này là hoàn hảo cho nhu cầu của tôi! Cảm ơn!
Cyril N.

4
Điều này là đủ đơn giản cho tôi là tốt. Không thể tin Safari không thích - nhưng cùng định dạng với một \ hoạt động. Cảm ơn @Elzo và cảm ơn Shrinath đã đăng câu hỏi
Pete

1
Tôi nghĩ rằng đây là câu trả lời hay nhất mà tôi có xu hướng quên / - / g thay vì '-'
Jacek Pietal

12
vỗ tay vì đã không thực hiện một thư viện.
lharby

55

Tôi đã phải đối mặt với một vấn đề tương tự. Date.Parse("DATESTRING")đã hoạt động trên Chrome (Phiên bản 59.0.3071.115) nhưng không hoạt động trên Safari (Phiên bản 10.1.1 (11603.2.5))

Safari:

Date.parse("2017-01-22 11:57:00")
NaN

Trình duyệt Chrome:

Date.parse("2017-01-22 11:57:00")
1485115020000

Giải pháp hiệu quả với tôi là thay thế không gian trong dateString bằng "T". (ví dụ dateString.replace(/ /g,"T"):)

Safari:

Date.parse("2017-01-22T11:57:00")
1485086220000

Trình duyệt Chrome:

Date.parse("2017-01-22T11:57:00")
1485115020000

Lưu ý rằng phản hồi từ trình duyệt Safari ít hơn 8 giờ (28800000ms) so với phản hồi được thấy trong trình duyệt Chrome vì Safari đã trả lại phản hồi trong TZ cục bộ (chậm hơn UTC 8 giờ)

Để có được cả hai lần trong cùng một TZ

Safari:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Trình duyệt Chrome:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Hoặc nếu bạn không muốn cả hai ngày giống nhau trong Safari và Chrome, bạn có thể sử dụng hàm new Date(year, month, date, hours, minutes, seconds, milliseconds)tạo. Phân tích ngày chuỗi thành một mảng các thành phần của nó để sử dụng các thành phần đó trong hàm tạo. @nizantz sẽ thật tuyệt nếu bạn nghĩ ví dụ như vậy có thể được thêm vào câu trả lời của bạn.
h3dkandi

Không đặc biệt hữu ích vì bạn nhận được ngày trong UTC và không phải giờ địa phương.
Jonas ppelgran

1
dateString.replace(/ /g,"T")Dòng mã ma thuật này đã làm việc với tôi. :)
Mazdak Shojaie

thay thế (/ - / g, '/')
Jack Hu

11

Tôi sử dụng thời điểm để giải quyết vấn đề. Ví dụ

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();

10

Để có một giải pháp hoạt động trên hầu hết các trình duyệt, bạn nên tạo đối tượng ngày tháng của mình với định dạng này

(year, month, date, hours, minutes, seconds, ms)

ví dụ:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

hoạt động tốt với IE, FF, Chrome và Safari. Ngay cả các phiên bản cũ hơn.

Trung tâm phát triển IE: Đối tượng ngày (JavaScript)

Mạng lưới Mozilla Dev: Ngày


6

chuyển đổi chuỗi thành Date fromat (bạn phải biết múi giờ của máy chủ)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

trong đó +08: 00 = timeZone từ máy chủ


Điều này không tính đến DST. Giá trị bù TZ có thể dao động và nó phụ thuộc vào chính ngày (và thời gian).
costa

5

Tôi đã có cùng một vấn đề. Sau đó, tôi đã sử dụng khoảnh khắc. Các biểu tượng đã biến mất.

Khi tạo một khoảnh khắc từ một chuỗi, trước tiên chúng tôi kiểm tra xem chuỗi có khớp với các định dạng ISO 8601 đã biết hay không, sau đó quay lại Ngày (chuỗi) mới nếu không tìm thấy định dạng đã biết.

Cảnh báo: Hỗ trợ trình duyệt để phân tích chuỗi không nhất quán. Vì không có thông số kỹ thuật về định dạng nào sẽ được hỗ trợ, những gì hoạt động trong một số trình duyệt sẽ không hoạt động trong các trình duyệt khác.

Để có kết quả phân tích nhất quán bất kỳ thứ gì ngoài chuỗi ISO 8601, bạn nên sử dụng Chuỗi + Định dạng.

ví dụ

var date= moment(String);

3

Mặc dù bạn có thể hy vọng rằng các trình duyệt sẽ hỗ trợ ISO 8601 (hoặc các tập hợp con chỉ theo ngày), nhưng đây không phải là trường hợp. Tất cả các trình duyệt mà tôi biết (ít nhất là tại các địa phương Hoa Kỳ / tiếng Anh tôi sử dụng) có thể phân tích MM/DD/YYYYđịnh dạng khủng khiếp của Hoa Kỳ .

Nếu bạn đã có các phần của ngày, thay vào đó bạn có thể muốn thử sử dụng Date.UTC () . Nếu bạn không, nhưng bạn phải sử dụng YYYY-MM-DDđịnh dạng, tôi khuyên bạn nên sử dụng biểu thức chính quy để phân tích các phần bạn biết và sau đó chuyển chúng sang Date.UTC().


Tôi đoán phân tích chuỗi là cách để đi :(
Shrinath

1

Sử dụng định dạng dưới đây, nó sẽ hoạt động trên tất cả các trình duyệt

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

// Sản phẩm của bạn sẽ như thế này "Thứ tư 23 tháng 3 năm 2016 00:00:00 GMT + 0530 (IST)"

// Lưu ý rằng đây sẽ là múi giờ hiện tại trong trường hợp này được ký hiệu là IST, để chuyển đổi sang múi giờ UTC bạn có thể bao gồm

alert(dateObj.toUTCSting);

// Đầu ra của bạn bây giờ sẽ như thế này "Thứ ba, ngày 22 tháng 3 năm 2016 18:30:00 GMT"

Lưu ý rằng bây giờ dateObj hiển thị thời gian ở định dạng GMT, cũng lưu ý rằng ngày và giờ đã được thay đổi tương ứng.

Hàm "toUTCSting" lấy thời gian tương ứng tại kinh tuyến Greenwich. Điều này thực hiện bằng cách thiết lập chênh lệch thời gian giữa múi giờ hiện tại của bạn với múi giờ Kinh tuyến Greenwich.

Trong trường hợp trên, thời gian trước khi chuyển đổi là 00:00 giờ và phút vào ngày 23 tháng 3 năm 2016. Và sau khi chuyển đổi từ GMT + 0530 (IST) giờ sang GMT (về cơ bản, nó trừ đi 5,30 giờ từ dấu thời gian đã cho trong này trường hợp) thời gian phản ánh 18,30 giờ vào ngày 22 tháng 3 năm 2016 (chính xác là 5,30 giờ sau lần đầu tiên).

Hơn nữa để chuyển đổi bất kỳ đối tượng ngày thành dấu thời gian bạn có thể sử dụng

alert(dateObj.getTime());

// đầu ra sẽ trông giống như "1458671400000" này

Điều này sẽ cung cấp cho bạn dấu thời gian duy nhất của thời gian



1

Cách tốt nhất để làm điều đó là bằng cách sử dụng định dạng sau:

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

Điều này được hỗ trợ trong tất cả các trình duyệt và sẽ không cung cấp cho bạn bất kỳ vấn đề nào. Xin lưu ý rằng các tháng được viết từ 0 đến 11.


Hoạt động tốt trên Safari và Chrome, nhưng vẫn có vấn đề trên Firefox. Safari: var date = new Date (2018,06,08,19,17) Chủ nhật ngày 08 tháng 7 năm 2018 19:17:00 GMT + 0800 (+08) Chrome: var date = ngày mới (2018,06,08,19, 17) Chủ nhật ngày 08 tháng 7 năm 2018 19:17:00 GMT + 0800 (Giờ Malaysia) Firefox: var date = new Date (2018,06,08,19,17) Ngày 2018-07-08T11: 17: 00.000Z
Biranchi

0

Vấn đề tương tự gặp phải trong Safari và nó đã được giải quyết bằng cách chèn vấn đề này vào trang web

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

Hy vọng nó cũng sẽ làm việc với trường hợp của bạn

Cảm ơn


Tại sao bạn nghĩ rằng điều này sẽ làm việc? Tôi đã xem tập lệnh và nó dường như không ghi đè các phương thức trong đối tượng Date. Tôi đã đến đây: polyfill.io/v3/url-builder và dường như không có gì về phân tích ngày.
costa

0

Như @nizantz đã đề cập trước đây, sử dụng Date.parse () không hoạt động với tôi trong Safari. Sau một chút nghiên cứu, tôi biết rằng thuộc tính LastDateModified cho đối tượng Tệp đã không được chấp nhận và không còn được Safari hỗ trợ nữa. Việc sử dụng thuộc tính LastModified của đối tượng File đã giải quyết các vấn đề của tôi. Chắc chắn không thích nó khi thông tin xấu được tìm thấy trực tuyến.

Cảm ơn tất cả những người đã đóng góp cho bài đăng này đã hỗ trợ tôi đi vào con đường tôi cần để tìm hiểu về vấn đề của mình. Nếu không có thông tin này, có lẽ tôi chưa bao giờ tìm ra vấn đề gốc của mình. Có lẽ điều này sẽ giúp người khác trong tình huống tương tự của tôi.


0

Tôi cũng đang đối mặt với vấn đề tương tự trong Safari Browser

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

Đây là giải pháp:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 

0

Đây không phải là giải pháp tốt nhất, mặc dù tôi chỉ đơn giản là bắt lỗi và gửi lại ngày hiện tại. Cá nhân tôi cảm thấy như không giải quyết được các vấn đề về Safari, nếu người dùng muốn sử dụng trình duyệt không tuân thủ tiêu chuẩn - họ phải sống với những điều kỳ quặc.

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

Tôi muốn đề nghị phụ trợ của bạn gửi ngày ISO.


Với tất cả sự tôn trọng, khi bạn có nghĩa là người dùng phải sử dụng trình duyệt mà bạn đã viết mã, điều đó có vẻ tệ trong ý nghĩa chung. Nó cũng phụ thuộc vào các trường hợp sử dụng và đối tượng mục tiêu của chúng tôi - nếu một trang web đang được xây dựng để tiêu thụ thị trường đại chúng, thì ít nhất chúng tôi cũng sẽ hỗ trợ IE10. Tôi chắc chắn rằng ai đó trong MS cũng nghĩ như vậy khi họ thiết kế / mã hóa cho trình thám hiểm internet. Chúng ta đều biết làm thế nào nó được nói về bây giờ.
Shrinath

-1

sử dụng định dạng 'mm / dd / yyyy'. Ví dụ: - Ngày mới ('02 / 28/2015 '). Nó hoạt động tốt trong tất cả các trình duyệt.

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.