Tại sao Date.parse cho kết quả không chính xác?


344

Trường hợp thứ nhất:

new Date(Date.parse("Jul 8, 2005"));

Đầu ra:

Thứ Sáu, ngày 08 tháng 7 năm 2005 00:00:00 GMT-0700 (PST)

Trường hợp thứ hai:

new Date(Date.parse("2005-07-08"));

Đầu ra:

Ngày 07 tháng 7 năm 2005 17:00:00 GMT-0700 (PST)


Tại sao phân tích thứ hai không chính xác?


30
Phân tích cú pháp thứ hai không chính xác mỗi lần, chỉ là lần đầu tiên được phân tích cú pháp theo giờ địa phương và lần thứ hai trong UTC. Lưu ý rằng "Thu Jul 07 2005 17:00:00 GMT-0700 (PST)" giống như "2005-07-08 00:00".
jches


18

1
Trong trường hợp bất kỳ ai đến đây để tìm hiểu lý do tại sao một ngày trở lại NaNtrong Firefox, tôi phát hiện ra rằng hầu hết các trình duyệt khác (và Node.js) sẽ phân tích một ngày mà không có một ngày, chẳng hạn như "Tháng Tư 2014" là ngày 1 tháng 4 năm 2014, nhưng Firefox trả về NaN. Bạn phải vượt qua một ngày thích hợp.
Jazzy

Để thêm vào nhận xét của Jason ở trên: Nếu bạn đang nhận được NaN trong Firefox, một vấn đề khác có thể là Firefox và Safari không thích ngày được gạch nối. Chỉ Chrome mới làm được. Sử dụng một dấu gạch chéo thay thế.
Bangkok

Câu trả lời:


451

Cho đến khi phiên bản thứ 5 xuất hiện, Date.parsephương thức này hoàn toàn phụ thuộc vào việc thực hiện ( new Date(string)tương đương với Date.parse(string)ngoại trừ cái sau trả về một số chứ không phải là a Date). Trong phiên bản thứ 5, yêu cầu đã được thêm vào để hỗ trợ đơn giản hóa ISO-8601 được (và hơi không chính xác) (cũng xem Chuỗi thời gian ngày hợp lệ trong JavaScript là gì? ). Nhưng ngoài điều đó ra, không có yêu cầu nào cho những gìDate.parse/new Date(string)nên chấp nhận ngoài việc họ phải chấp nhận bất kỳDate#toStringđầu ra nào (mà không nói đó là gì).

Kể từ ECMAScript 2017 (phiên bản 8), việc triển khai được yêu cầu phân tích đầu ra của chúng cho Date#toStringDate#toUTCString, nhưng định dạng của các chuỗi đó không được chỉ định.

Kể từ ECMAScript 2019 (phiên bản 9), định dạng cho Date#toStringDate#toUTCString, đã được chỉ định là (tương ứng):

  1. ddd MMM DD YYYY HH: mm: ss ZZ [(tên múi giờ)]
    ví dụ Thứ ba ngày 10 tháng 7 năm 2018 18:39:58 GMT + 0530 (IST)
  2. ddd, DD MMM YYYY HH: mm: ss Z,
    ví dụ: Thứ ba 10 tháng 7 năm 2018 13:09:58 GMT

cung cấp thêm 2 định dạng Date.parsenên phân tích đáng tin cậy trong các triển khai mới (lưu ý rằng hỗ trợ không phổ biến và các triển khai tuân thủ không theo quy tắc sẽ vẫn được sử dụng trong một thời gian).

Tôi muốn giới thiệu rằng các chuỗi ngày được phân tích cú pháp theo cách thủ công và hàm tạo Ngày được sử dụng với các đối số năm, tháng và ngày để tránh sự mơ hồ:

// parse a date in yyyy-mm-dd format
function parseDate(input) {

  let parts = input.split('-');

  // new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
  return new Date(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
}

Tuyệt vời, tôi đã phải sử dụng điều này vì Date.parseđã không cư xử với các định dạng ngày ở Vương quốc Anh vì một số lý do tôi không thể làm việc
Ben

1
Các phần thời gian được ghi lại bằng mã @CMS. Tôi đã sử dụng mã này với định dạng ngày "2012-01-31 12:00:00" return new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);Hoạt động hoàn hảo, cảm ơn!
Richard Rout

