42

In a project I am working on, I need to validate a date entered into an <input type="date">

With Safari 4/5 (on Mac OSX) the Javascript fails to parse dates of the format YYYY-MM-DD, returning NaN instead of the expected epoch timestamp.

I am using the following technique to validate the field just before the form is submitted:

//value = '2010-06-21' var stamp = Date.parse(value); if (isNaN(stamp)) { //notify user } else { value = new Date(stamp).format_mysql(); } 

Where format_mysql() is a prototype function that formats the date (correctly) into MySQL Date-Time format (YYYY-MM-DD).

Replacing the -'s with /'s (YYYY/MM/DD) yields a "correct" timestamp.

I should note that the field should accept any date format, not just YYYY-MM-DD, and that though I would like to, I cannot use libraries like Date.js

How can I fix this, or is there a better way to parse/validate a date?

2
  • I have Safari 5.17, and this work fine for me (tested on iOS 5.12 aswell): when = Date.parse("2013-01-29 08:30"); Commented Jan 26, 2013 at 8:36
  • The strings accepted by the Date() constructor vary across browsers, but the safest one does seem to be YYYY/MM/DD--see dygraphs.com/date-formats.html . Commented Jul 1, 2015 at 13:42

5 Answers 5

64

The behavior of the Date.parse method is implementation dependent, on ECMAScript 5, this method can parse ISO8601 formatted dates, but I would recommend you to make the parsing manually.

Some time ago I've made a simple function, that can handle a format specifier argument:

function parseDate(input, format) { format = format || 'yyyy-mm-dd'; // default format var parts = input.match(/(\d+)/g), i = 0, fmt = {}; // extract date-part indexes from the format format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; }); return new Date(parts[fmt['yyyy']], parts[fmt['mm']]-1, parts[fmt['dd']]); } parseDate('06.21.2010', 'mm.dd.yyyy'); parseDate('21.06.2010', 'dd.mm.yyyy'); parseDate('2010/06/21', 'yyyy/mm/dd'); parseDate('2010-06-21'); 

Also you could detect the ECMAScript 5 behavior to parse ISO formatted dates, you can check if the Date.prototype.toISOString is available, e.g.:

if (typeof Date.prototype.toISOString == "function") { // ES5 ISO date parsing available } 
Sign up to request clarification or add additional context in comments.

7 Comments

+1, you beat me to it. As advice to the OP, I would consider moving away from a single input element for dates to avoid the situation where a user inputs dates in their own locale (e.g. mixing up dd and mm). Either that or use a read-only input and a date picker control.
Unless I understand wrongly, your function would only apply when I know the date format before hand, correct? @Andy E's head: Separate inputs is a good idea, and something I will look into. Thanks for the tip.
@Austin, yes, you have to know the format somehow, otherwise you will have a lot of ambiguities, e.g. "01/02/2010" vs "02/01/2010", which one January 2, and which is February 1?
@CMS how to just display dd/mm/yyyy using ur function
I found that typeof Date.prototype.toISOString == "function" returned true on Safari 5.1.2 so I had to change this check for Date.parse
|
24

Generally DD-MM-YYYY format is not support in safari.

value = 2010/06/21 ; //should work.

(or)

value = new Date('2010-06-21'.replace(/-/g, "/"));

2 Comments

Really helpful ; )
second one worked can you explain little bit
3

the field should accept any date format

You don't mean what you think you mean.

  • It's difficult to reliably distinguish between M/D/Y (US) and D/M/Y (UK). D.M.Y is more common in the UK, but by no means universal.
  • Good luck with dates before around 1600 — the Gregorian (solar) calendar was introduced in 1582, and was only (mostly universally) adopted in the 20th century (Wikipedia gives 1929). February 30 was a valid date Sweden.
  • OS X gives you a choice of 13 (!) calendars, though the default is Gregorian.

Instead, I recommend using a calendar widget. I think JQuery has one, but ICBW.

2 Comments

Well, I'm targeting a fairly small US audience, looking at dates from 2000+, and more than likely the Gregorian calendar. Yes, jQuery has a datepicker widget as part of its UI package, but I cannot use it :(. When I say "any date format" I mean "June 21, 2010", "6/21/10", "2010-06-21", etc all represent the same date.
If you mean "any vaguely common date format in the US", you probably have to write your own.
1

You can get an unambiguous date from input, but you still need to check it, so a user doesn't give you April 31.

<fieldset id= "localdate"> <select id= "monthselect" size= "1"> <option selected= "selected"> January</option> <option> February</option> <option> March</option> <option> April</option> <option> May</option> <option> June</option> <option> July</option> <option> August</option> <option> September</option> <option> October</option> <option> November</option> <option> December</option> </select> <label> Date: <input name= "inputdate" size= "2" value= "1"> </label> <label> Year: <input name= "inputyear" size= "4" value= "2010"> </label> </fieldset> 

shortcut for document.getElementsByName

function byName(s, n){ n= n || 0; return document.getElementsByName(s)[n]; }

function getDateInput(){ var day, y= parseInt(byName('inputyear').value), m= byName('monthselect').selectedIndex, d= parseInt(byName('inputdate').value); if(!y || y<1000 || y> 3000) throw 'Bad Year '+y; if((!d || d<1 || d> 32) throw 'Bad Date '+d; day= new Date(y,m,d); if(day.getDate()!= d) throw 'Bad Date '+d; value= day.format_mysql(); } 

you can preset the fields to reflect the current date onload

onload= function(){ var now= new Date(); byName('inputyear').value= now.getFullYear(); byName('monthselect').selectedIndex= now.getMonth(); byName('inputdate').value= now.getDate(); } 

Comments

0

At least Safari 26.1, Javascript successfully parses dates of the format YYYY-MM-DD without workaround.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.