315

What is an easy way to check if a value is a valid date, any known date format allowed.

For example I have the values 10-11-2009, 10/11/2009, 2009-11-10T07:00:00+0000 which should all be recognized as date values, and the values 200, 10, 350, which should not be recognized as a date value. What is the simplest way to check this, if this is even possible? Because timestamps would also be allowed.

Thizzer
  • 16,153
  • 28
  • 98
  • 139
  • 1
    There are a few other good test cases in the comments here: `whatever 123`, `Mac OS X 10.14.2`, `3/4/5`, `2/31/2021`,`31-02-2021`, `4.3`, `100%`,`  1` – icc97 Jun 11 '22 at 20:24
  • Use a simple moment.js library - https://momentjs.com/docs/#/parsing/is-valid/ – Karan Raiyani Oct 13 '22 at 13:50
  • I would strongly recommend "luxon" package from the same moment.js team. https://moment.github.io/luxon This is a lifesaver. I have worked on many super complex projects where the validity of date, durations, and intervals are important and luxon seems to be the best in the market. – Rameez Rami Feb 28 '23 at 19:05

23 Answers23

350

2015 Update

It is an old question but other new questions like:

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:

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:

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

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.

rsp
  • 107,747
  • 29
  • 201
  • 177
  • 1
    The answer came just at the right time for me! I had included `moment` for something else to work, didn't realise what it could do. I basically just did `if (moment(val).isValid() && !$.isNumeric(val)) {` where `val` possibly contains a date in a string. I had to add the numeric check because it can also be an integer and it parses that as a date too. – Jamie Barker Jun 17 '15 at 09:07
  • 7
    how exactly should one use this? `moment("whatever 123").isValid()` returns `true`. – krivar Jun 22 '15 at 11:49
  • 6
    @krivar It's best to use it like this: `moment("06/22/2015", "DD/MM/YYYY", true).isValid();` with the expected date format explicitly provided and with an argument `true` meaning strict checking. I updated my answer with more info and better examples. – rsp Jun 22 '15 at 14:36
  • 4
    Same though, but I'm validating user input and I don't know the expected date format... – Jan Van der Haegen Jan 23 '17 at 22:51
  • 2
    @JanVanderHaegen If you don't know the expected date format then how can you validate anything? The problem in guessing is that when you have 03/22/99 then you can guess it and you think it's valid. If you have 22/03/99 then it's also obvious what's the date. but then you have a problem with 03/04/99 or worse 03/04/05 because there are at least 3 different ways how you can interpret it and if you don't know the expected format then it doesn't matter if you say that it's valid if you don't know what it means. I always recommend using an explicit format because of that, preferably ISO string. – rsp Apr 14 '17 at 12:30
  • @rsp We have an open system where several USA based clients can load data (contracts, meter readings, prices) coming from files extracted from 3rd party USA based systems. We offer an interface where they can load their file then map it to our structure, then still modify if needed. Hence, assumptions can be made that 3/4/5 is a valid date, so is April 1st 2015. 'Suite 30' probably means their mapping is off. Note: Date.parse('suite 30') returns a valid date in Chrome, hence our dilemma. – Jan Van der Haegen Apr 15 '17 at 16:19
  • 4
    @JanVanderHaegen If assumptions can be made that 3/4/5 is a valid date and so is April 1st 2015 then I would recommend adding those formats (and potentially much more) to an explicit list of supported formats. Note that 3/4/5 that you mentioned is ambiguous without an explicit format. – rsp May 10 '17 at 09:06
  • 1
    This should be the accepted answer and not the accepted one. – Krishnan Venkiteswaran Nov 01 '18 at 10:05
  • 1
    `moment("Spiderman 2", moment.ISO_8601, true).isValid();` returns true – Ridd Jan 04 '21 at 15:57
  • Recommending `Luxon` is not nice - that package has `3.67 MB` which is ridiculous – Sebastian Voráč MSc. Dec 22 '21 at 08:50
  • Why you guys always take a lib for the most simple tasks? This is such a bad habit these days. – Jonathan Jun 02 '22 at 12:15
  • moment.js [suggests using other libraries now](https://momentjs.com/docs/#/-project-status/), I used https://date-fns.org/, with `isValid(parse(date, 'format', new Date()))`. – icc97 Jun 11 '22 at 20:29
91

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));
}
fabpico
  • 2,628
  • 4
  • 26
  • 43