1
@CMS bạn có ý nghĩa gì khi thực hiện phụ thuộc ?
Royi Namir

3
@RoyiNamir, điều đó có nghĩa là kết quả phụ thuộc vào trình duyệt web nào (hoặc triển khai JavaScript khác) đang chạy mã của bạn.
Phường Samuel Edwin

1
Tôi cũng gặp vấn đề với Ngày (chuỗi) mới trong các trình duyệt khác nhau hoạt động khác nhau. Thậm chí không có vấn đề gì về việc nó bị hỏng trên các phiên bản IE cũ, các trình duyệt khác nhau không nhất quán. Không sử dụng Date.parse hoặc Ngày mới (chuỗi) bao giờ.
Hoffmann

195

Trong kinh nghiệm gần đây khi viết một trình thông dịch JS, tôi đã vật lộn rất nhiều với các hoạt động bên trong của ngày ECMA / JS. Vì vậy, tôi nghĩ rằng tôi sẽ ném 2 xu của mình vào đây. Hy vọng việc chia sẻ nội dung này sẽ giúp những người khác có bất kỳ câu hỏi nào về sự khác biệt giữa các trình duyệt trong cách họ xử lý ngày.

Phía đầu vào

Tất cả các cài đặt đều lưu trữ giá trị ngày của chúng bên trong dưới dạng số 64 bit đại diện cho số mili giây (ms) kể từ 1970-01-01 UTC (GMT giống với UTC). Ngày này là kỷ nguyên ECMAScript cũng được sử dụng bởi các ngôn ngữ khác như các hệ thống Java và POSIX như UNIX. Ngày xảy ra sau kỷ nguyên là số dương và ngày trước là âm.

Mã sau đây được hiểu là cùng một ngày trong tất cả các trình duyệt hiện tại, nhưng với phần bù múi giờ cục bộ:

Date.parse('1/1/1970'); // 1 January, 1970

Trong múi giờ của tôi (EST, là -05: 00), kết quả là 18000000 vì đó là bao nhiêu ms trong 5 giờ (chỉ 4 giờ trong các tháng tiết kiệm ánh sáng ban ngày). Giá trị sẽ khác nhau ở các múi giờ khác nhau. Hành vi này được chỉ định trong ECMA-262 vì vậy tất cả các trình duyệt thực hiện theo cùng một cách.

Mặc dù có một số phương sai trong các định dạng chuỗi đầu vào mà các trình duyệt chính sẽ phân tích thành ngày, nhưng về cơ bản, chúng diễn giải chúng giống như liên quan đến múi giờ và tiết kiệm ánh sáng ban ngày mặc dù phân tích cú pháp chủ yếu phụ thuộc vào việc thực hiện.

Tuy nhiên, định dạng ISO 8601 là khác nhau. Đây là một trong hai định dạng được nêu trong ECMAScript 2015 (ed 6) cụ thể phải được phân tích cú pháp theo cùng một cách bởi tất cả các triển khai (định dạng còn lại là định dạng được chỉ định cho Date.prototype.toString ).

Nhưng, ngay cả đối với các chuỗi định dạng ISO 8601, một số triển khai đã hiểu sai. Đây là kết quả so sánh của Chrome và Firefox khi câu trả lời này ban đầu được viết cho 1/1/1970 (kỷ nguyên) trên máy của tôi bằng cách sử dụng các chuỗi định dạng ISO 8601 nên được phân tích cú pháp thành chính xác cùng một giá trị trong tất cả các lần triển khai:

