JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse
I had this issue today. I found momentjs was a good way of parsing ISO 8601 dates in a cross browser manor.
momentjs can also be used to output the date in a different format.
Is `new Date(string)` reliable in modern browsers, assuming the input is a full ISO 8601 string?
Yes. The format of acceptable Date strings in JavaScript is standardized:
ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 calendar date extended format. The format is as follows:
YYYY-MM-DDTHH:mm:ss.sssZ
From ECMAScript current draft under the section heading " Date Time String Format".
This is the only standard for parsing date strings presented in the spec and hence the aim of date libraries will be to format dates into this format before calling new Date
or Date.parse
. I can't comment on what the "simplification" of the ISO standard is, but the format asked about in the post matches that of the [ECMAScript] standard.
Note the standard continues on to state date only forms
YYYY
YYYY-MM
YYYY-MM-DD
are accepted and that time formats, optionally followed by a UTC offset, of
THH:mm
THH:mm:ss
THH:mm:ss.sss
may be used following the date component.
Parsing ISO 8601 date in Javascript
datejs could parse following, you might want to try out.
Date.parse('1997-07-16T19:20:15') // ISO 8601 Formats
Date.parse('1997-07-16T19:20:30+01:00') // ISO 8601 with Timezone offset
Edit: Regex version
x = "2011-01-28T19:30:00EST"
MM = ["January", "February","March","April","May","June","July","August","September","October","November", "December"]
xx = x.replace(
/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):\d{2}(\w{3})/,
function($0,$1,$2,$3,$4,$5,$6){
return MM[$2-1]+" "+$3+", "+$1+" - "+$4%12+":"+$5+(+$4>12?"PM":"AM")+" "+$6
}
)
Result
January 28, 2011 - 7:30PM EST
Edit2: I changed my timezone to EST and now I got following
x = "2011-01-28T19:30:00-05:00"
MM = {Jan:"January", Feb:"February", Mar:"March", Apr:"April", May:"May", Jun:"June", Jul:"July", Aug:"August", Sep:"September", Oct:"October", Nov:"November", Dec:"December"}
xx = String(new Date(x)).replace(
/\w{3} (\w{3}) (\d{2}) (\d{4}) (\d{2}):(\d{2}):[^(]+\(([A-Z]{3})\)/,
function($0,$1,$2,$3,$4,$5,$6){
return MM[$1]+" "+$2+", "+$3+" - "+$4%12+":"+$5+(+$4>12?"PM":"AM")+" "+$6
}
)
return
January 28, 2011 - 7:30PM EST
Basically
String(new Date(x))
return
Fri Jan 28 2011 19:30:00 GMT-0500 (EST)
regex parts just converting above string to your required format.
January 28, 2011 - 7:30PM EST
javascript date.parse difference in chrome and other browsers
Here is a fix for Firefox and IE/Safari (with the help from JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse
) :
DEMO
var noOffset = function(s) {
var day= s.slice(0,-5).split(/\D/).map(function(itm){
return parseInt(itm, 10) || 0;
});
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
var offsetString = s.slice(-5)
var offset = parseInt(offsetString,10)/100;
if (offsetString.slice(0,1)=="+") offset*=-1;
day.setHours(day.getHours()+offset);
return day.getTime();
}
From MDN
JavaScript 1.8.5 note
A subset of ISO 8601 formatted date strings can now also be parsed.
Alternatively, the date/time string may be in ISO 8601 format. Starting with JavaScript 1.8.5 / Firefox 4, a subset of ISO 8601 is supported. For example, "2011-10-10" (just date) or "2011-10-10T14:48:00 (date and time) can be passed and parsed. Timezones in ISO dates are not yet supported, so e.g. "2011-10-10T14:48:00+0200" (with timezone) does not give the intended result yet.
JavaScript ISO 8601 string into Date object
The
2014-03-03T...
notation is a fancy JavaScript Date Time String Format and expects a time zone. If you don't provide one, it defaults toZ
(UTC).The
2014-03-03 18:30:00
notation, however, is just a regular string without an interesting name and, if you don't provide a time zone, it assumes local time.
This info was taken from the MDN article about Date.parse()
.
Does Javascript/EcmaScript3 support ISO8601 date parsing?
Try this: http://anentropic.wordpress.com/2009/06/25/javascript-iso8601-parser-and-pretty-dates/
Date parsing in javascript is different between safari and chrome
You can't really use Date.parse. I suggest you use: new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )
To split the string you could try
var s = '2011-06-21T14:27:28.593Z';
var a = s.split(/[^0-9]/);
//for (i=0;i<a.length;i++) { alert(a[i]); }
var d=new Date (a[0],a[1]-1,a[2],a[3],a[4],a[5] );
alert(s+ " "+d);
Chrome 66: Date.parse() gives unexpected results for invalid ISO 8601 dates
The JavaScript Date
object is happy to handle unit rollover for you, that's all that's going on with the 2018-06-31
example — it's handling the rollover from June 30th to July 1st.
It doesn't do that for the 2018-06-32
example because 32
is an invalid value for the days field (whereas 31 isn't, it's just that June only has 30 days). The spec defines the valid ranges for the parts of the date/time string here, where we can see it says the valid values for the day of the month are 01 to 31 inclusive.
It's probably worth noting that the parsing of that ISO-8601-derived format (it isn't ISO-8601, quite) if you don't include a timezone indicator has a checkered history, sadly. ES5 specified ISO-8601 but got the meaning of the absense of a timezone indicator wrong (it said it should mean UTC, but ISO-8601 says it means local time); then ES2015 tried to fix that, but conforming to ES2016's rules would have broken a substantial amount of real-world code; and so it wasn't stabilized until ES2016, which says: Date-only forms (like yours) without a timezone indicator are UTC, date/time forms without one are local time. (It's been fine for years if you do include a timezone indicator.)
How to parse dates correctly in Javascript?
Here's the explanation from the Date documentation:
Note: parsing of date strings with the Date constructor (and Date.parse, they are equivalent) is strongly discouraged due to browser differences and inconsistencies. Support for RFC 2822 format strings is by convention only. Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
The parsing happens correctly, but in the second example, the time is treated as UTC, which then turns in Dec 28th in your local time zone.
More infos:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
ECMAScript 5 Date.parse results for ISO 8601 test cases
According to the ES5 spec, Date.parse will only work with valid ISO 8601 dates. Anything else is implementation dependent (in practice, IE < 9 doesn't work with standard ISO dates, it requires a '/' seperator). So if you feed it an invalid date (such as 2012-11-31) you can get anythying, from 2012-12-01 to an error.
In your tests:
2012-12-31T23:59:60.000Z
should work, though probably not as you expect. Using 60 for seconds indicates a leap second, it isn't equivalent to 24:00:00, only Safari seems to get that right.
Also:
2012-04-04T24:00:00.000Z
should work, it indicates midnight at the end of 4 April, 2012 so Firefox is in error there.
The formats that ES5 implementations should support are in the spec.
Oh, and you should probably also test omission of the 'T' (since it is optional in certain cases that I think include browsers) and different time zones such as:
2012-04-03 23:50:00+10:00
2012-04-03 23:50:00-04:15
2012-04-03 23:50:00+10
20120403T235000+1000
and so on with YYYYDDD and YYYYWwwD formats, though implementations aren't required to support them.
Related Topics
How to Add Conditional Attribute in Angular 2
Remove Items from Array with Splice in for Loop
Setting Query String Using Fetch Get Request
What Is Returned from a Constructor
Coordinating Parallel Execution in Node.Js
How to Get the Destination Url for the Onbeforeunload Event
Make Browser Window Blink in Task Bar
Accessing Variables from Greasemonkey to Page & Vice Versa
How to Delay a Function Call for 5 Seconds
Force Download Through Js or Query
(![]+[])[+[]]... Explain Why This Works
Invalid Hook Call. Hooks Can Only Be Called Inside of the Body of a Function Component
What's the Recommended Way to Extend Angularjs Controllers
Create Svg Tag with JavaScript
Angularjs 1.2 $Injector:Modulerr
Vanilla JavaScript Event Delegation