Neil Girardi
  • 4,533
  • 1
  • 28
  • 45
  • 8
    I needed to return (new Date(date)).toString() !== "Invalid Date" for node. Also note that ? true : false is redundant. simply returning the expression will be enough here. – domenukk Aug 16 '14 at 12:15
  • 1
    In IE8, `new Date(date)` does not give you 'Invalid Date'. – krillgar Sep 11 '14 at 18:51
  • @krillgar good call, I did not realize that. What does IE 8 give you? (I haven't set up windows & IE VMs on my Mac and Linux laptops yet...) – Neil Girardi Sep 12 '14 at 19:56
  • Doing `new Date('text')` in IE8 gives you `NaN`. *facepalm* Stinking Microsoft. – krillgar Sep 12 '14 at 23:24
  • 36
    This is not a good answer. `new Date(date) !== "Invalid Date"` will **always** return *true* since the left expression will return a Date object with a timevalue of *NaN*, which can never be `===` to a string. Using `==` "works" due to type conversion. But since parsing of date strings is still largely implementation dependent, relying on it to parse random formats us seriously flawed. – RobG Jun 15 '15 at 14:17
  • 8
    new Date("469") results in Tue Jan 01 469 00:00:00 GMT+0200 (EET) – Dan Ochiana Mar 17 '16 at 15:56
  • @krillgar A Date in reality should be epoch time. This means the Date object should convert a string to a number, then when asked, display back the proper format expected. With this mindset of how Dates should work, NaN makes way more sense than an arbitrary string that is browser-specific. Also note that at this time IE was the only browser calculating local time from UTC correctly and that is because they ignored ECMA standard, while all other browsers that tried to follow it didn't calculate local time correctly. – Kody Apr 05 '17 at 18:46
  • For this to work, you need to call `.toString()` first: e.g. `new Date(date).toString() !== 'Invalid Date'` – jonschlinkert May 29 '18 at 23:08
  • in chrome new Date("01/30/2026") returns true but new Date("30/01/2026") returns invalid date – delwasaf ewrew Jan 16 '19 at 12:10
  • 12
    This is similar to the falsely accepted correct answer. `isDate('Mac OS X 10.14.2')` returns true here. – BradStell Jan 18 '19 at 18:18
  • This will also return true for strings that are formatted as dates, but will not return the correct date, like 2/31/2021. – Janine White Mar 30 '21 at 15:31
  • I tried with a/b/2021 and it worked. Any quick fix to that. – prashantchalise Aug 10 '21 at 10:56
  • `new Date("this is not a date.4")` will be a valid Date here – Elijah Mock Feb 13 '22 at 02:28
  • `new Date('Leywdeeffeeg 221')` returns `Mon Jan 01 0221 00:00:00 GMT+0155 (GMT+03:00)` on chrome – Kamuran Sönecek Aug 24 '23 at 09:54
68

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)
TOPKAT
  • 6,667
  • 2
  • 44
  • 72
