Last updated: Mar 6, 2024
Reading timeยท7 min
To check if a date is valid:
Date
object.isNaN()
function returns false
.function dateIsValid(date) { return date instanceof Date && !isNaN(date); } console.log(dateIsValid(new Date('2022-03-36'))); // ๐๏ธ false console.log(dateIsValid(new Date())); // ๐๏ธ true console.log(dateIsValid(new Date('2022-03-24'))); // ๐๏ธ true
We created a reusable function that takes a Date
object as a parameter and
checks if the date is valid.
The instanceof
operator returns a boolean value indicating whether the
prototype property of the constructor appears in the prototype chain of the
object.
console.log(new Date() instanceof Date); // ๐๏ธ true console.log({} instanceof Date); // ๐๏ธ false console.log([] instanceof Date); // ๐๏ธ false console.log('hi' instanceof Date); // ๐๏ธ false
The instanceof
operator will only return true
if the value to the left was created using the
Date() constructor or a class
that extends it.
The second condition checks if passing the date to the
isNaN()
function returns false
.
function dateIsValid(date) { return date instanceof Date && !isNaN(date); }
The isNaN
function takes a value and tries to determine if the value is NaN
(not a number).
isNaN
function automatically converts it to one.When you convert a valid date to a number, you get a timestamp - the number of milliseconds elapsed between the 1st of January and the given date.
// ๐๏ธ 1643112264226 console.log(Number(new Date())); // ๐๏ธ NaN console.log(Number(new Date('2022-03-36')));
In the second example we passed an invalid date to the Date
constructor, so
converting the value to a number returning NaN
.
Date
is an instance of the Date()
constructor and converting it to a number doesn't return NaN
(not a number), then we have a valid Date
.It should be noted that the instanceof
operator wouldn't work if the Date
object is created in another context, e.g. in an external iframe.
If you are creating the Date
object in an external window or an iframe,
stringify the object's prototype instead of using the instanceof
operator.
function dateIsValid(date) { return ( Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date) ); } console.log(dateIsValid(new Date('2022-03-36'))); // ๐๏ธ false console.log(dateIsValid(new Date())); // ๐๏ธ true console.log(dateIsValid(new Date('2022-03-24'))); // ๐๏ธ true
The code snippet above should only be used if you are creating your Date
objects in an external window, e.g. an iframe.
In all other cases, the instanceof
operator gets the job done and is much more
readable.
Alternatively, you can use duck-typing.
function dateIsValid(date) { if ( typeof date === 'object' && date !== null && typeof date.getTime === 'function' && !isNaN(date) ) { return true; } return false; } console.log(dateIsValid(new Date('2022-03-36'))); // ๐๏ธ false console.log(dateIsValid(new Date())); // ๐๏ธ true console.log(dateIsValid(new Date('2022-03-24'))); // ๐๏ธ true console.log(dateIsValid([])); // ๐๏ธ true console.log(dateIsValid({})); // ๐๏ธ true console.log(dateIsValid(null)); // ๐๏ธ true
We first
check if the passed-in value has a type of object
.
Since null
also has a type of object in JavaScript, we have to explicitly
check that the value is not null.
Then, we check if the object has a getTime
property that is a function. You
could repeat this process with any other properties or methods that the Date
object implements.
To validate a date that is formatted as YYYY-MM-DD
:
Date
constructor returns a valid Date
object.YYYY-MM-DD
.function dateIsValid(dateStr) { const regex = /^\d{4}-\d{2}-\d{2}$/; if (dateStr.match(regex) === null) { return false; } const date = new Date(dateStr); const timestamp = date.getTime(); if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) { return false; } return date.toISOString().startsWith(dateStr); } console.log(dateIsValid('2022-01-24')); // ๐๏ธ true console.log(dateIsValid('2022-01-35')); // ๐๏ธ false console.log(dateIsValid('hello')); // ๐๏ธ false
We created a reusable function that checks if a string is a valid date,
formatted as YYYY-MM-DD
.
The function takes a string in the form of YYYY-MM-DD
as a parameter.
The regex
variable stores a regular expression.
The forward slashes / /
mark the beginning and end of the regex.
^
matches the beginning of the input and the dollar sign $
matches the end of the input.The \d
special character matches any digit in the range of 0
to 9
.
Specifying the \d
character is the same as specifying a range of [0-9]
.
The number in the curly braces {}
is an exact match of the number of digits we
expect between the hyphens.
If you ever need help reading a regular expression, check out this regex cheat sheet from MDN.
The String.match() method returns an
array containing the matches of the regular expression in the string or null
if no matches are found.
false
from the function.The next step is to pass the date string to the
Date() constructor to see if we
get a valid Date
object back.
Here is an example of the flow for when an invalid date that passes the regex
is supplied to the dateIsValid
function.
function dateIsValid(dateStr) { const regex = /^\d{4}-\d{2}-\d{2}$/; if (dateStr.match(regex) === null) { return false; } const date = new Date(dateStr); console.log(date); // ๐๏ธ Invalid Date const timestamp = date.getTime(); console.log(timestamp); // ๐๏ธ NaN if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) { // ๐๏ธ this runs return false; } return date.toISOString().startsWith(dateStr); } console.log(dateIsValid('2022-01-35')); // ๐๏ธ false
The date
variable stores an Invalid Date
object.
Calling the getTime()
method on the Invalid Date
object returns NaN
(not a
number).
The getTime() method returns a number that represents the milliseconds between the 1st of January, 1970 and the given date.
In our if
condition, we check if the timestamp
variable doesn't store a
number or stores NaN
.
Unfortunately, if you console.log(typeof NaN)
, you will get "number"
back.
toISOString()
method to check if the Date
object's ISO 8601 formatted string starts with the provided string.The
toISOString()
method returns a string formatted as YYYY-MM-DDTHH:mm:ss.sssZ
.
If the ISO representation of the Date
object starts with the provided string,
we can conclude that the date string is valid and formatted as YYYY-MM-DD
.
To validate a date that is formatted as DD/MM/YYYY
:
Date
constructor returns a valid Date
object.// โ Validate date formatted as `DD/MM/YYYY` function dateIsValid(dateStr) { const regex = /^\d{2}\/\d{2}\/\d{4}$/; if (dateStr.match(regex) === null) { return false; } const [day, month, year] = dateStr.split('/'); // ๐๏ธ format Date string as `yyyy-mm-dd` const isoFormattedStr = `${year}-${month}-${day}`; const date = new Date(isoFormattedStr); const timestamp = date.getTime(); if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) { return false; } return date.toISOString().startsWith(isoFormattedStr); } console.log(dateIsValid('18/01/2022')); // ๐๏ธ true console.log(dateIsValid('35/01/2022')); // ๐๏ธ false console.log(dateIsValid('hello')); // ๐๏ธ false
We created a reusable function that checks if a string is a valid date formatted
as DD/MM/YYYY
.
The function takes a string in the form of DD/MM/YYYY
as a parameter.
You can use the same approach if you need to validate a date that is formatted
as MM/DD/YYYY
.
You just have to change the order of destructuring when splitting on the
forwards slash /
.
// โ Validate date formatted as `MM/DD/YYYY` function dateIsValid(dateStr) { const regex = /^\d{2}\/\d{2}\/\d{4}$/; if (dateStr.match(regex) === null) { return false; } // ๐๏ธ only changed the order of destructuring assignment const [month, day, year] = dateStr.split('/'); // ๐๏ธ format Date string as `yyyy-mm-dd` const isoFormattedStr = `${year}-${month}-${day}`; const date = new Date(isoFormattedStr); const timestamp = date.getTime(); if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) { return false; } return date.toISOString().startsWith(isoFormattedStr); } console.log(dateIsValid('01/18/2022')); // ๐๏ธ true console.log(dateIsValid('01/35/2022')); // ๐๏ธ false console.log(dateIsValid('hello')); // ๐๏ธ false
The regex
variable stores a regular expression.
The forward slashes / /
mark the beginning and end of the regular expression.
^
matches the beginning of the input and the dollar sign $
matches the end of the input.The \d
special character matches any digit in the range of 0
to 9
.
Specifying the \d
character is the same as specifying a range of [0-9]
.
The number in the curly braces {}
is an exact match of the number of digits we
expect between the forward slashes.
If you ever need help reading a regular expression, check out this regex cheat sheet from MDN.
The String.match() method returns an
array containing the matches of the regular expression in the string or null
if no matches are found.
false
from the function.The next step is to get a string, formatted as YYYY-MM-DD
and pass it to the
Date() constructor to see if we
get a valid Date
object back.
Here is an example of the flow where an invalid date that passes the regex
is
supplied to the dateIsValid
function.
function dateIsValid(dateStr) { const regex = /^\d{2}\/\d{2}\/\d{4}$/; if (dateStr.match(regex) === null) { return false; } const [day, month, year] = dateStr.split('/'); // ๐๏ธ format Date string as `yyyy-mm-dd` const isoFormattedStr = `${year}-${month}-${day}`; const date = new Date(isoFormattedStr); console.log(date); // ๐๏ธ Invalid Date const timestamp = date.getTime(); console.log(timestamp); // ๐๏ธ NaN if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) { // ๐๏ธ this runs return false; } return date.toISOString().startsWith(isoFormattedStr); } console.log(dateIsValid('35/01/2022')); // ๐๏ธ false
The date
variable stores an Invalid Date
object.
Calling the getTime()
method on the Invalid Date
object returns NaN
(not a
number).
The getTime() method returns a number that represents the milliseconds between the 1st of January 1970 and the given date.
In our if
condition, we check if the timestamp
variable doesn't store a
number or stores NaN
.
Unfortunately, if you console.log(typeof NaN)
, we get back a "number"
value
back.
toISOString()
method to check if the Date
object's ISO 8601 formatted string starts with the provided string.The
toISOString()
method returns a string formatted as YYYY-MM-DDTHH:mm:ss.sssZ
.
If the ISO representation of the Date
object starts with the provided string,
then the date string is valid and formatted as DD/MM/YYYY
.