Date.parse('1970-01-01T00:00:00Z');       // Chrome: 0         FF: 0
Date.parse('1970-01-01T00:00:00-0500');   // Chrome: 18000000  FF: 18000000
Date.parse('1970-01-01T00:00:00');        // Chrome: 0         FF: 18000000
  • Trong trường hợp đầu tiên, bộ xác định "Z" chỉ ra rằng đầu vào ở thời gian UTC nên không được bù từ epoch và kết quả là 0
  • Trong trường hợp thứ hai, chỉ định "-0500" chỉ ra rằng đầu vào nằm trong GMT-05: 00 và cả hai trình duyệt diễn giải đầu vào là ở múi giờ -05: 00. Điều đó có nghĩa là giá trị UTC được bù từ kỷ nguyên, có nghĩa là thêm 18000000ms vào giá trị thời gian nội bộ của ngày.
  • Trường hợp thứ ba, nơi không có specifier, nên được coi là cục bộ cho hệ thống máy chủ. FF coi chính xác đầu vào là giờ địa phương trong khi Chrome coi nó là UTC, do đó tạo ra các giá trị thời gian khác nhau. Đối với tôi điều này tạo ra sự khác biệt 5 giờ trong giá trị được lưu trữ, đó là vấn đề. Các hệ thống khác có độ lệch khác nhau sẽ nhận được kết quả khác nhau.

Sự khác biệt này đã được sửa chữa vào năm 2020, nhưng các quirks khác tồn tại giữa các trình duyệt khi phân tích chuỗi định dạng ISO 8601.

Nhưng nó trở nên tồi tệ hơn. Một điều khó hiểu của ECMA-262 là định dạng chỉ ngày ISO 8601 (YYYY-MM-DD) được yêu cầu phân tích thành UTC, trong khi ISO 8601 yêu cầu nó phải được phân tích cú pháp thành cục bộ. Đây là đầu ra từ FF với các định dạng ngày ISO dài và ngắn không có chỉ định múi giờ.

Date.parse('1970-01-01T00:00:00');       // 18000000
Date.parse('1970-01-01');                // 0

Vì vậy, lần đầu tiên được phân tích cú pháp là cục bộ vì đó là ngày và thời gian ISO 8601 không có múi giờ và lần thứ hai được phân tích cú pháp là UTC vì đó chỉ là ngày ISO 8601.

Vì vậy, để trả lời trực tiếp câu hỏi ban đầu, "YYYY-MM-DD"ECMA-262 yêu cầu phải được hiểu là UTC, trong khi câu hỏi còn lại được hiểu là cục bộ. Đó là lý do:

Điều này không tạo ra kết quả tương đương:

console.log(new Date(Date.parse("Jul 8, 2005")).toString()); // Local
console.log(new Date(Date.parse("2005-07-08")).toString());  // UTC

Cái này không

console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00")).toString());

Dòng dưới cùng là để phân tích chuỗi ngày. Chuỗi CHỈ ISO 8601 mà bạn có thể phân tích cú pháp một cách an toàn trên các trình duyệt là dạng dài có độ lệch (± HH: mm hoặc "Z"). Nếu bạn làm điều đó, bạn có thể quay lại một cách an toàn giữa giờ địa phương và giờ UTC.

Điều này hoạt động trên các trình duyệt (sau IE9):

console.log(new Date(Date.parse("2005-07-08T00:00:00Z")).toString());

Hầu hết các trình duyệt hiện tại đều đối xử bình đẳng với các định dạng đầu vào khác, bao gồm '1/1/1970' (M / D / YYYY) và '1/1/1970 00:00:00 AM' (M / D / YYYY hh : mm: ss ap) định dạng. Tất cả các định dạng sau (ngoại trừ định dạng cuối cùng) được coi là đầu vào thời gian cục bộ trong tất cả các trình duyệt. Đầu ra của mã này giống nhau trong tất cả các trình duyệt trong múi giờ của tôi. Cái cuối cùng được coi là -05: 00 bất kể múi giờ của máy chủ vì phần bù được đặt trong dấu thời gian:

