Check if a string is a date value

2015 Update

It is an old question but other new questions like:

  • How to validate if a string is a valid date in js

get closed as duplicates of this one, so I think it's important to add some fresh info here. I'm writing it because I got scared thinking that people actually copy and paste some of the code posted here and use it in production.

Most of the answers here either use some complex regular expressions that match only some very specific formats and actually do it incorrectly (like matching January 32nd while not matching actual ISO date as advertised - see demo) or they try to pass anything to the Date constructor and wish for the best.

Using Moment

As I explained in this answer there is currently a library available for that: Moment.js

It is a library to parse, validate, manipulate, and display dates in JavaScript, that has a much richer API than the standard JavaScript date handling functions.

It is 12kB minified/gzipped and works in Node.js and other places:

bower install moment --save # bower
npm install moment --save   # npm
Install-Package Moment.js   # NuGet
spm install moment --save   # spm
meteor add momentjs:moment  # meteor

Using Moment you can be very specific about checking valid dates. Sometimes it is very important to add some clues about the format that you expect. For example, a date such as 06/22/2015 looks like a valid date, unless you use a format DD/MM/YYYY in which case this date should be rejected as invalid. There are few ways how you can tell Moment what format you expect, for example:

moment("06/22/2015", "MM/DD/YYYY", true).isValid(); // true
moment("06/22/2015", "DD/MM/YYYY", true).isValid(); // false

The true argument is there so the Moment won't try to parse the input if it doesn't exactly conform to one of the formats provided (it should be a default behavior in my opinion).

You can use an internally provided format:

moment("2015-06-22T13:17:21+0000", moment.ISO_8601, true).isValid(); // true

And you can use multiple formats as an array:

var formats = [
    moment.ISO_8601,
    "MM/DD/YYYY  :)  HH*mm*ss"
];
moment("2015-06-22T13:17:21+0000", formats, true).isValid(); // true
moment("06/22/2015  :)  13*17*21", formats, true).isValid(); // true
moment("06/22/2015  :(  13*17*21", formats, true).isValid(); // false

See: DEMO.

Other libraries

If you don't want to use Moment.js, there are also other libraries:

  • XDate
  • DateJS

2016 Update

I created the immoment module that is like (a subset of) Moment but without surprises caused by mutation of existing objects (see the docs for more info).

2018 Update

Today I recommend using Luxon for date/time manipulation instead of Moment, which (unlike Moment) makes all object immutable so there are no nasty surprises related to implicit mutation of dates.

More info

See also:

  • Managing Dates and Times Using Moment.js by Jay Raj
  • Working with JavaScript Dates Using Moment.js by Bradley Holbrook

A series of articles by Rob Gravelle on JavaScript date parsing libraries:

  • A Roundup of Popular JavaScript Date Parsing Libraries: Moment.js
  • A Roundup of Popular JavaScript Date Parsing Libraries: Datejs
  • A Roundup of Popular JavaScript Date Parsing Libraries: XDate

Bottom line

Of course anyone can try to reinvent the wheel, write a regular expression (but please actually read ISO 8601 and RFC 3339 before you do it) or call buit-in constructors with random data to parse error messages like 'Invalid Date' (Are you sure this message is exactly the same on all platforms? In all locales? In the future?) or you can use a tested solution and use your time to improve it, not reinvent it. All of the libraries listed here are open source, free software.


This is how I solved this problem in an app I'm working on right now:

updated based on feedback from krillgar:

var isDate = function(date) {
    return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}

Would Date.parse() suffice?

See its relative MDN Documentation page.

Date.parse returns a timestamp if string date is valid. Here are some use cases:

// /!\ from now (2021) date interpretation changes a lot depending on the browser
Date.parse('01 Jan 1901 00:00:00 GMT') // -2177452800000
Date.parse('01/01/2012') // 1325372400000
Date.parse('153') // NaN (firefox) -57338928561000 (chrome)
Date.parse('string') // NaN
Date.parse(1) // NaN (firefox) 978303600000 (chrome)
Date.parse(1000) // -30610224000000 from 1000 it seems to be treated as year
Date.parse(1000, 12, 12) // -30610224000000 but days and month are not taken in account like in new Date(year, month,day...)
Date.parse(new Date(1970, 1, 0)) // 2588400000
// update with edge cases from comments
Date.parse('4.3') // NaN (firefox) 986248800000 (chrome)
Date.parse('2013-02-31') // NaN (firefox) 1362268800000 (chrome)
Date.parse("My Name 8") // NaN (firefox) 996616800000 (chrome)