How to Validate a Date in JavaScript

avatar
Borislav Hadzhiev

Last updated: Mar 6, 2024
7 min

banner

# Table of Contents

  1. Check if a Date is valid using JavaScript
  2. Check if a Date is valid using Object.toString()
  3. Check if a Date is valid using duck-typing
  4. Validate a Date formatted as YYYY-MM-DD in JavaScript
  5. Validate a Date formatted as DD/MM/YYYY in JavaScript

# Check if a Date is valid using JavaScript

To check if a date is valid:

  1. Check if the date is an instance of the Date object.
  2. Check if passing the date to the isNaN() function returns false.
  3. If both conditions are met, the date is valid.
index.js
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

check if date is valid

The code for this article is available on GitHub

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.

index.js
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.

index.js
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).

If the value is not already a number, the 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.

index.js
// ๐Ÿ‘‡๏ธ 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.

If the 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.

# Check if a Date is valid using Object.toString()

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.

index.js
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

check if date is valid using object tostring

The code for this article is available on GitHub

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.

# Check if a Date is valid using duck-typing

Alternatively, you can use duck-typing.

index.js
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

check if date is valid using duck typing

The code for this article is available on GitHub
When using duck-typing, we simply check if the object implements specific properties or methods and if it does, we assume it's an object of the right type.

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.

# Validate a Date formatted as YYYY-MM-DD in JavaScript

To validate a date that is formatted as YYYY-MM-DD:

  1. Check if the string passes a regular expression check.
  2. Check if passing the string to the Date constructor returns a valid Date object.
  3. If both conditions are met, the string is formatted as YYYY-MM-DD.
index.js
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
The code for this article is available on GitHub

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.

The caret ^ 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.

If the provided string doesn't match the regular expression, we return 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.

index.js
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.

The last step is to use the 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.

# Validate a Date formatted as DD/MM/YYYY in JavaScript

To validate a date that is formatted as DD/MM/YYYY:

  1. Check if the string passes a regular expression check.
  2. Check if formatting the string as ISO and passing it to the Date constructor returns a valid Date object.
  3. If all of the conditions are met, the string is formatted correctly.
index.js
// โœ… 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
The code for this article is available on GitHub

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

index.js
// โœ… 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 code for this article is available on GitHub

The regex variable stores a regular expression.

The forward slashes / / mark the beginning and end of the regular expression.

The caret ^ 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.

If the provided string doesn't match the regular expression, we return 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.

index.js
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 code for this article is available on GitHub

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.

The last step is to use the 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.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev