I have done quite a bit to make sure the date my date picker creates is compatible for being converted into a javascript Date object. I followed the advice on this stack overflow entry: Invalid date in safari and removed dashes from the string using: new Date('24-August-2016 12:44 AM'.replace(/-/g, "/")); That made things compatible with every other operating system and browser, except browsers on a Mac. It still seems safari does not like the full month name in the string. What is the recommended approach to getting safari to recognize the string as a date if I am forced to use that format?
-
Do not parse strings with the Date constructor (or Date.parse), they are almost entirely implementation dependent and inconsistent across browsers. Manually parse strings, a library can help but a small function is normally all that is required. – RobG Jun 17 '16 at 02:32
3 Answers
Read the documentation about Date()
:
new Date(dateString)
String value representing a date. The string should be in a format recognized by the Date.parse() method (IETF-compliant RFC 2822 timestamps and also a version of ISO8601).
Also note the following which means that you have to be extra-careful when doing this.
Note: parsing of date strings with the Date constructor (and Date.parse, they are equivalent) is strongly discouraged due to browser differences and inconsistencies.
See the documentation of Date.parse
where it clearly states which date formats are accepted:
A string representing an RFC2822 or ISO 8601 date (other formats may be used, but results may be unexpected).
The format you try to parse is neither of the supported ones and you have to expect different behaviours in different browsers.
Personally, I always use dates in the ISO 8601 format (e.g. 2016-06-16T06:15:24.040Z
). Using such a standard also supports adding a timezone which is crucial in multi-timezone applications.
Oh and by the way: It is generally a bad idea to add localized date strings to a JavaScript method. The user's browser might use another language than English which, in addition of the strange date format, may also cause further problems.
-
Note that MDN is primarily documentation for JavaScript, which is Mozilla's implementation of ECMAScript and is not necessarily applicable to all browsers in use. Far better to reference the language specification, which only specifies ISO 8601 (and has changed support in each of the last 4 versions). – RobG Jun 17 '16 at 02:36
-
@RobG the question is referring to a browser implementation, specifically webkit. When talking about real world problems I would argue that it is much better to reference Javascript docs such as MDN (which reference implementations) rather than the specs which make no reference to the status of features. Also to be clear MDN covers all major browser implementations, not just Mozilla's. – som Jun 17 '16 at 06:12
-
@som—MDN is a public wiki that anyone can contribute to. While it's very useful, it's not the language specification. The OP's issue is with a browser not listed in the MDN compatibility section (there are no mobile browsers listed at all), so proof that relying on non–standard behaviour is a bad idea. – RobG Jun 19 '16 at 23:43
-
@RobG the OP's issue was with a browser, not the language itself (specifically Safari on OSX, not mobile). Regardless MDN does list mobile browser support - you need to click the mobile tab at the top of the compatibility table. To be clear the spec has no reference to compatibility at all, rendering it somewhat useless for debugging problems specific to a browser. – som Jun 20 '16 at 00:18
-
@som—the specification doesn't mention implementations because it's the standard. It specifically states that it does not specify implementation. Following the standard seems a good first step. – RobG Jun 20 '16 at 01:28
-
@RobG again I have to disagree. Developers work with browsers implementing a spec, not the spec itself. I do agree that it's worthwhile having some knowledge of what's included, but as far as using it as a first step? Most browsers don't even implement all of ES5, let alone anything newer. Many browsers include non-standard features. IMO an implementation and compatibility guide is infinitely more useful than any spec. Check out http://kangax.github.io/compat-table/es5/ – som Jun 20 '16 at 02:12
-
Using the string you're suggesting completely ignores the bit in ECMA-262 that says "anything other than ISO 8601 is implementation dependent" and the evidence in the OP that non–standard strings are not treated equally in all browsers. Do it if you want, but it is bad advice. It is extremely simple to write a small function or parser that is 100% compliant with the ECMA-262 and works in every browser past, present and future. Or do you like constant maintenance for every new implementation that surfaces? – RobG Jun 20 '16 at 02:43
-
@RobG the solution doesn't ignore 'the bit', it embraces it. Fit for purpose is the name of the game here. – som Jun 20 '16 at 03:48
I up voted both answers. I chose yours (som) as the accepted answer because it provides a solution. I went with solving the problem with moment.js. moment.js is able to take the string as is and return a valid date object. I ended up with something like this:
if (typeof service.trade.onlineEndTime == 'string'){
if(!moment(service.trade.onlineEndTime, moment.ISO_8601, true).isValid()){
service.trade.onlineEndTime = service.trade.onlineEndTime.replace(/-/g,'/'); // replaces all occurances of "-" with "/"
service.trade.onlineEndTime = moment(service.trade.onlineEndTime, 'DD/MMMM/YYYY hh:mm a');
}
else{
service.trade.onlineEndTime = new Date(service.trade.onlineEndTime);
}
}
if(typeof service.trade.onlineEndTime == 'number') {
service.trade.onlineEndTime = new Date(service.trade.onlineEndTime);
}

