New Date()可以在 Chrome 中使用,但不能在 Firefox 中使用

我正在创建一个日期时间字符串,如下所示: 2010-07-15 11:54:21

通过下面的代码,我在 Firefox 中得到了无效的日期,但是在 Chrome 中工作得很好

var todayDateTime = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + seconds;
var date1 = new Date(todayDateTime);

在 firefox date1给我一个无效的日期,但在 chrome 中它的工作正常,主要原因是什么?

134614 次浏览

You can't instantiate a date object any way you want. It has to be in a specific way. Here are some valid examples:

new Date() // current date and time
new Date(milliseconds) //milliseconds since 1970/01/01
new Date(dateString)
new Date(year, month, day, hours, minutes, seconds, milliseconds)

or

d1 = new Date("October 13, 1975 11:13:00")
d2 = new Date(79,5,24)
d3 = new Date(79,5,24,11,33,0)

Chrome must just be more flexible.

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

From apsillers comment:

the EMCAScript specification requires exactly one date format (i.e., YYYY-MM-DDTHH:mm:ss.sssZ) but custom date formats may be freely supported by an implementation: "If the String does not conform to that [ECMAScript-defined] format the function may fall back to any implementation-specific heuristics or implementation-specific date formats." Chrome and FF simply have different "implementation-specific date formats."

This works in all browsers -

new Date('2001/01/31 12:00:00 AM')

new Date('2001-01-31 12:00:00')

Format: YYYY-MM-DDTHH:mm:ss.sss

Details: http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15

This should work for you:

var date1 = new Date(year, month, day, hour, minute, seconds);

I had to create date form a string so I have done it like this:

var d = '2013-07-20 16:57:27';
var date1 = new Date(d.substr(0, 4), d.substr(5, 2), d.substr(8, 2), d.substr(11, 2), d.substr(14, 2), d.substr(17, 2));

Remember that the months in javascript are from 0 to 11, so you should reduce the month value by 1, like this:

var d = '2013-07-20 16:57:27';
var date1 = new Date(d.substr(0, 4), d.substr(5, 2) - 1, d.substr(8, 2), d.substr(11, 2), d.substr(14, 2), d.substr(17, 2));

If you still want to create date using dashes, you can use this format:

var date = new Date('2013-08-31T17:00:00Z')

But bear in mind, that it creates time according to UTC. Meaning, if you live in GMT+3 (3 hours ahead of GMT) timezone, it will add this timezone offset to the time. So the above example will have this value, if GMT+3 (note that it is hour 20:00 and not 17:00):

Sat Aug 31 2013 20:00:00 GMT+0300 (FLE Standard Time)

