Categories
date javascript

Detecting an “invalid date” Date instance in JavaScript

1921

I’d like to tell the difference between valid and invalid date objects in JS, but couldn’t figure out how:

var d = new Date("foo");
console.log(d.toString()); // shows 'Invalid Date'
console.log(typeof d); // shows 'object'
console.log(d instanceof Date); // shows 'true'

Any ideas for writing an isValidDate function?

  • Ash recommended Date.parse for parsing date strings, which gives an authoritative way to check if the date string is valid.
  • What I would prefer, if possible, is have my API accept a Date instance and to be able to check/assert whether it’s valid or not. Borgar’s solution does that, but I need to test it across browsers. I also wonder whether there’s a more elegant way.
  • Ash made me consider not having my API accept Date instances at all, this would be easiest to validate.
  • Borgar suggested testing for a Date instance, and then testing for the Date‘s time value. If the date is invalid, the time value is NaN. I checked with ECMA-262 and this behavior is in the standard, which is exactly what I’m looking for.

15

  • 1

    I deleted my original answer since checking if NaN is a much better solution than comparing to a string “Invalid Date”. I’ll have to make use of the isNaN solution, myself.

    Aug 30, 2009 at 11:55

  • @orip, “have my API accept a Date instance and to be able to check/assert whether it’s valid or not” Have you tried: isNan(d.getTime())==true on the date instance?

    – Ash

    Aug 30, 2009 at 17:49

  • 20

    You could remove the if statement by changing the body of the function to: return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );

    – styfle

    Jun 23, 2011 at 23:35

  • 2

    @styfle – sure, but why?

    – orip

    Jun 25, 2011 at 14:39

  • 3

    @styfle – guess it’s a style preference: I find it clearer to separate the type check from the equality logic.

    – orip

    Jun 27, 2011 at 13:05

1695

Here’s how I would do it:

if (Object.prototype.toString.call(d) === "[object Date]") {
  // it is a date
  if (isNaN(d)) { // d.getTime() or d.valueOf() will also work
    // date object is not valid
  } else {
    // date object is valid
  }
} else {
  // not a date object
}

Update [2018-05-31]: If you are not concerned with Date objects from other JS contexts (external windows, frames, or iframes), this simpler form may be preferred:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

Update [2021-02-01]: Please note that there is a fundamental difference between “invalid dates” (2013-13-32) and “invalid date objects” (new Date('foo')). This answer does not deal with validating date input, only if a Date instance is valid.

27

  • 26

    instanceof breaks across frames. Duck-typing can work just fine too: validDate == d && d.getTime && !isNaN(d.getTime()); — Since the question is for a general utility function I prefer to be more strict.

    – Borgar

    Aug 30, 2009 at 12:14

  • 13

    @Borgar, just found my answer: “The problems arise when it comes to scripting in multi-frame DOM environments. In a nutshell, Array objects created within one iframe do not share [[Prototype]]’s with arrays created within another iframe. Their constructors are different objects and so both instanceof and constructor checks fail.”

    – Ash

    Aug 31, 2009 at 5:35

  • 80

    you don’t even need d.getTime just isNan(d)

    – TecHunter

    May 30, 2013 at 8:26

  • 17

    Could be simplified like this: d instanceof Date && !isNaN(d.getTime())

    – Zorgatone

    Apr 7, 2017 at 15:27

  • 10

    Thanks for the answer, but I wish to stress @Borgar and @blueprintChris comments: if I parse the digit 1 for example I would still have a valid date resulting to Mon Jan 01 2001 00:00:00 which is indeed a date, however for the purpose of my application it is completely useless. Thus, there is some more input validation needed in my case at least. This answer validates a dateObject not a Date!

    – dnhyde

    Sep 22, 2018 at 10:20

323

Instead of using new Date() you should use:

var timestamp = Date.parse('foo');

if (isNaN(timestamp) == false) {
  var d = new Date(timestamp);
}

Date.parse() returns a timestamp, an integer representing the number of milliseconds since 01/Jan/1970. It will return NaN if it cannot parse the supplied date string.

7

  • 177

    -1 Dunno why this has so many up votes, Date.parse is implementation dependent and definitely not to be trusted to parse general date strings. There is no single format that is parsed correctly in popular browsers, much less all those in use (though eventually the ISO8601 format specified in ES5 should be ok).

    – RobG

    May 25, 2012 at 2:30

  • 4

    If you use the new Date('foo') that’s basically equivalent with the Date.parse('foo') method. See: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… So what @RobG said, it also applies to it.

    Jun 3, 2019 at 7:52


  • 4

    This test would fail in Chrome. For example, Date.parse(‘AAA-0001’) in Chrome gives me a number.

    – Nick

    Jun 17, 2019 at 4:28


  • 2

    failed … detect all numeric values

    – mercury

    Nov 23, 2019 at 22:42

  • Needs the American MM/DD/YYYY format to work. Date.parse('24/12/2021') returns NaN.

    May 24, 2021 at 2:26


120

You can check the validity of a Date object d via

d instanceof Date && isFinite(d)

To avoid cross-frame issues, one could replace the instanceof check with

Object.prototype.toString.call(d) === '[object Date]'

A call to getTime() as in Borgar’s answer is unnecessary as isNaN() and isFinite() both implicitly convert to number.

8

  • Try this in chrome – Object.prototype.toString.call(new Date(“2013-07-09T19:07:9Z”)). It will return “[object Date]”. According to you, therefore, “2013-07-09T19:07:9Z”, should be a valid date. But it is not. You can verify it, again in chrome, by doing var dateStr = new Date(“2013-07-09T19:07:9Z”); dateStr It will return invalid date.

    – Tintin

    Jul 18, 2013 at 0:06


  • 2

    @Tintin: that’s what isFinite() is for – toString.call() is only a replacement for the instanceof part of the check

    – Christoph

    Jul 18, 2013 at 5:25


  • Will comparing with ‘[object Date]’ work with non-english browsers? I doubt it.

    – kristianp

    May 8, 2015 at 1:04

  • 2

    @kristianp actually it probably will and is probably even part of the ECMAScript spec. But, yes, it seems ugly.

    – binki

    Dec 11, 2015 at 6:36

  • To me the first approach here is the very best option, although I’m not sure if there’s any real-world advantage of using isFinite over isNaN (both work just fine with Date(Infinity)). Furthermore, if you want the opposite condition, it gets a bit simpler: if (!(date instanceof Date) || isNaN(date)).

    – Andrew

    Jan 30, 2018 at 1:33