console.log(Date.parse("1/1/1970"));
console.log(Date.parse("1/1/1970 12:00:00 AM"));
console.log(Date.parse("Thu Jan 01 1970"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00 GMT-0500"));

Tuy nhiên, do việc phân tích cú pháp ngay cả các định dạng được chỉ định trong ECMA-262 là không nhất quán, nên không bao giờ dựa vào bộ dữ liệu được xây dựng trong trình phân tích cú pháp và luôn luôn phân tích chuỗi theo cách thủ công, sử dụng thư viện và cung cấp định dạng cho trình phân tích cú pháp.

Ví dụ: trong khoảnh khắc.js bạn có thể viết:

let m = moment('1/1/1970', 'M/D/YYYY'); 

Phía đầu ra

Về phía đầu ra, tất cả các trình duyệt dịch các múi giờ theo cùng một cách nhưng chúng xử lý các định dạng chuỗi khác nhau. Dưới đây là các toStringchức năng và những gì họ đầu ra. Lưu ý toUTCStringtoISOString chức năng đầu ra 5:00 AM trên máy của tôi. Ngoài ra, tên múi giờ có thể là viết tắt và có thể khác nhau trong các triển khai khác nhau.

Chuyển đổi từ UTC sang Giờ địa phương trước khi in

 - toString
 - toDateString
 - toTimeString
 - toLocaleString
 - toLocaleDateString
 - toLocaleTimeString

In trực tiếp thời gian UTC được lưu trữ

 - toUTCString
 - toISOString 

Trong Chrome
toString            Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString        Thu Jan 01 1970
toTimeString        00:00:00 GMT-05:00 (Eastern Standard Time)
toLocaleString      1/1/1970 12:00:00 AM
toLocaleDateString  1/1/1970
toLocaleTimeString  00:00:00 AM

toUTCString         Thu, 01 Jan 1970 05:00:00 GMT
toISOString         1970-01-01T05:00:00.000Z

Trong Firefox
toString            Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString        Thu Jan 01 1970
toTimeString        00:00:00 GMT-0500 (Eastern Standard Time)
toLocaleString      Thursday, January 01, 1970 12:00:00 AM
toLocaleDateString  Thursday, January 01, 1970
toLocaleTimeString  12:00:00 AM

toUTCString         Thu, 01 Jan 1970 05:00:00 GMT
toISOString         1970-01-01T05:00:00.000Z

Tôi thường không sử dụng định dạng ISO cho đầu vào chuỗi. Thời gian duy nhất sử dụng định dạng đó có lợi cho tôi là khi ngày cần được sắp xếp thành chuỗi. Định dạng ISO có thể sắp xếp như hiện tại trong khi các định dạng khác thì không. Nếu bạn phải có khả năng tương thích giữa nhiều trình duyệt, hãy chỉ định múi giờ hoặc sử dụng định dạng chuỗi tương thích.

new Date('12/4/2013').toString()đi qua chuyển đổi giả nội bộ sau đây:

  "12/4/2013" -> toUCT -> [storage] -> toLocal -> print "12/4/2013"

Tôi hy vọng câu trả lời này có ích.


3
Trước hết, đây là một bài viết tuyệt vời. Tôi muốn chỉ ra một phụ thuộc, tuy nhiên. Liên quan đến các công cụ xác định múi giờ, bạn tuyên bố: "Việc không có công cụ xác định nên đoán trước thời gian địa phương." Rất may, tiêu chuẩn ECMA-262 loại bỏ mọi nhu cầu giả định. Nó tuyên bố : "Giá trị của phần bù múi giờ vắng mặt là của Z Z." Vì vậy, chuỗi ngày / giờ không có múi giờ được chỉ định được coi là UTC thay vì giờ địa phương. Tất nhiên, cũng như rất nhiều thứ JavaScript, dường như có rất ít sự thỏa thuận giữa các lần triển khai.
Daniel

2
... bao gồm các định dạng '1/1/1970' và '1/1/1970 00:00:00 AM' được sử dụng thường xuyên nhất. - Sử dụng thường xuyên nhất ở đâu ? Đó không phải là ở đất nước của tôi, chắc chắn.
ulidtko

2
@ulidtko - Xin lỗi, tôi đang ở Mỹ. Wow ... bạn đang ở ngay tại Kiev. Tôi hy vọng rằng bạn và gia đình của bạn được an toàn và mọi thứ sẽ ổn định ở đó sớm. Hãy chăm sóc bản thân và may mắn với mọi thứ.
drankin2112

Chỉ cần một lưu ý ở đây. Có vẻ như điều này không hoạt động đối với các trình duyệt Safari (tức là iOS hoặc OSX). Điều đó hoặc tôi có một số vấn đề khác đang diễn ra.
keyneom

1
@ Daniel, may mắn thay, các tác giả ECMAScript đã sửa lỗi của họ liên quan đến việc mất múi giờ cho các biểu diễn ngày và thời gian. Bây giờ các chuỗi ngày và thời gian không có múi giờ sử dụng phần bù múi giờ của máy chủ (tức là "cục bộ"). Thật khó hiểu, các biểu mẫu chỉ ngày ISO 8601 được coi là UTC (mặc dù nó không đặc biệt rõ ràng với thông số kỹ thuật), trong khi ISO 8601 coi chúng là cục bộ, vì vậy chúng không khắc phục được mọi thứ.
Cướp

70

Có một số phương pháp cho sự điên rồ. Theo nguyên tắc chung, nếu một trình duyệt có thể hiểu ngày là ISO-8601, thì nó sẽ. "2005-07-08" rơi vào trại này, và do đó nó được phân tích thành UTC. "Ngày 8 tháng 7 năm 2005" không thể, và do đó, nó được phân tích cú pháp theo giờ địa phương.

Xem JavaScript và ngày, Thật là một mớ hỗn độn! để biết thêm


3
" Theo nguyên tắc chung, nếu một trình duyệt có thể hiểu ngày là ISO-8601, thì nó sẽ không hỗ trợ." "2020-03-20 13:30:30" được coi là ISO 8601 và cục bộ bởi nhiều trình duyệt, nhưng Ngày không hợp lệ của Safari. Có nhiều định dạng ISO 8601 không được hầu hết các trình duyệt hỗ trợ, ví dụ 2004-W53-7 và 2020-092.
RobG

7

Một giải pháp khác là xây dựng một mảng kết hợp với định dạng ngày và sau đó định dạng lại dữ liệu.

Phương pháp này hữu ích cho ngày được định dạng theo cách không phổ biến.

Một ví dụ:

    mydate='01.02.12 10:20:43':
    myformat='dd/mm/yy HH:MM:ss';


    dtsplit=mydate.split(/[\/ .:]/);
    dfsplit=myformat.split(/[\/ .:]/);

    // creates assoc array for date
    df = new Array();
    for(dc=0;dc<6;dc++) {
            df[dfsplit[dc]]=dtsplit[dc];
            }

    // uses assc array for standard mysql format
    dstring[r] = '20'+df['yy']+'-'+df['mm']+'-'+df['dd'];
    dstring[r] += ' '+df['HH']+':'+df['MM']+':'+df['ss'];

5

Sử dụng khoảnh khắc.js để phân tích ngày tháng:

var caseOne = moment("Jul 8, 2005", "MMM D, YYYY", true).toDate();
var caseTwo = moment("2005-07-08", "YYYY-MM-DD", true).toDate();

Đối số thứ 3 xác định phân tích cú pháp nghiêm ngặt (có sẵn kể từ 2.3.0). Không có nó khoảnh khắc.js cũng có thể cho kết quả không chính xác.


4

Theo http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html định dạng "yyyy / mm / dd" giải quyết các vấn đề thông thường. Ông nói: "Bám sát" YYYY / MM / DD "cho chuỗi ngày của bạn bất cứ khi nào có thể. Nó được hỗ trợ toàn cầu và không mơ hồ. Với định dạng này, tất cả thời gian là cục bộ." Tôi đã đặt thử nghiệm: http://jsfiddle.net/jlanus/ND2Qg/432/ Định dạng này: + tránh sự mơ hồ về thứ tự ngày và tháng bằng cách sử dụng đơn đặt hàng ymd và năm 4 chữ số + tránh UTC so với vấn đề cục bộ không tuân thủ định dạng ISO bằng cách sử dụng dấu gạch chéo + danvk, anh chàng thợ nhuộm , nói rằng định dạng này tốt trong tất cả các trình duyệt.


Bạn có thể muốn xem câu trả lời của tác giả .
Brad Koch

Tôi muốn nói rằng giải pháp với ví dụ trong jsFiddle hoạt động đủ tốt nếu bạn sử dụng jQuery vì nó sử dụng trình phân tích cú pháp datepicker. Trong trường hợp của tôi, vấn đề là với jqGrid, nhưng thấy nó có phương thức parseDate. Nhưng dù sao thì ví dụ này đã giúp tôi bằng cách cho tôi một ý tưởng +1 cho nó, cảm ơn.
Vasil Popov

2
Bài viết đó trên máy in là sai và ví dụ đầu tiên trên trang minh họa rõ ràng lý do tại sao sử dụng dấu gạch chéo thay cho dấu gạch nối là lời khuyên thực sự tồi. Tại thời điểm bài viết được viết, sử dụng "2012/03/13" dẫn đến trình duyệt phân tích cú pháp dưới dạng ngày cục bộ, thay vì UTC. Đặc tả ECMAScript xác định hỗ trợ rõ ràng cho việc sử dụng "YYYY-MM-DD" (ISO8601), vì vậy luôn luôn sử dụng dấu gạch nối. Cần lưu ý rằng tại thời điểm tôi viết nhận xét này, Chrome đã được vá để coi dấu gạch chéo là UTC.
Lachlan Hunt

4

Mặc dù CMS chính xác rằng việc chuyển các chuỗi vào phương thức phân tích thường không an toàn, nhưng đặc tả ECMA-262 5 Edition (hay còn gọi là ES5) mới trong phần 15.9.4.2 cho thấy rằng Date.parse()thực sự nên xử lý các ngày có định dạng ISO. Các đặc điểm kỹ thuật cũ không đưa ra yêu cầu như vậy. Tất nhiên, các trình duyệt cũ và một số trình duyệt hiện tại vẫn không cung cấp chức năng ES5 này.

Ví dụ thứ hai của bạn không sai. Đó là ngày được chỉ định trong UTC, theo ngụ ý của Date.prototype.toISOString(), nhưng được thể hiện trong múi giờ địa phương của bạn.


1
Và việc phân tích chuỗi ngày đã được thay đổi một lần nữa trong ECMAScript 2015 để "2005-07-08" là cục bộ, không phải UTC. BTW, ES5 không phải là tiêu chuẩn cho đến tháng 6 năm 2011 (và hiện tại ECMAScript 2015 là). ;-)
RobG

1
Chỉ để gây bối rối, TC39 đã quyết định tháng 10 (chỉ một tháng sau bài viết trước của tôi) rằng "2005-07-08" phải là UTC , tuy nhiên "" 2005-07-08T00: 00: 00 "phải là cục bộ. Cả hai đều là ISO 8601 các định dạng tuân thủ, cả hai đều không có múi giờ, nhưng được xử lý khác nhau. Hãy xem
RobG

2

Thư viện phân tích ngày trọng lượng nhẹ này sẽ giải quyết tất cả các vấn đề tương tự. Tôi thích thư viện vì nó khá dễ dàng để mở rộng. Cũng có thể i18n nó (không quá thẳng về phía trước, nhưng không khó lắm).

Ví dụ phân tích cú pháp:

var caseOne = Date.parseDate("Jul 8, 2005", "M d, Y");
var caseTwo = Date.parseDate("2005-07-08", "Y-m-d");

Và định dạng trở lại chuỗi (bạn sẽ thấy cả hai trường hợp đều cho kết quả chính xác như nhau):

console.log( caseOne.dateFormat("M d, Y") );
console.log( caseTwo.dateFormat("M d, Y") );
console.log( caseOne.dateFormat("Y-m-d") );
console.log( caseTwo.dateFormat("Y-m-d") );

2

Dưới đây là đoạn mã ngắn, linh hoạt để chuyển đổi chuỗi thời gian theo kiểu an toàn trên nhiều trình duyệt như nicel chi tiết bởi @ drankin2112.

var inputTimestamp = "2014-04-29 13:00:15"; //example

var partsTimestamp = inputTimestamp.split(/[ \/:-]/g);
if(partsTimestamp.length < 6) {
    partsTimestamp = partsTimestamp.concat(['00', '00', '00'].slice(0, 6 - partsTimestamp.length));
}
//if your string-format is something like '7/02/2014'...
//use: var tstring = partsTimestamp.slice(0, 3).reverse().join('-');
var tstring = partsTimestamp.slice(0, 3).join('-');
tstring += 'T' + partsTimestamp.slice(3).join(':') + 'Z'; //configure as needed
var timestamp = Date.parse(tstring);

Trình duyệt của bạn sẽ cung cấp kết quả dấu thời gian giống như Date.parsevới:

(new Date(tstring)).getTime()

Tôi cũng khuyên bạn nên thêm T vào biểu thức chính quy để bắt được các ngày đã được định dạng JS: inputTimestamp.split (/ [T \ /: -] / g)
andig

Nếu bạn chia chuỗi thành các phần thành phần, thì bước tiếp theo đáng tin cậy nhất là sử dụng các phần đó làm đối số cho hàm tạo Ngày. Tạo một chuỗi khác để cung cấp cho trình phân tích cú pháp chỉ giúp bạn quay lại bước 1. "2014-04-29 13:00:15" nên được phân tích cú pháp thành cục bộ, mã của bạn định dạng lại thành UTC. :-(
RobG

2

Cả hai đều đúng, nhưng chúng đang được hiểu là ngày với hai múi giờ khác nhau. Vì vậy, bạn so sánh táo và cam:

// local dates
new Date("Jul 8, 2005").toISOString()            // "2005-07-08T07:00:00.000Z"
new Date("2005-07-08T00:00-07:00").toISOString() // "2005-07-08T07:00:00.000Z"
// UTC dates
new Date("Jul 8, 2005 UTC").toISOString()        // "2005-07-08T00:00:00.000Z"
new Date("2005-07-08").toISOString()             // "2005-07-08T00:00:00.000Z"

Tôi đã xóa Date.parse()cuộc gọi vì nó được sử dụng tự động trên một đối số chuỗi. Tôi cũng đã so sánh các ngày sử dụng định dạng ISO8601 để bạn có thể so sánh trực quan các ngày giữa ngày địa phương của bạn và ngày UTC. Thời gian cách nhau 7 giờ, đó là chênh lệch múi giờ và tại sao các thử nghiệm của bạn cho thấy hai ngày khác nhau.

Cách khác để tạo các ngày địa phương / UTC tương tự sẽ là:

new Date(2005, 7-1, 8)           // "2005-07-08T07:00:00.000Z"
new Date(Date.UTC(2005, 7-1, 8)) // "2005-07-08T00:00:00.000Z"

Nhưng tôi vẫn khuyến nghị mạnh mẽ cho Moment.js , đơn giản nhưng mạnh mẽ :

// parse string
moment("2005-07-08").format()       // "2005-07-08T00:00:00+02:00"
moment.utc("2005-07-08").format()   // "2005-07-08T00:00:00Z"
// year, month, day, etc.
moment([2005, 7-1, 8]).format()     // "2005-07-08T00:00:00+02:00"
moment.utc([2005, 7-1, 8]).format() // "2005-07-08T00:00:00Z"

0

Các câu trả lời được chấp nhận từ CMS là đúng, tôi đã chỉ cần thêm một số tính năng:

  • cắt và làm sạch không gian đầu vào
  • dấu gạch chéo, dấu gạch ngang, dấu hai chấm và dấu cách
  • có ngày và giờ mặc định

// parse a date time that can contains spaces, dashes, slashes, colons
function parseDate(input) {
    // trimes and remove multiple spaces and split by expected characters
    var parts = input.trim().replace(/ +(?= )/g,'').split(/[\s-\/:]/)
    // new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
    return new Date(parts[0], parts[1]-1, parts[2] || 1, parts[3] || 0, parts[4] || 0, parts[5] || 0); // Note: months are 0-based
}
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.