- 467
- 6
- 15
-
Using a library is a good start, but you **must** provide the format of the string to parse, otherwise you are just hoping that either moment.js or the built–in parser are able to create what appears to be a valid date from the string. – RobG Jun 17 '16 at 02:39
-
You're right. In this case, I check for a valid ISO date string. If it isn't, in my application, I know it has to be a string in the format I specify when calling moment(... on line 4. – Dean Peterson Jun 17 '16 at 03:24
Try formatting with a space instead of a dash or slash - it should work across all modern browsers (including IE and Safari):
var dateString = '24/August/2016 12:44 AM',
dateFormatted = dateString.replace(/\//g, ' '),
date = new Date( dateFormatted );
A minor gotcha:
If no timezone if specified in dateString
it will default to the user's current timezone. This may not be a problem for your use case, however if someone in Ireland runs the code above they will get a different timestamp to someone in Mexico using the same code.
// defaults to the user's timezone (in my case AEST)
console.log(date); // "Wed Aug 24 2016 00:44:00 GMT+1000 (AEST)"
You can get around this by appending a timezone:
var date = new Date( dateFormatted + ' GMT' );
// timezone is now relative to GMT
console.log(date); // "Wed Aug 24 2016 10:44:00 GMT+1000 (AEST)"

- 2,023
- 30
- 37
-
Please do not suggest parsing strings with the Date constructor, it's largely implementation dependent and neither the format in the OP or your suggested changes are consistent with the format in ECMAScript 2015 (which is not parsed consistently by browsers in use anyway). – RobG Jun 17 '16 at 02:34
-
@RobG agree you might not want to be parsing a variable format, however the above produces a consistent result across all modern browsers .. IMO it is perfectly acceptable to use a fit for purpose solution. – som Jun 17 '16 at 03:50
-
@RobG also please correct me if wrong, but ES5/6/2016 all specify/allow for a browser-specific date heuristic. So while you may not recommend it, it is both allowed and works. – som Jun 17 '16 at 04:27
-
Every version of ECMAScript allows for implementation dependent parsing, so returning an invalid date for the OP format (or your variation) is consistent with every version of the standard. Just because you tested a couple of browsers and found it "works" doesn't mean it's a good idea. There is no support for the OP format in any specification, using it is not a good idea, particularly when writing a parsing function is maybe 5 lines of code (including validation) and there are many small parser libraries available. – RobG Jun 19 '16 at 23:30
-
@RobG I'm not sure what you mean by "returning an invalid date [...] is consistent with every version of the standard". Also I haven't just tested a couple of browsers. The solution provided above works across all major browsers; i.e. Chrome, Firefox, Safari, IE9+ and Edge, across Windows, OSX, iOS and Android (I haven't tested Linux). Are you trying to say that it may stop working in the future because it doesn't follow a defined standard? – som Jun 20 '16 at 00:12
-
In ECMA-262 ed 3 and earlier, parsing a string with the Date constructor (or Date.parse, they are equivalent for parsing) was entirely implementation dependent, so returning an invalid date for **any** string was consistent with the standard. In later versions, only correctly formatted ISO 8601 extended format dates are exempt. There's no guarantee that a random string will be parsed correctly by all browsers as the OP discovered. Is it better to test in every current and future browser on every device, or use a parser that you know works everywhere? – RobG Jun 20 '16 at 01:26
-
@RobG ok cool, I understand what you're getting at but I still disagree. The spec explicitly allows for flexibility, and the provided solution currently works across all browsers. Which is to say the solution complies completely with all specs past and present. While your points are valid, whether you recommend the solution or not is an opinion, not a technical statement. As to your final point, surely you're not suggesting that there's no need to test a solution across browsers if it appears to follow the spec? – som Jun 20 '16 at 02:02
-
I am simply saying that parsing strings with a bespoke function or small library avoids all vagaries of parsing using the built–in Date. Correctly written, it's guaranteed to work in every browser past, present or future. A similar claim can't be made for strings that appear to work in some current browsers. – RobG Jun 20 '16 at 02:20
-
@RobG without the ability to use timezone shorthand in ISO8601 I can see it being quite difficult to implement a parser that properly considers offsets and daylight saving without parsing a string somewhere. Moment.js is currently at version 2.13.0 and sits at over 4000 lines of code, excluding any locale information. How's that for no maintenance? Developers should be looking to reduce complexity where possible - IMO including a 15kb library for an issue that can be resolved in 30 characters is very bad advice. – som Jun 20 '16 at 03:50