351

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.

4
  • 2
    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 Commented Jun 11, 2022 at 20:24
  • Use a simple moment.js library - momentjs.com/docs/#/parsing/is-valid Commented Oct 13, 2022 at 13:50
  • I would strongly recommend "luxon" package from the same moment.js team. 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. Commented Feb 28, 2023 at 19:05
  • Is there a natural language parser for date/times in javascript? has some good suggestions Commented Jun 29 at 2:30

25 Answers 25

369

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.

Sign up to request clarification or add additional context in comments.

12 Comments

how exactly should one use this? moment("whatever 123").isValid() returns true.
@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.
Same though, but I'm validating user input and I don't know the expected date format...
@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.
@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.
|
101

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));
}

14 Comments

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.
In IE8, new Date(date) does not give you 'Invalid Date'.
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.
new Date("469") results in Tue Jan 01 469 00:00:00 GMT+0200 (EET)
This is similar to the falsely accepted correct answer. isDate('Mac OS X 10.14.2') returns true here.
|
80

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)

15 Comments

Be careful with this as it will still return return for invalid dates in February, for example: 2013-02-31
Another reason to be careful - numbers parse as dates. Date.parse("4.3") is 986270400000.
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).
Sorry @Asmor, this is not a correct answer. Date.parse will parse any string with a number it in.
Date.parse("My Name 8") is coming as 99662040000 which is wrong. I used this and now suffering.
|
37

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 */
}

5 Comments

I realize it's a couple years later, but isNan is not a function; incorrect case on the first instance.
Does not work. If date is Foostreet 1, your condition is evaluated as true.
@FabianPicone - well, technically, it works, but shares a flaw with other parse-based solutions: Date.parse("<text here> <number here>") is likely be parsed into a "valid" date, causing parsedDate to not evaluate to NaN.
This parses date-like strings that aren't real dates, like 2/31/2021.
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.
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.

11 Comments

Hello! While this code may solve the question, including an explanation 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.
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.
I have added the explanation. Thanks for guidance.
becareful, isDate('4.3') and isDate('xxx 8') returns both true
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.
|
15

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];
} 

7 Comments

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 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.
@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
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.
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
|
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.

4 Comments

This doesn't test for strings that aren't real dates, like 2/31/2021.
Ya, this is probably not the best way to go. It would be very difficult to match every possible combination of date string.
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. stackoverflow.com/a/66863366/7530620
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.
11

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);
    }

1 Comment

This doesn't test for strings that aren't real dates like 2/31/2021.
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.

8 Comments

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.
for javascript this is working, but how to use it in typescript.?
This doesn't test for dates that are not real dates, like 2/31/2021.
@JanineWhite Here new Date(isISO) returns invalid date.
@NikhilZurunge The question explicitly asks about multiple formats, not just ISO dates.
|
9

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.

2 Comments

this does not work as passing 'test 2' will pass as a true date. tested in latest version of chrome
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)));
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"));

4 Comments

console.log("hello 1 ", isDate("hello 1 ")); returns true
you are right! do you have a solution? Up till now I think none of the answers here really addressed the question appropriately!
"100%", a percentage, returns true
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
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

1 Comment

This is the only answer that works in 2021.
2

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;
}

3 Comments

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.
Don't think this works as it should validateDate('2016-12-30T08:00:00.000Z') // false
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);
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;

Comments

1

I find this solution very good:

const isDateValid = stringDate => {
  const formats = [
    'd-M-y',
    'd,M,y',
    'y-M-d',
    'y,M,d',
    'y.M.d',
    'd.M.y',
    'y/M/d',
    'd/M/y',
  ];

  for (const format of formats) {
    const date = luxon.DateTime.fromFormat(stringDate, format);

    if (date.invalid === null) {
      return date.toJSDate(); // or return true
    }
  }

  return false;
};

console.log(isDateValid('30.12.86')); // true
console.log(isDateValid('30/12/86')); // true
console.log(isDateValid('86-12-40')); // false
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.js"></script>

and you can easily add more formats.

2 Comments

I did not dv this answer, but I find this solution to be "unexplained" and very far from D.R.Y.
I made your snippet runnable. Notice the sample dates parse incorrectly. '30.12.86' -> "0086-12-30T07:52:58.000Z" (year is 86 rather than 1986). You could cherry-pick test cases that work, but I think there's a great deal of risk with this approach, promising as it may seem. It could be useful if you keep the dates constrained to a particular input set, like variants of mm-dd-yyyy with different delimiters (but then maybe it's not much better than regex validation).
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;
}

Comments

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.

Comments

0

You can use this regex, change [1-5] if you want to include 2026..29:

^([1-2][1-9]|3[01])[\/\.-]((0[1-9])|1[0-2])[\/\.-](1\d{3}|20(([01]\d)|2[1-5]))$

Comments

0

chrono-node does this:

<script type="module">
import * as chrono from "https://esm.sh/[email protected]";

[
  "10-11-2009",
  "10/11/2009",
  "2009-11-10T07:00:00+0000",
  "200",
  "10",
  "350",
].forEach(test => console.log(chrono.parseDate(test)));
</script>

Comments

-1

Here's a minimalist version.

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

4 Comments

Still doesn't work for my example: isDate("&nbsp; 1")
@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.
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.
This doesn't test for strings that aren't real dates, like 2/31/2021.
-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.

3 Comments

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.
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.
Now that I've come to think of it, you can leave the !! can't you? Without them, it's the exact same thing.
-1

it is Simple:

// add you expresion
(/\d+-\d+-\d+/).test("2023-01-17 14:05:56.83419") // true

(/\d+-\d+-\d+/).test("202x-01-17 14:05:56.83419") // false

Comments

-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;
            }
        }

Comments

-2

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;
}

Comments

-2

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'

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.