Asmor
  • 5,043
  • 6
  • 32
  • 42
  • 52
    Be careful with this as it will still return return for invalid dates in February, for example: 2013-02-31 – leojh Feb 13 '13 at 22:47
  • 101
    Another reason to be careful - numbers parse as dates. `Date.parse("4.3")` is `986270400000`. – Mogsdad Feb 21 '13 at 06:05
  • 4
    I tried a fiddle with both of the 'caution' cases above: console.log(Date.parse("2013-02-31")); console.log(Date.parse("4.3")); and in both cases (on firefox) it returned NaN, so for me, Date.parse seems OK (I'm prevalidating for dashes and correct length before the parse anyway). – Cloudranger Apr 08 '13 at 14:28
  • @Cloudranger - In Chrome it parses it into a date. – Grinn May 21 '13 at 17:13
  • 84
    Sorry @Asmor, this is not a correct answer. Date.parse will parse any string with a number it in. – jwerre Mar 10 '14 at 16:01
  • 1
    `isNaN(Date.parse('Departing'))` is `true` and `isNaN(Date.parse('Sep 16, 2019'))` is `false` – Ashkan Sep 17 '19 at 08:08
  • 35
    Date.parse("My Name 8") is coming as 99662040000 which is wrong. I used this and now suffering. – Rohith Sep 20 '19 at 15:05
  • It works in Firefox, but it does not seem to work in Chrome, possibly it has been fully implemented there. – Jamo Jul 09 '20 at 20:36
  • as few people are telling above, some cases it return true but it should not, for example: Date.parse('2020-9-31') On September there is not this date... – felipe muner Aug 26 '20 at 08:21
  • The same in Safari: `Date.parse(1)` returns `-62135596800000`. In Chrome it's `978300000000`. But yeah, works fine in Firefox: `NaN` – Fogus Jul 02 '21 at 08:23
  • There's always server-side checking anyhows.. so no need to get hung up over edge cases :-) – Kieran Ryan Nov 07 '21 at 12:50
  • This is not reliable in chrome. – Austin Born Mar 04 '22 at 19:40
  • 1
    The above with a number and simple regex check seems to work like a charm for nearly all cases: `const isDate = date => !Number.isNaN(Number(date)) && !/(.*?2(?:\/|-)(29|30|31).*?)|(.*?\d\d.*?)/.test(date) ? false : !!Date.parse(date);` – Tim Mar 22 '22 at 03:43
  • This is not a good answer in 2022. In Chrome, `Date.parse('INVALID-DATE-5')` returns 988689600000. You can also see what it's thinking by doing `new Date('INVALID-DATE-5')` which returns (for me) Tue May 01 2001 00:00:00 GMT-0400 (Eastern Daylight Time). So, that's not at all what's expected. Use something like luxon instead. – Dave Haynes Dec 09 '22 at 21:25
  • From the docs: `Only the ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ) is explicitly specified to be supported. Other formats are implementation-defined and may not work across all browsers. A library can help if many different formats are to be accommodated.` – Turnip Feb 08 '23 at 23:13
36

new Date(date) === 'Invalid Date' only works in Firefox and Chrome. IE8 (the one I have on my machine for testing purposes) gives NaN.

As was stated to the accepted answer, Date.parse(date) will also work for numbers. So to get around that, you could also check that it is not a number (if that's something you want to confirm).

var parsedDate = Date.parse(date);

// You want to check again for !isNaN(parsedDate) here because Dates can be converted
// to numbers, but a failed Date parse will not.
if (isNaN(date) && !isNaN(parsedDate)) {
    /* do your work */
}
krillgar
  • 12,596
  • 6
  • 50
  • 86
  • 3
    I realize it's a couple years later, but `isNan` is not a function; incorrect case on the first instance. – Tim Lewis Aug 16 '16 at 21:17
  • 3
    Does not work. If `date` is `Foostreet 1`, your condition is evaluated as true. – fabpico Jun 05 '20 at 13:18
  • 1
    @FabianPicone - well, technically, it works, but shares a flaw with other `parse`-based solutions: `Date.parse(" ")` is likely be parsed into a "valid" date, causing `parsedDate` to not evaluate to `NaN`. – Oleg Valter is with Ukraine Oct 17 '20 at 10:43
  • This parses date-like strings that aren't real dates, like 2/31/2021. – Janine White Mar 30 '21 at 15:33
  • it does not work for `new Date()` giving `Tue Jul 19 2022 22:25:55 GMT+0200 (Central European Summer Time)` which returns false for `isnan`. I expect true. – Timo Jul 19 '22 at 20:27
22

Does not work consistently, watch out!

isDate('Leyweg 1') returns true on Chrome (Firefox returns false)

Read: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse (Date.parse is called under the hood when invoking like so: new Date(someDateString).


Original answer:

function isDate(dateStr) {
  return !isNaN(new Date(dateStr).getDate());
}
  • This will work on any browser since it does not rely on "Invalid Date" check.
  • This will work with legacy code before ES6.
  • This will work without any library.
  • This will work regardless of any date format.
  • This does not rely on Date.parse which fails the purpose when values like "Spiderman 22" are in date string.
  • This does not ask us to write any RegEx.
Youp Bernoulli
  • 5,303
  • 5
  • 39
  • 59
Yuvraj Patil
  • 7,944
  • 5
  • 56
  • 56
  • 2
    Hello! While this code may solve the question, [including an explanation](https://meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Brian61354270 Jul 30 '20 at 13:59
  • When adding an answer to an eight year old question with an accepted answer and 19 existing answers it is really important to point out what new aspect of the question your answer addresses, otherwise it might appear to be a duplicate answer and get removed. – Jason Aller Jul 30 '20 at 15:29
  • I have added the explanation. Thanks for guidance. – Yuvraj Patil Jul 31 '20 at 00:51
  • 12
    becareful, isDate('4.3') and isDate('xxx 8') returns both true – Boris Sep 29 '20 at 10:57
  • 3
    The statement about not relying on `Date.parse` is, unfortunately, untrue as both the aforementioned and the `Date()` constructor called with a string function pretty much identically. – Oleg Valter is with Ukraine Oct 17 '20 at 10:53
  • isDate(true || false) -> true :) – Oleg Protsenko Oct 22 '20 at 06:49
  • isDate("4") returns TRUE, so this answer is not any better than the other ones above – DoArNa Dec 23 '20 at 18:03
  • This doesn't test for dates that are not real dates, like 2/31/2021. – Janine White Mar 30 '21 at 15:37
  • This can't be the answer. Have you tried: `isDate("Option-1")` ? – Saket Kumar Jul 14 '21 at 00:58
  • This doest work for invalid dates like "30-Feb-2021" – Vinnie Amir Mar 15 '22 at 21:57
  • As far as I understand it the code can be simplified to: `!isNaN(Date.parse(dateStr )) && Date.parse(dateStr) >= 0 ` (considering the note) – Pavel Francírek Aug 26 '22 at 06:57
14

None of the answers here address checking whether the date is invalid such as February 31. This function addresses that by checking if the returned month is equivalent to the original month and making sure a valid year was presented.

//expected input dd/mm/yyyy or dd.mm.yyyy or dd-mm-yyyy
function isValidDate(s) {
  var separators = ['\\.', '\\-', '\\/'];
  var bits = s.split(new RegExp(separators.join('|'), 'g'));
  var d = new Date(bits[2], bits[1] - 1, bits[0]);
  return d.getFullYear() == bits[2] && d.getMonth() + 1 == bits[1];
} 
iamnotsam
  • 9,470
  • 7
  • 33
  • 30
  • Because the question is not wether to check if a string is a 'valid' date, but just checking wether a string represents a date format. – Thizzer Jul 28 '16 at 14:44
  • @Thizzer good point. I wouldn't mind fixing but on rereading your question I'm stumped because you say 10 shouldn't validate but that timestamps should be allowed. – ykay says Reinstate Monica Jul 31 '16 at 07:22
  • xD didn't even notice that, a question from my earlier days with date/timestamps. I will try to edit the question later today. – Thizzer Aug 01 '16 at 08:47
  • why month-1 and then month+1? – Kapil Raghuwanshi May 07 '19 at 04:30
  • 1
    @KapilRaghuwanshi javascript dates use a zero based month, so you need to subtract 1 to create the proper date and add 1 to check if it is equivalent to the original month – ykay says Reinstate Monica May 07 '19 at 07:15
  • 1
    This worked for me because, for example, if you create a new date with "2/30/2020", Chrome creates a valid date for March 1, 2020. So this was the only thing I could do to detect this sort of invalid date. After creating the new date object, I compared the year, month, and day to the original string. – John Gilmer Sep 11 '20 at 06:02
  • 1
    This is the best answer, and while OP asked a qestion about format, I am pretty sure he is trying to validate a string to be a date, not just the format. I would also extend this function to cover dd-MMM-yyyy format, e.g. 12-Jun-2021. IMHO all dates communicated between systems should be in this format, or ISO i.e. yyyy-mm-dd – Vinnie Amir Mar 15 '22 at 22:01
12

How about something like this? It will test if it is a Date object or a date string:

function isDate(value) {
    var dateFormat;
    if (toString.call(value) === '[object Date]') {
        return true;
    }
    if (typeof value.replace === 'function') {
        value.replace(/^\s+|\s+$/gm, '');
    }
    dateFormat = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
    return dateFormat.test(value);
}

I should mention that this doesn't test for ISO formatted strings but with a little more work to the RegExp you should be good.

Ulysse BN
  • 10,116
  • 7
  • 54
  • 82
jwerre
  • 9,179
  • 9
  • 60
  • 69
  • 1
    This doesn't test for strings that aren't real dates, like 2/31/2021. – Janine White Mar 30 '21 at 15:34
  • Ya, this is probably not the best way to go. It would be very difficult to match *every* possible combination of date string. – jwerre Mar 30 '21 at 15:48
  • I test that the string parses to a date and that the date in the original string matches the date in the parsed string to ensure that a real date is entered. https://stackoverflow.com/a/66863366/7530620 – Janine White Mar 30 '21 at 15:56
  • Using pipes inside of a character class is incorrect and damages the integrity/accuracy of the pattern. I worry for the many users that copy-pasted this snippet into their projects. – mickmackusa Feb 24 '22 at 22:02
10

Use Regular expression to validate it.

isDate('2018-08-01T18:30:00.000Z');

isDate(_date){
        const _regExp  = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
        return _regExp.test(_date);
    }
lpradhap
  • 623
  • 6
  • 17
9

By referring to all of the above comments, I have come to a solution.

This works if the Date passed is in ISO format or need to manipulate for other formats.

var isISO = "2018-08-01T18:30:00.000Z";

if (new Date(isISO) !== "Invalid Date" && !isNaN(new Date(isISO))) {
    if(isISO == new Date(isISO).toISOString()) {
        console.log("Valid date");
    } else {
        console.log("Invalid date");
    }
} else {
    console.log("Invalid date");
}

You can play here on JSFiddle.

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Nikhil Zurunge
  • 716
  • 6
  • 10
  • 1
    This solution worked best for me as the date strings my app supports are of the format `YYYY-MM-DD`, so it's trivial to attach `T00:00:00.000Z` and use this solution to check for valid strings. – accelerate Oct 30 '19 at 19:14
  • 2
    for javascript this is working, but how to use it in typescript.? – Sae Nov 30 '19 at 06:59
  • This doesn't test for dates that are not real dates, like 2/31/2021. – Janine White Mar 30 '21 at 15:38
  • @JanineWhite Here `new Date(isISO)` returns invalid date. – Nikhil Zurunge Apr 02 '21 at 13:43
  • @NikhilZurunge The question explicitly asks about multiple formats, not just ISO dates. – Janine White Apr 03 '21 at 15:14
  • @JanineWhite well a little modification worked for me, not every problem has a straight forward answer I believe. Hope other solutions do proper justice to the 'question'. – Nikhil Zurunge Apr 03 '21 at 15:43
  • @JanineWhite I genuinely like that you've gone through pointing out a flawed case in most of these answers. An answer that answers a subset to the solution can still be a useful answer. So if you add the restriction 'date must be ISO format' and you can have a function as small as this that doesn't rely on a library and also handles your case of '2/31/2021', then for me this is a good answer. – icc97 Jun 11 '22 at 20:14
  • There might be a case here for also having a regex check for an iso date – icc97 Jun 11 '22 at 20:15
7

Here is an improved function that uses only Date.parse():

function isDate(dateToTest) {
    return isNaN(dateToTest) && !isNaN(Date.parse(dateToTest));
}

Note: Date.parse() will parse numbers: for example Date.parse(1) will return a date. So here we check if dateToTest is not a number then if it is a date.

Daniel Tonon
  • 9,261
  • 5
  • 61
  • 64
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
  • 2
    this does not work as passing 'test 2' will pass as a true date. tested in latest version of chrome – user1751287 Oct 07 '19 at 09:48
  • 1
    This doesn't test for dates that are not real like 2/31/2021. Also, you don't need an if then structure. You could just return the condition, or assign it to a variable, then return the variable, i.e., return (isNaN(s) && !isNaN(Date.parse(s))); – Janine White Mar 30 '21 at 15:40
5

I know it's an old question but I faced the same problem and saw that none of the answers worked properly - specifically weeding out numbers (1,200,345,etc..) from dates, which is the original question. Here is a rather unorthodox method I could think of and it seems to work. Please point out if there are cases where it will fail.

if(sDate.toString() == parseInt(sDate).toString()) return false;

This is the line to weed out numbers. Thus, the entire function could look like:

function isDate(sDate) {  
  if(sDate.toString() == parseInt(sDate).toString()) return false; 
  var tryDate = new Date(sDate);
  return (tryDate && tryDate.toString() != "NaN" && tryDate != "Invalid Date");  
}

console.log("100", isDate(100));
console.log("234", isDate("234"));
console.log("hello", isDate("hello"));
console.log("25 Feb 2018", isDate("25 Feb 2018"));
console.log("2009-11-10T07:00:00+0000", isDate("2009-11-10T07:00:00+0000"));
peekolo
  • 342
  • 3
  • 8
  • 2
    `console.log("hello 1 ", isDate("hello 1 "));` returns true – John Nov 20 '19 at 11:10
  • you are right! do you have a solution? Up till now I think none of the answers here really addressed the question appropriately! – peekolo Nov 24 '19 at 05:07
  • "100%", a percentage, returns true – toddmo Apr 02 '20 at 18:11
  • Among all the answers this is the correct one and it is working in 2022, by the way you must add this code in order to skip the booleans `if (typeof sDate === 'boolean') return false`. Do not try to add more equal signs to the equation because it wont work anymore – VeRJiL Apr 03 '22 at 13:25
4

I feel none of the answers correctly understood what the OP asked. The issue here is that JavaScript can parse any number as a valid date, since the Date object can parse a string like '3000' as the year and will return a valid Date instance:

new Date('3000')

> Wed Jan 01 3000 02:00:00 GMT+0200 (Eastern European Standard Time)

To solve this, we can use the Day.js library's parsing method in strict mode by passing in a third argument. It's documented in their String + Format page. In order for parsing to work based on a format, we must also enable the CustomParseFormat plugin. I'm assuming you can use ESM imports here or have a compiler like Webpack set up

import dayjs from 'dayjs'
import formatParser from 'dayjs/plugin/customParseFormat'

dayjs.extend(formatParser)

dayjs('3000', 'YYYY-MM-DD', true).isValid()

> false
kano
  • 5,626
  • 3
  • 33
  • 48
2

I would do this

var myDateStr= new Date("2015/5/2");

if( ! isNaN ( myDateStr.getMonth() )) {
    console.log("Valid date");
}
else {
    console.log("Invalid date");
}

Play here

kiranvj
  • 32,342
  • 7
  • 71
  • 76
  • 2
    This doesn't work in current Chrome, possibly other browsers. I changed the string provided to `EXAMPLE STRING 12345` and it's returns "Valid date". –  Apr 03 '17 at 20:59
  • 1
    This doesn't test for strings that aren't real dates, like 2/31/2021. – Janine White Mar 30 '21 at 15:40
1

is it fine to check for a Date related function is available for the object to find whether it is a Date object or not ?

like

var l = new Date();
var isDate = (l.getDate !== undefined) ? true; false;
Kishore Relangi
  • 1,928
  • 16
  • 18
1

This callable function works perfectly, returns true for valid date. Be sure to call using a date on ISO format (yyyy-mm-dd or yyyy/mm/dd):

function validateDate(isoDate) {

    if (isNaN(Date.parse(isoDate))) {
        return false;
    } else {
        if (isoDate != (new Date(isoDate)).toISOString().substr(0,10)) {
            return false;
        }
    }
    return true;
}
Peter DK
  • 21
  • 2
  • 1
    It's good, but it doesn't answer the question completely. Specifically, it doesn't work for '2009-11-10T07:00:00+0000', one of the examples given. – amadan Nov 29 '16 at 10:32
  • Don't think this works as it should validateDate('2016-12-30T08:00:00.000Z') // false – Jose Browne Dec 30 '16 at 21:58
  • 1
    Regardless of whether or not this works, it could be simplified as `return !isNaN(Date.parse(isoDate)) || isoDate == new Date(isoDate).toISOString().substr(0,10);` – Michel Jung Aug 28 '18 at 13:37
1

i find this solution very good:

const DateTime = require('luxon').DateTime;

isDateValid(stringDate) {
  let date = DateTime.fromFormat(stringDate, 'd-M-y');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'd,M,y');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'y-M-d');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'y,M,d');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'y.M.d');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'd.M.y');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'y/M/d');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  date = DateTime.fromFormat(stringDate, 'd/M/y');
  if (date.invalid === null) {
    return date.toJSDate();
  }
  return false;
}

isDateValid('30.12.86'); //true
isDateValid('30/12/86'); //true
isDateValid('86-12-40'); //false

and you can easily add more formats

itzhar
  • 12,743
  • 6
  • 56
  • 63
1

I think the most straight forward solution would be

Date.parse(yourDate) > 0 ? true : false;

If it is not a valid date, it will be NaN, which is not greater than 0.

Dev-Siri
  • 592
  • 5
  • 22
  • Date in JS can be < 0 (for dates before 1970). Also the syntax is incorrect, `if` and `;` is not needed here. And `x ? : true : false` is not the best way to make a boolean from an expression, use `!!(x)` instead, which is a common pattern. – Piotr Henryk Dabrowski Sep 30 '22 at 22:24
  • Thanks so much. I didn't consider the fact that dates might be before 1970. I also didn't know the !!(x) syntax up until now. – MillCreeker Oct 02 '22 at 08:40
  • Now that I've come to think of it, you can leave the ```!!``` can't you? Without them, it's the exact same thing. – MillCreeker Oct 03 '22 at 06:32
0

Here's a minimalist version.

var isDate = function (date) {
    return!!(function(d){return(d!=='Invalid Date'&&!isNaN(d))})(new Date(date));
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • 2
    Still doesn't work for my example: `isDate("  1")` – Tomas Sep 12 '17 at 09:59
  • @Tom You should check if the value contains white-space characters before determining if it's a date. Your issue is a special-case which needs to be handled by your controller logic. – Mr. Polywhirl Sep 12 '17 at 14:12
  • 3
    Checking for white space chars should not be required as the string Jan. 1, 2020 is a valid date that contains white space. Your method does not account for this. – Kirstin Walsh Jan 30 '20 at 21:52
  • This doesn't test for strings that aren't real dates, like 2/31/2021. – Janine White Mar 30 '21 at 15:41
0

Ok, this is an old question, but I found another solution while checking the solutions here. For me works to check if the function getTime() is present at the date object:

const checkDate = new Date(dateString);

if (typeof checkDate.getTime !== 'function') {
  return;
}
m.steini
  • 21
  • 2
0

I believe this is the simplest working answer for date that contains only numbers:

var rst = Date.parse(sDate.replaceAll(" ",""));
if(rst===NaN) console.log("not a date");
else console.log("a great date")

By removing spaces you detect values like "hello 2" that are taken as a date. For the dates that contain strings like day name or month name ... I believe it is about string validation.

-1

This function verifies that the input string in the format m/d/yyyy or mm/dd/yyyy can be converted to a date and that the date is a valid date matching the input string. Add more conditional checks to verify additional formats.

/**
 * Verify if a string is a date
 * @param {string} sDate - string that should be formatted m/d/yyyy or mm/dd/yyyy
 * @return {boolean} whether string is a valid date
 */
function isValidDate(sDate) {
  let newDate = new Date(sDate);
  console.log(sDate + " date conversion: " + newDate);
  let isDate = (!isNaN(newDate.getTime()));
  console.log(sDate + " is a date: " + isDate);
  if (isDate) {
    let firstSlash = sDate.indexOf("/");
    let secondSlash = sDate.indexOf("/",firstSlash+1);
    let originalDateString = parseInt(sDate.slice(0,firstSlash),10) + "/" + parseInt(sDate.slice(firstSlash+1,secondSlash),10) + "/" + parseInt(sDate.slice(secondSlash+1),10);
    let newDateString = (newDate.getMonth()+1) + "/" + (newDate.getDate()) + "/" + (newDate.getFullYear());
    isDate = (originalDateString == newDateString);
    console.log(originalDateString + " matches " + newDateString + ": " + isDate);
  }
  return isDate;
}
Janine White
  • 439
  • 5
  • 14
-1

Here is what one could use to validate that the input is a number or a string that can be converted to a date object.

It covers the following cases:

  1. catching whatever input leads to "Invalid Date" date constructor result;
  2. catching the cases where the date is "valid" from technical point of view, but it is not valid from business logic point of view, like
  • new Date(null).getTime(): 0
  • new Date(true).getTime(): 1
  • new Date(-3.14).getTime(): -3
  • new Date(["1", "2"]).toDateString(): Tue Jan 02 2001
  • new Date([1, 2]).toDateString(): Tue Jan 02 2001
function checkDateInputValidity(input, lowerLimit, upperLimit) {
    // make sure the input is a number or string to avoid false positive correct dates:
    if (...) {
        return false
    }
    // create the date object:
    const date = new Date(input)
    // check if the Date constructor failed:
    if (date.toDateString() === 'Invalid Date') {
        return false
    }
    // check if the Date constructor succeeded, but the result is out of range:
    if (date < new Date(lowerLimit) || date > new Date(upperLimit)) {
        return false
    }
    return true
}

// const low = '2021-12-31T23:59:59'
// const high = '2025-01-01T00:00:00'
MadJoRR
  • 240
  • 2
  • 9
-2

This is how I end up doing it. This will not cover all formats. You have to adjust accordingly. I have control on the format, so it works for me

function isValidDate(s) {
            var dt = "";
            var bits = [];
            if (s && s.length >= 6) {
                if (s.indexOf("/") > -1) {
                    bits = s.split("/");
                }
                else if (s.indexOf("-") > -1) {
                    bits = s.split("-");
                }
                else if (s.indexOf(".") > -1) {
                    bits = s.split(".");
                }
                try {
                    dt = new Date(bits[2], bits[0] - 1, bits[1]);
                } catch (e) {
                    return false;
                }
                return (dt.getMonth() + 1) === parseInt(bits[0]);
            } else {
                return false;
            }
        }
kheya
  • 7,546
  • 20
  • 77
  • 109