Be sure to add 'Z' letter at the end, because otherwise Chrome and Firefox will parse the string differently (one will add time offset and the other won't).

This works in most browsers as well

new Date('2001/01/31 12:00:00')

That is the format of

"yyyy/MM/dd HH:mm:ss"

I was having a similar issue in both Firefox and Safari when working with AngularJS. For example, if a date returned from Angular looked like this:

2014-06-02 10:28:00

using this code:

new Date('2014-06-02 10:28:00').toISOString();

returns an invalid date error in Firefox and Safari. However in Chrome it works fine. As another answer stated, Chrome is most likely just more flexible with parsing date strings.

My eventual goal was to format the date a certain way. I found an excellent library that handled both the cross browser compatibility issue and the date formatting issue. The library is called moment.js.

Using this library the following code works correctly across all browsers I tested:

moment('2014-06-02 10:28:00').format('MMM d YY')

If you are willing to include this extra library into your app you can more easily build your date string while avoiding possible browser compatibility issues. As a bonus you will have a good way to easily format, add, subtract, etc dates if needed.

In Firefox, any invalid Date is returned as a Date object as Date 1899-11-29T19:00:00.000Z, therefore check if browser is Firefox then get Date object of string "1899-11-29T19:00:00.000Z".getDate(). Finally compare it with the date.

One situation I've run into was when dealing with milliseconds. FF and IE will not parse this date string correctly when trying to create a new date. "2014/11/24 17:38:20.177Z" They do not know how to handle .177Z. Chrome will work though.

In fact, Chrome is more flexible to deal with different string format. Even if you don't figure out its String format, Chrome still can successfully convert String to Date without error. Like this:

  var outputDate = new Date(Date.parse(inputString));

But for Firefox and Safari, things become more complex. In fact, in Firefox's document, it already says: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse)

A string representing an RFC2822 or ISO 8601 date (other formats may be used, but results may be unexpected).

So, when you want to use Date.parse in Firefox and Safari, you should be careful. For me, I use a trick method to deal with it. (Note: it might be not always correct for all cases)

if (input.indexOf("UTC") != -1) {
var tempInput = inputString.substr(0, 10) + "T" + inputString.substr(11, 8) + "Z";
date = new Date(Date.parse(tempInput));
}

Here it converts 2013-08-08 11:52:18 UTC to 2013-08-08T11:52:18Z first, and then its format is fit words in Firefox's document. At this time, Date.parse will be always right in any browser.

I have used following date format and it's working in all browser.

var target_date = new Date("Jul 17, 2015 16:55:22").getTime();


var days, hours, minutes, seconds;


var countdown = document.getElementById("countdown");


remaining = setInterval(function () {


var current_date = new Date().getTime();
var seconds_left = (target_date - current_date) / 1000;
days = parseInt(seconds_left / 86400);
seconds_left = seconds_left % 86400;
hours = parseInt(seconds_left / 3600);
seconds_left = seconds_left % 3600;
minutes = parseInt(seconds_left / 60);
seconds = parseInt(seconds_left % 60);
countdown.innerHTML = "<b>"+days + " day, " + hours + " hour, "
+ minutes + " minute, " + seconds + " second.</b>";
}, 1000);

Option 1 :

Suppose your timestring has a format that looks like this :

'2016-03-10 16:00:00.0'

In that case, you could do a simple regex to convert it to ISO 8601 :

'2016-03-10 16:00:00.0'.replace(/ /g,'T')

This would procude the following output :

'2016-03-10T16:00:00.0'

This is the standard datetime format, and thus supported by all browsers :

document.body.innerHTML = new Date('2016-03-10T16:00:00.0') // THIS IS SAFE TO USE

Option 2 :

Suppose your timestring has a format that looks like this :

'02-24-2015 09:22:21 PM'

Here, you can do the following regex :

'02-24-2015 09:22:21 PM'.replace(/-/g,'/');

This, too, produces a format supported by all browsers :

document.body.innerHTML = new Date('02/24/2015 09:22:21 PM') // THIS IS SAFE TO USE

Option 3 :

Suppose you have a time string that isn't easy to adjust to one of the well-supported standards.

In that case, it's best to just split your time string into different pieces and use them as individual parameters for Date :

document.body.innerHTML = new Date(2016, 2, 26, 3, 24, 0); // THIS IS SAFE TO USE

Simple Solution, This works with All Browsers,

var StringDate = "24-11-2017"
var DateVar = StringDate.split("-");
var DateVal = new Date(DateVar[1] + "/" + DateVar[0] + "/" + DateVar[2]);
alert(DateVal);

This is what worked for me on Firefox and Chrome:

// The format is 'year-month-date hr:mins:seconds.milliseconds'
const d = new Date('2020-1-4 12:00:00.999')
// we use the `.` separator between seconds and milliseconds.

Good Luck...

There is a W3C specification defining possible date strings that should be parseable by any browser (including Firefox and Safari):

Year:
YYYY (e.g., 1997)
Year and month:
YYYY-MM (e.g., 1997-07)
Complete date:
YYYY-MM-DD (e.g., 1997-07-16)
Complete date plus hours and minutes:
YYYY-MM-DDThh:mmTZD (e.g., 1997-07-16T19:20+01:00)
Complete date plus hours, minutes and seconds:
YYYY-MM-DDThh:mm:ssTZD (e.g., 1997-07-16T19:20:30+01:00)
Complete date plus hours, minutes, seconds and a decimal fraction of a
second
YYYY-MM-DDThh:mm:ss.sTZD (e.g., 1997-07-16T19:20:30.45+01:00)

where

YYYY = four-digit year
MM   = two-digit month (01=January, etc.)
DD   = two-digit day of month (01 through 31)
hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
mm   = two digits of minute (00 through 59)
ss   = two digits of second (00 through 59)
s    = one or more digits representing a decimal fraction of a second
TZD  = time zone designator (Z or +hh:mm or -hh:mm)

According to YYYY-MM-DDThh:mmTZD, the example 2010-07-15 11:54:21 has to be converted to either 2010-07-15T11:54:21Z or 2010-07-15T11:54:21+02:00 (or with any other timezone).

Here is a short example showing the results of each variant:

const oldDateString = '2010-07-15 11:54:21'
const newDateStringWithoutTZD = '2010-07-15T11:54:21Z'
const newDateStringWithTZD = '2010-07-15T11:54:21+02:00'
document.getElementById('oldDateString').innerHTML = (new Date(oldDateString)).toString()
document.getElementById('newDateStringWithoutTZD').innerHTML = (new Date(newDateStringWithoutTZD)).toString()
document.getElementById('newDateStringWithTZD').innerHTML = (new Date(newDateStringWithTZD)).toString()
div {
padding: 10px;
}
<div>
<strong>Old Date String</strong>
<br>
<span id="oldDateString"></span>
</div>
<div>
<strong>New Date String (without Timezone)</strong>
<br>
<span id="newDateStringWithoutTZD"></span>
</div>
<div>
<strong>New Date String (with Timezone)</strong>
<br>
<span id="newDateStringWithTZD"></span>
</div>