How to validate date with format "mm/dd/yyyy" in JavaScript?
Asked Answered
C

25

161

I want to validate the date format on an input using the format mm/dd/yyyy.

I found below codes in one site and then used it but it doesn't work:

function isDate(ExpiryDate) { 
    var objDate,  // date object initialized from the ExpiryDate string 
        mSeconds, // ExpiryDate in milliseconds 
        day,      // day 
        month,    // month 
        year;     // year 
    // date length should be 10 characters (no more no less) 
    if (ExpiryDate.length !== 10) { 
        return false; 
    } 
    // third and sixth character should be '/' 
    if (ExpiryDate.substring(2, 3) !== '/' || ExpiryDate.substring(5, 6) !== '/') { 
        return false; 
    } 
    // extract month, day and year from the ExpiryDate (expected format is mm/dd/yyyy) 
    // subtraction will cast variables to integer implicitly (needed 
    // for !== comparing) 
    month = ExpiryDate.substring(0, 2) - 1; // because months in JS start from 0 
    day = ExpiryDate.substring(3, 5) - 0; 
    year = ExpiryDate.substring(6, 10) - 0; 
    // test year range 
    if (year < 1000 || year > 3000) { 
        return false; 
    } 
    // convert ExpiryDate to milliseconds 
    mSeconds = (new Date(year, month, day)).getTime(); 
    // initialize Date() object from calculated milliseconds 
    objDate = new Date(); 
    objDate.setTime(mSeconds); 
    // compare input date and parts from Date() object 
    // if difference exists then date isn't valid 
    if (objDate.getFullYear() !== year || 
        objDate.getMonth() !== month || 
        objDate.getDate() !== day) { 
        return false; 
    } 
    // otherwise return true 
    return true; 
}

function checkDate(){ 
    // define date string to test 
    var ExpiryDate = document.getElementById(' ExpiryDate').value; 
    // check date and print message 
    if (isDate(ExpiryDate)) { 
        alert('OK'); 
    } 
    else { 
        alert('Invalid date format!'); 
    } 
}

Any suggestion about what could be wrong?

Climber answered 30/5, 2011 at 15:11 Comment(4)
Welcome to StackOverflow. You can format source code with the {} toolbar button. I've done it for you this time. Also, try to provide some information about your problem: a doesn't work description is a useful as a then fix it solution.Vair
What kind of date formats are you trying to validate? Can you give some example of dates that should be valid?Mcdaniel
#1354184Pisolite
manishprajapati.in/blog/…Pert
C
243

I think Niklas has the right answer to your problem. Besides that, I think the following date validation function is a little bit easier to read:

// Validates that the input string is a valid date formatted as "mm/dd/yyyy"
function isValidDate(dateString)
{
    // First check for the pattern
    if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString))
        return false;

    // Parse the date parts to integers
    var parts = dateString.split("/");
    var day = parseInt(parts[1], 10);
    var month = parseInt(parts[0], 10);
    var year = parseInt(parts[2], 10);

    // Check the ranges of month and year
    if(year < 1000 || year > 3000 || month == 0 || month > 12)
        return false;

    var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

    // Adjust for leap years
    if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
        monthLength[1] = 29;

    // Check the range of the day
    return day > 0 && day <= monthLength[month - 1];
};
Capwell answered 30/5, 2011 at 15:51 Comment(8)
Remember to use the second argument to parseInt: parseInt(parts[0], 10). Otherwise, September's 09 is read as an octal and parses to 0Boucicault
A couple years down the line and this just saved me a fair bit of time, thanks for the sweet answer!Coping
Excellent post! Combines the regex formatting with the needed parsing for validation.Dendrochronology
I would suggest you change the regex to this: /^(\d{2}|\d{1})\/(\d{2}|\d{1})\/\d{4}$/ this way it catches one digit month and day 1/5/2014. Thanks for the sample!Archiearchiepiscopacy
@MitchLabrador - Thanks for the feedback. I improved the regex based on your suggestion.Capwell
Regex could be ^\d{1,2}[\-\s\/]\d{1,2}[\-\s\/]\d{4}$ to support all types of date in given format. space - / can work well.Telepathy
Two tests could be added, the first to verify the length of the date (10 characters) and the second about the length of the 'parts' array that should be 3 elements.Puffer
@Puffer - Note that these tests are already implicitly covered by the regex.Capwell
A
155

I would use Moment.js for date validation.

alert(moment("05/22/2012", 'MM/DD/YYYY',true).isValid()); //true

Jsfiddle: http://jsfiddle.net/q8y9nbu5/

true value is for strict parsing credit to @Andrey Prokhorov which means

you may specify a boolean for the last argument to make Moment use strict parsing. Strict parsing requires that the format and input match exactly, including delimeters.

Amateurism answered 4/7, 2016 at 4:48 Comment(4)
Use "M/D/YYYY" to allow 1-2 digits for Month & Day.Abbreviate
good to know that third parameter "true" stays for "use strict parsing" momentjs.com/docs/#/parsing/string-formatQuestionnaire
@Razan Paul hope you did not mind I added little explanation for more clarity. it wise not reinvent the wheels again and again, so pual's answer is the best one in my humble opinionSobersided
moment(dateString, 'MM/DD/YYYY', true).isValid() || moment(dateString, 'M/DD/YYYY', true).isValid() || moment(dateString, 'MM/D/YYYY', true).isValid();Playoff
C
52

Use the following regular expression to validate:

var date_regex = /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/;
if (!(date_regex.test(testDate))) {
    return false;
}

This is working for me for MM/dd/yyyy.

Charlesettacharleston answered 2/7, 2013 at 9:46 Comment(10)
How We will validate yyyy-mm-dd or invalid date like 9834-66-43Ibrahim
You can use /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/ to validate yyyy-mm-dd.Charlesettacharleston
this is awesome, since I for one hate formulating regex and two like their efficiency!Haddington
What happens in the year 3000? :)Accelerometer
What about leap year and month days variations?Bertrando
@TheOne..y3k problem.. :PQumran
what about month feb ? and date 30?Nailbrush
I remember there's a song by Elvis where he says that he's going to do something on "July 32nd". This regex would allow that.Article
@Ravi Kant Use additional validation by using the Date constructor but be aware that there is some odd behavior with it. When date is not valid it will return a string 'Invalid Date' (I was expecting an exception)Unpromising
No 30/31 check, no leap year check and never returns true. This is horrible. How did this get over 50 upvotes?Pun
D
37

All credits go to elian-ebbing

Just for the lazy ones here I also provide a customized version of the function for the format yyyy-mm-dd.

function isValidDate(dateString)
{
    // First check for the pattern
    var regex_date = /^\d{4}\-\d{1,2}\-\d{1,2}$/;

    if(!regex_date.test(dateString))
    {
        return false;
    }

    // Parse the date parts to integers
    var parts   = dateString.split("-");
    var day     = parseInt(parts[2], 10);
    var month   = parseInt(parts[1], 10);
    var year    = parseInt(parts[0], 10);

    // Check the ranges of month and year
    if(year < 1000 || year > 3000 || month == 0 || month > 12)
    {
        return false;
    }

    var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

    // Adjust for leap years
    if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
    {
        monthLength[1] = 29;
    }

    // Check the range of the day
    return day > 0 && day <= monthLength[month - 1];
}
Doorkeeper answered 1/5, 2014 at 9:29 Comment(3)
This validates '2020-5-1' as true while the leading zero's are ignored. I made it work by first testing the pattern of the year with /^(19|20)\d\d$/, the month with /^(0[0-9]|1[0-2])$/ and the day with /^(0[1-9]|[12][0-9]|3[01])$/ before parsing. Then it worked thanks.Sustenance
Also to test the pattern of the date for exactly yyyy-mm-dd format this regex /^\d{4}\-\d{1,2}\-\d{1,2}$/ will validate yyyy-mm-dd or yyyy-m-d as true, therefore it only validates the length not each individual date part. For precise length of yyyy-mm-dd without checking that the year, month and date is correct use /^\d{4}\-\d{2}\-\d{2}$/ instead.Sustenance
The required format is mm/dd/yyyy not yyyy-m-d.Pun
B
29

It's unusual to see a post so old on such a basic topic, with so many answers, none of them right. (I'm not saying none of them work.)

  • A leap-year determination routine is not needed for this. The language can do that work for us.
  • Moment is not needed for this.
  • Date.parse() shouldn't be used for local date strings. MDN says "It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent." The standard requires a (potentially simplified) ISO 8601 string; support for any other format is implementation-dependent.
  • Nor should new Date(string) be used, because that uses Date.parse().
  • IMO the leap day should be validated.
  • The validation function must account for the possibility that the input string doesn't match the expected format. For example, '1a/2a/3aaa', '1234567890', or 'ab/cd/efgh'.

Here's an efficient, concise solution with no implicit conversions. It takes advantage of the Date constructor's willingness to interpret 2018-14-29 as 2019-03-01. It does use a couple modern language features, but those are easily removed if needed. I've also included some tests.

function isValidDate(s) {
  // Assumes s is "mm/dd/yyyy"
  if (!/^\d\d\/\d\d\/\d\d\d\d$/.test(s)) {
    return false;
  }
  const parts = s.split('/').map((p) => parseInt(p, 10));
  parts[0] -= 1;
  const d = new Date(parts[2], parts[0], parts[1]);
  return d.getMonth() === parts[0] && d.getDate() === parts[1] && d.getFullYear() === parts[2];
}

function testValidDate(s) {
  console.log(s, isValidDate(s));
}
testValidDate('01/01/2020'); // true
testValidDate('02/29/2020'); // true
testValidDate('02/29/2000'); // true
testValidDate('02/29/1900'); // false
testValidDate('02/29/2019'); // false
testValidDate('01/32/1970'); // false
testValidDate('13/01/1970'); // false
testValidDate('14/29/2018'); // false
testValidDate('1a/2b/3ccc'); // false
testValidDate('1234567890'); // false
testValidDate('aa/bb/cccc'); // false
testValidDate(null); // false
testValidDate(''); // false
Belgae answered 22/6, 2020 at 15:3 Comment(1)
Nice answer. Could improve readability using const [mm, dd, yyyy] = date.split('/').map((p) => parseInt(p)); instead of parts[x]Omen
C
21

You could use Date.parse()

You can read in MDN documentation

The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in some cases, contains illegal date values (e.g. 2015-02-31).

And check if the result of Date.parse isNaN

let isValidDate = Date.parse('01/29/1980');

if (isNaN(isValidDate)) {
  // when is not valid date logic

  return false;
}

// when is valid date logic

Please take a look when is recommended to use Date.parse in MDN

Claudell answered 8/3, 2018 at 16:50 Comment(4)
Date.parse will give you a valid parse with a date such as "46/7/17"Admittedly
Will return true result for yyyy/02/30Vandyke
Downvoted as this will allow garbage through. e.g. Date.parse('01//////29//000')Fund
The question is specifically about the mm/dd/yyyy format, not anything vaguely resembling a date that can be parsed.Pun
M
12

It appears to be working fine for mm/dd/yyyy format dates, example:

http://jsfiddle.net/niklasvh/xfrLm/

The only problem I had with your code was the fact that:

var ExpiryDate = document.getElementById(' ExpiryDate').value;

Had a space inside the brackets, before the element ID. Changed it to:

var ExpiryDate = document.getElementById('ExpiryDate').value;

Without any further details regarding the type of data that isn't working, there isn't much else to give input on.

Mcdaniel answered 30/5, 2011 at 15:24 Comment(1)
Please post the code here. You can click edit and then [<>] to make a snippet here if you wish to keep the answer in the questionMurrumbidgee
A
11

The function will return true if the given string is in the right format('MM/DD/YYYY') else it will return false. (I found this code online & modified it a little)

function isValidDate(date) {
    var temp = date.split('/');
    var d = new Date(temp[2] + '/' + temp[0] + '/' + temp[1]);
    return (d && (d.getMonth() + 1) == temp[0] && d.getDate() == Number(temp[1]) && d.getFullYear() == Number(temp[2]));
}

console.log(isValidDate('02/28/2015'));
            
Allheal answered 23/6, 2016 at 11:47 Comment(2)
This accepts ˙'1/010/100˙ which isn't in mm/dd/yyyy format.Pun
And this code looks almost exactly the same as an existing answer, except that it tries to validate mm/dd/yyyy instead of dd/mm/yyyy.Pun
P
4

It's ok if you want to check validate dd/MM/yyyy

function isValidDate(date) {
    var temp = date.split('/');
    var d = new Date(temp[1] + '/' + temp[0] + '/' + temp[2]);
     return (d && (d.getMonth() + 1) == temp[1] && d.getDate() == Number(temp[0]) && d.getFullYear() == Number(temp[2]));
}

alert(isValidDate('29/02/2015')); // it not exist ---> false
            
Pricefixing answered 8/6, 2018 at 7:25 Comment(1)
The question is about validating mm/dd/yyyy, not dd/mm/yyyy. And this considers '1/010/100' a valid format.Pun
O
4

Expanding (or better contracting) on @Jay Dunnings answer, the following two-liner uses the Intl API and ES6 destructuring. It passes all tests given by Jay Dunning.

/**
 * @param {string} date
 * @returns {boolean} true if date is of the form mm/dd/yyyy
 */
function is_en_US_date(date) {
    const [match, mm, dd, yyyy] = /^(\d\d)[/](\d\d)[/](\d{4})$/.exec(date) || [];
    return match !== undefined && new Intl.DateTimeFormat('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' }).format(new Date(yyyy, mm-1, dd)) === date
}
Omen answered 24/3, 2021 at 20:24 Comment(0)
P
2

Here is one snippet to check for valid date:

function validateDate(dateStr) {
   const regExp = /^(\d\d?)\/(\d\d?)\/(\d{4})$/;
   let matches = dateStr.match(regExp);
   let isValid = matches;
   let maxDate = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
   
   if (matches) {
     const month = parseInt(matches[1]);
     const date = parseInt(matches[2]);
     const year = parseInt(matches[3]);
     
     isValid = month <= 12 && month > 0;
     isValid &= date <= maxDate[month] && date > 0;
     
     const leapYear = (year % 400 == 0)
        || (year % 4 == 0 && year % 100 != 0);
     isValid &= month != 2 || leapYear || date <= 28; 
   }
   
   return isValid
}

console.log(['1/1/2017', '01/1/2017', '1/01/2017', '01/01/2017', '13/12/2017', '13/13/2017', '12/35/2017'].map(validateDate));
Purgative answered 4/12, 2017 at 6:37 Comment(1)
1/1/2017 isn't in the format mm/dd/yyyy.Pun
K
2

Alternative

This question has already been answered ad nauseum, I know, but I'd like to throw myself to the SO wolves by proposing an alternative solution.

AFAICT, this method isn't presented in any of the other answers. And maybe there's some edge case that I'm not considering... I'm sure y'all will duly roast me if so.

Someone once said-- Jesus or Confucius, maybe --

When you decide to solve a problem with regex, now you have two problems

That said, I love regex and use it on a regular basis for other things; however, recently, I ran into an issue with one of the top answers on here, which threw a false positive for an invalid date. It used too strict a regex. I replaced said check of a date string (dd/dd/dddd) with the following:

const isInvalidDate = (dateString) => new Date(dateString).toString() === 'Invalid Date'

console.log(isInvalidDate('asdf')) //> true
console.log(isInvalidDate('09/29/1985')) //> false

Edit 2022

My alternative solution remains the same since I posted it, but it could perhaps be better written in a non-negative-ish form to minimize cognitive strain. So, if you're gonna copy-paste it, copy-paste this instead:

const isValidDate = (dateString) => new Date(dateString).toString() !== 'Invalid Date'

console.log(isValidDate('asdf')) //> false
console.log(isValidDate('09/29/1985')) //> true

Why am I still talking?

As @jay-dunning points out above, this solution may not be ideal for some applications (presumably those implemented in <ES5? cough). I'm not at all compelled to stop using my solution, but just beware:

  • Date.parse() shouldn't be used for local date strings. MDN says "It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent." The standard requires a
    (potentially simplified) ISO 8601 string; support for any other
    format is implementation-dependent.
  • Nor should new Date(string) be used, because that uses Date.parse().
Kythera answered 12/8, 2021 at 13:37 Comment(1)
The question is specifically about the mm/dd/yyyy format, not anything vaguely resembling a date that can be parsed.Pun
L
1

Find in the below code which enables to perform the date validation for any of the supplied format to validate start/from and end/to dates. There could be some better approaches but have come up with this. Note supplied date format and date string go hand in hand.

function validate() {

  var format = 'yyyy-MM-dd';

  if (isAfterCurrentDate(document.getElementById('start').value, format)) {
    console.log('Date is after the current date.');
  } else {
    console.log('Date is not after the current date.');
  }
  if (isBeforeCurrentDate(document.getElementById('start').value, format)) {
    console.log('Date is before current date.');
  } else {
    console.log('Date is not before current date.');
  }
  if (isCurrentDate(document.getElementById('start').value, format)) {
    console.log('Date is current date.');
  } else {
    console.log('Date is not a current date.');
  }
  if (isBefore(document.getElementById('start').value, document.getElementById('end').value, format)) {
    console.log('Start/Effective Date cannot be greater than End/Expiration Date');
  } else {
    console.log('Valid dates...');
  }
  if (isAfter(document.getElementById('start').value, document.getElementById('end').value, format)) {
    console.log('End/Expiration Date cannot be less than Start/Effective Date');
  } else {
    console.log('Valid dates...');
  }
  if (isEquals(document.getElementById('start').value, document.getElementById('end').value, format)) {
    console.log('Dates are equals...');
  } else {
    console.log('Dates are not equals...');
  }
  if (isDate(document.getElementById('start').value, format)) {
    console.log('Is valid date...');
  } else {
    console.log('Is invalid date...');
  }
}

/**
 * This method gets the year index from the supplied format
 */
function getYearIndex(format) {

  var tokens = splitDateFormat(format);

  if (tokens[0] === 'YYYY' ||
    tokens[0] === 'yyyy') {
    return 0;
  } else if (tokens[1] === 'YYYY' ||
    tokens[1] === 'yyyy') {
    return 1;
  } else if (tokens[2] === 'YYYY' ||
    tokens[2] === 'yyyy') {
    return 2;
  }
  // Returning the default value as -1
  return -1;
}

/**
 * This method returns the year string located at the supplied index
 */
function getYear(date, index) {

  var tokens = splitDateFormat(date);
  return tokens[index];
}

/**
 * This method gets the month index from the supplied format
 */
function getMonthIndex(format) {

  var tokens = splitDateFormat(format);

  if (tokens[0] === 'MM' ||
    tokens[0] === 'mm') {
    return 0;
  } else if (tokens[1] === 'MM' ||
    tokens[1] === 'mm') {
    return 1;
  } else if (tokens[2] === 'MM' ||
    tokens[2] === 'mm') {
    return 2;
  }
  // Returning the default value as -1
  return -1;
}

/**
 * This method returns the month string located at the supplied index
 */
function getMonth(date, index) {

  var tokens = splitDateFormat(date);
  return tokens[index];
}

/**
 * This method gets the date index from the supplied format
 */
function getDateIndex(format) {

  var tokens = splitDateFormat(format);

  if (tokens[0] === 'DD' ||
    tokens[0] === 'dd') {
    return 0;
  } else if (tokens[1] === 'DD' ||
    tokens[1] === 'dd') {
    return 1;
  } else if (tokens[2] === 'DD' ||
    tokens[2] === 'dd') {
    return 2;
  }
  // Returning the default value as -1
  return -1;
}

/**
 * This method returns the date string located at the supplied index
 */
function getDate(date, index) {

  var tokens = splitDateFormat(date);
  return tokens[index];
}

/**
 * This method returns true if date1 is before date2 else return false
 */
function isBefore(date1, date2, format) {
  // Validating if date1 date is greater than the date2 date
  if (new Date(getYear(date1, getYearIndex(format)),
      getMonth(date1, getMonthIndex(format)) - 1,
      getDate(date1, getDateIndex(format))).getTime() >
    new Date(getYear(date2, getYearIndex(format)),
      getMonth(date2, getMonthIndex(format)) - 1,
      getDate(date2, getDateIndex(format))).getTime()) {
    return true;
  }
  return false;
}

/**
 * This method returns true if date1 is after date2 else return false
 */
function isAfter(date1, date2, format) {
  // Validating if date2 date is less than the date1 date
  if (new Date(getYear(date2, getYearIndex(format)),
      getMonth(date2, getMonthIndex(format)) - 1,
      getDate(date2, getDateIndex(format))).getTime() <
    new Date(getYear(date1, getYearIndex(format)),
      getMonth(date1, getMonthIndex(format)) - 1,
      getDate(date1, getDateIndex(format))).getTime()
  ) {
    return true;
  }
  return false;
}

/**
 * This method returns true if date1 is equals to date2 else return false
 */
function isEquals(date1, date2, format) {
  // Validating if date1 date is equals to the date2 date
  if (new Date(getYear(date1, getYearIndex(format)),
      getMonth(date1, getMonthIndex(format)) - 1,
      getDate(date1, getDateIndex(format))).getTime() ===
    new Date(getYear(date2, getYearIndex(format)),
      getMonth(date2, getMonthIndex(format)) - 1,
      getDate(date2, getDateIndex(format))).getTime()) {
    return true;
  }
  return false;
}

/**
 * This method validates and returns true if the supplied date is 
 * equals to the current date.
 */
function isCurrentDate(date, format) {
  // Validating if the supplied date is the current date
  if (new Date(getYear(date, getYearIndex(format)),
      getMonth(date, getMonthIndex(format)) - 1,
      getDate(date, getDateIndex(format))).getTime() ===
    new Date(new Date().getFullYear(),
      new Date().getMonth(),
      new Date().getDate()).getTime()) {
    return true;
  }
  return false;
}

/**
 * This method validates and returns true if the supplied date value 
 * is before the current date.
 */
function isBeforeCurrentDate(date, format) {
  // Validating if the supplied date is before the current date
  if (new Date(getYear(date, getYearIndex(format)),
      getMonth(date, getMonthIndex(format)) - 1,
      getDate(date, getDateIndex(format))).getTime() <
    new Date(new Date().getFullYear(),
      new Date().getMonth(),
      new Date().getDate()).getTime()) {
    return true;
  }
  return false;
}

/**
 * This method validates and returns true if the supplied date value 
 * is after the current date.
 */
function isAfterCurrentDate(date, format) {
  // Validating if the supplied date is before the current date
  if (new Date(getYear(date, getYearIndex(format)),
      getMonth(date, getMonthIndex(format)) - 1,
      getDate(date, getDateIndex(format))).getTime() >
    new Date(new Date().getFullYear(),
      new Date().getMonth(),
      new Date().getDate()).getTime()) {
    return true;
  }
  return false;
}

/**
 * This method splits the supplied date OR format based 
 * on non alpha numeric characters in the supplied string.
 */
function splitDateFormat(dateFormat) {
  // Spliting the supplied string based on non characters
  return dateFormat.split(/\W/);
}

/*
 * This method validates if the supplied value is a valid date.
 */
function isDate(date, format) {
  // Validating if the supplied date string is valid and not a NaN (Not a Number)
  if (!isNaN(new Date(getYear(date, getYearIndex(format)),
      getMonth(date, getMonthIndex(format)) - 1,
      getDate(date, getDateIndex(format))))) {
    return true;
  }
  return false;
}
<input type="text" name="start" id="start" size="10" value="" />
<br/>
<input type="text" name="end" id="end" size="10" value="" />
<br/>
<input type="button" value="Submit" onclick="validate();" />
Leah answered 21/11, 2014 at 9:18 Comment(1)
That's way too much code to just validate a date. And if the required format is mm/dd/yyyy I don't want it to accept 10.10.10.Pun
R
1

Moment is really a good one to resolve it. I don't see reason to add complexity just to check date... take a look on moment : http://momentjs.com/

HTML :

<input class="form-control" id="date" name="date" onchange="isValidDate(this);" placeholder="DD/MM/YYYY" type="text" value="">

Script :

 function isValidDate(dateString)  {
    var dateToValidate = dateString.value
    var isValid = moment(dateToValidate, 'MM/DD/YYYY',true).isValid()
    if (isValid) {
        dateString.style.backgroundColor = '#FFFFFF';
    } else {
        dateString.style.backgroundColor = '#fba';
    }   
};
Rosanarosane answered 7/2, 2019 at 23:31 Comment(0)
C
1

My answer supports five formats of date with easy codes and comments

/**
     * Validate a date 
     * @param {string} value 
     * Allowed formates are:
     * 1) YYYY-DD-MM this is default format
     * 2) YYYY/DD/MM
     * 3) MM/DD/YYYY
     * 4) DD/MM/YYYY
     * 5) YYYY-MM-DD
     * 
     */
    function verifyDate(value, format = "YYYY-DD-MM") {
        /**
         * The default format is YYYY-DD-MM
         * and
         * @var monthIndex When we split the date string into an array then to support
         * different formats like YYYY-DD-MM we need to track the
         * index of month, day and year i.e here month is at 2 index 
         * where as in MM/DD/YYYY month is at 0 index. Same goes for 
         * dayIndex and yearIndex.
         */
        let regex = /^\d{4}-\d{1,2}-\d{1,2}$/, 
            monthIndex = 2, 
            dayIndex = 1, 
            yearIndex = 0;
        /**
         * In these if else we are updating
         * regex and indexes for month, day and year.
         */
        if(format == "YYYY-MM-DD"){
                monthIndex = 1;
                dayIndex = 2;
            }
            else if(format == "YYYY/DD/MM"){
                regex = /^\d{4}\/\d{1,2}\/\d{1,2}$/;
            }
            else if(format == "MM/DD/YYYY" || format == "DD/MM/YYYY"){
                regex = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
                let bool = format == "DD/MM/YYYY";
                /**
                 * If format === "DD/MM/YYYY" means
                 * here day in at 0 index and month is at index 1.
                 * The other possible format inside this else if condition
                 * can be "MM/DD/YYYY" where month is
                 * at 0 index and date at 1 index.
                 * In both conditions year index is at 2.
                 */
                monthIndex = bool ? 1 : 0;
                dayIndex = bool ? 0 : 1; 
                yearIndex = 2;
            }  
        // First check for the pattern
        if (!regex.test(value))
            return false;
        /**
         * Check that is date is like this 
         * YYYY-DD-MM or YYYY/DD/MM 
         * splited with dashes "-" or slashes "/".
        */
        let splitChar = value.includes('-') ? '-' : '/',
        /**
         * Split the date string into an array and convert
         * every string into number
         */
        date = value.split(splitChar).map(Number),
        /**
         * Now use our day, month and year
         * indexes to get the day, month and year respectively 😁.
         */
        day = date[dayIndex],
        month = date[monthIndex],
        year = date[yearIndex];

        // Check the ranges for possible dates
        if (year < 1000 || year > 3000 || month < 1 || month > 12 || day < 1)
            return false;

        const months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

        // Check for leap years.
        if ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0))
            months[1] = 29;

        // Check that day should not be more than the month length
        return day <= months[month - 1];
    };
Colter answered 21/10, 2023 at 22:7 Comment(0)
R
0
function fdate_validate(vi)
{
  var parts =vi.split('/');
  var result;
  var mydate = new Date(parts[2],parts[1]-1,parts[0]);
  if (parts[2] == mydate.getYear() && parts[1]-1 == mydate.getMonth() && parts[0] == mydate.getDate() )
  {result=0;}
  else
  {result=1;}
  return(result);
}
Reft answered 23/6, 2017 at 1:6 Comment(2)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Comedo
This doesn't work at all. It always returns 1 which for some reason indicates invalid date.Pun
G
0

Date is complex. The best way to validate it is using package like Luxon , date-fns, or DayJS.

Using date-fns:

import {isMatch} from 'date-fns'

const match = isMatch('12/25/2010', 'MM/dd/yyyy') // true
Germann answered 2/5, 2021 at 2:56 Comment(5)
This doesn't work, it returns false.Pun
yes, you are right, the argument is wrong, I edit it with the correct one.Germann
this is not working: console.log(isMatch("12/25/2", "MM/dd/yyyy")); // true console.log(isMatch("1/5/2", "MM/dd/yyyy")); // true this are completly invalid dates this seems not to be correctSampson
@RalfHannuschka, that is a valid date, 25 December 2 and 5 January 2.Germann
@AbrahamAnakAgung yeah Date is maybe valid but it should match the pattern like MM/dd/yyyy and i would say 1/5/2 does not match the pattern for Month(2 digits)/Day(2 digits)/Year(4 digits) but for date-fns it matches.Sampson
D
0
function isValidDate(dateString) {
  // Regular expression for the "mm/dd/yyyy" format
  var dateFormat = /^\d{2}\/\d{2}\/\d{4}$/;

  // Check if the input matches the date format
  if (!dateString.match(dateFormat)) {
    return false;
  }

  // Parse the date using the Date object
  var date = new Date(dateString);

  // Check if the parsed date is a valid date
  if (isNaN(date.getTime())) {
    return false;
  }

  // Check if the parsed date matches the input date
  return (
    date.getDate() == parseInt(dateString.substring(3, 5), 10) &&
    date.getMonth() + 1 == parseInt(dateString.substring(0, 2), 10) &&
    date.getFullYear() == parseInt(dateString.substring(6), 10)
  );
}

// Example usage
var inputDate = "02/05/2024";
if (isValidDate(inputDate)) {
  console.log(inputDate + " is a valid date.");
} else {
  console.log(inputDate + " is not a valid date.");
}

function uses a regular expression to check if the input string matches the "mm/dd/yyyy" format. If it does, it then tries to parse the date using the Date object and checks if the parsed date is valid and matches the input date.

Doud answered 5/2 at 15:33 Comment(0)
L
-1

Similar to Elian Ebbing answer, but support "\", "/", ".", "-", " " delimiters

function js_validate_date_dmyyyy(js_datestr)
{
    var js_days_in_year = [ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
    var js_datepattern = /^(\d{1,2})([\.\-\/\\ ])(\d{1,2})([\.\-\/\\ ])(\d{4})$/;

    if (! js_datepattern.test(js_datestr)) { return false; }

    var js_match = js_datestr.match(js_datepattern);
    var js_day = parseInt(js_match[1]);
    var js_delimiter1 = js_match[2];
    var js_month = parseInt(js_match[3]);
    var js_delimiter2 = js_match[4];
    var js_year = parseInt(js_match[5]);                            

    if (js_is_leap_year(js_year)) { js_days_in_year[2] = 29; }

    if (js_delimiter1 !== js_delimiter2) { return false; } 
    if (js_month === 0  ||  js_month > 12)  { return false; } 
    if (js_day === 0  ||  js_day > js_days_in_year[js_month])   { return false; } 

    return true;
}

function js_is_leap_year(js_year)
{ 
    if(js_year % 4 === 0)
    { 
        if(js_year % 100 === 0)
        { 
            if(js_year % 400 === 0)
            { 
                return true; 
            } 
            else return false; 
        } 
        else return true; 
    } 
    return false; 
}
Lammastide answered 8/4, 2017 at 22:46 Comment(2)
your days and months are backwards.Cavafy
"30.7.2022" is't a valid mm/dd/yyyy format.Pun
S
-1
  1. Javascript

    function validateDate(date) {
        try {
            new Date(date).toISOString();
            return true;
        } catch (e) { 
            return false; 
        }
    }
    
  2. JQuery

    $.fn.validateDate = function() {
        try {
            new Date($(this[0]).val()).toISOString();
            return true;
        } catch (e) { 
            return false; 
        }
    }
    

returns true for a valid date string.

Sally answered 4/3, 2020 at 18:15 Comment(1)
The requirement is specifically for the format mm/dd/yyyy. validateDate("2022-10-04") shouldn't return true.Pun
S
-1

we can use customized function or date pattern. Below code is customized function as per your requirement please change it.

 function isValidDate(str, separator = '-') {
    var getvalue = str.split(separator);
    var day = parseInt(getvalue[2]);
    var month = parseInt(getvalue[1]);
    var year = parseInt(getvalue[0]);
    if(year < 1901 || year > 2100){
       return false;
    }
    if (month < 1 || month > 12) { 
       return false;
    }
    if (day < 1 || day > 31) {
       return false;
    }
    if ((month==4 && month==6 && month==9 && month==11) && day==31) {
       return false;
    }
    if (month == 2) { // check for february 29th
       var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
       if (day>29 || (day==29 && !isleap)) {
          return false;
       }
    }
    else{
       return true;
    }
    return true;
}
Sanderlin answered 22/5, 2020 at 20:18 Comment(1)
The required format is mm/dd/yyyy not yyyy-m-d. And isValidDate("failure") returns true.Pun
P
-1
function validatedate(inputText, DateFormat) {
    // format dd/mm/yyyy or in any order of (dd or mm or yyyy) you can write dd or mm or yyyy in first or second or third position ... or can be slash"/" or dot"." or dash"-" in the dates formats
    var invalid = "";
    var dt = "";
    var mn = "";
    var yr = "";
    var k;
    var delm = DateFormat.includes("/") ? "/" : ( DateFormat.includes("-") ? "-" : ( DateFormat.includes(".") ? "." : "" ) ) ;
    var f1 = inputText.split(delm);
    var f2 = DateFormat.split(delm);
    for(k=0;k<=2;k++) { 
        dt = dt + (f2[parseInt(k)]=="dd" ? f1[parseInt(k)] : "");
        mn = mn + (f2[parseInt(k)]=="mm" ? f1[parseInt(k)] : "");
        yr = yr + (f2[parseInt(k)]=="yyyy" ? f1[parseInt(k)] : "");
    }
    var mn_days = "0-31-" + (yr % 4 == 0 ? 29 : 28) + "-31-30-31-30-31-31-30-31-30-31";
    var days = mn_days.split("-");
    if (f1.length!=3 ||
    mn.length>2 ||
    dt.length>2 ||
    yr.length!=4 ||
    !(parseInt(mn)>=1 && parseInt(mn)<=12) ||
    !(parseInt(yr)>=parseInt(1900) && parseInt(yr)<=parseInt(2100)) ||
    !(parseInt(dt)>=1 && parseInt(dt)<=parseInt(days[parseInt(mn)]))) {
        invalid = "true";
    }
    alert( ( invalid=="true" ? "Invalid Date" : "Valid Date")  );
}
Paternal answered 10/7, 2021 at 11:28 Comment(2)
Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.Synonymous
Why are you parsing integers into integers? Why are you parsing the same string multiple times? Why are you building a string and then spiting it just to get an array? Just make an array. Why are you assigning strings "true" and ""` instead of booleans true and false? Why are you using an alert instead of just returning the result. This also doesn't properly calculate leap years. 1900 and 2100 aren't leap years.Pun
K
-2

First string date is converted to js date format and converted into string format again, then it is compared with original string.

function dateValidation(){
    var dateString = "34/05/2019"
    var dateParts = dateString.split("/");
    var date= new Date(+dateParts[2], dateParts[1] - 1, +dateParts[0]);

    var isValid = isValidDate( dateString, date );
    console.log("Is valid date: " + isValid);
}

function isValidDate(dateString, date) {
    var newDateString = ( date.getDate()<10 ? ('0'+date.getDate()) : date.getDate() )+ '/'+ ((date.getMonth() + 1)<10? ('0'+(date.getMonth() + 1)) : (date.getMonth() + 1) )  + '/' +  date.getFullYear();
    return ( dateString == newDateString);
}
Keyway answered 4/4, 2019 at 7:39 Comment(2)
This will not run because ìsValid` is not a function.Omen
The required format is mm/dd/yyyy not dd/mm/yyyyPun
P
-4
var date = new Date(date_string)

returns the literal 'Invalid Date' for any invalid date_string.

Note: Please see the comment's below.

Pisolite answered 4/1, 2016 at 16:39 Comment(5)
False: new Date("02-31-2000") gives Thu Mar 02 2000 00:00:00 GMT-0300 (BRT).Bertrando
#1354184Pisolite
To elaborate further about the use case where it doesn't work, please, read the first note from Mozilla's Date parameters documentation.Bertrando
Yeah, I'm leaving this up primarily to show that they're are alternatives to writing ad-hoc parses. The link above is authoritative. Nice doc though!Pisolite
This doesn't validate for the required format.Pun
P
-5

function validatedate(inputText, dateFormat) {
  var minYear = 1950;
  var maxYear = 2050;
  inputText = inputText.toLowerCase();
  if (dateFormat == "dd/mmm/yyyy" || dateFormat == "dd-mmm-yyyy" || dateFormat == "dd.mmm.yyyy" || dateFormat == "dd/yyyy/mmm" || dateFormat == "dd-yyyy-mmm" || dateFormat == "dd.yyyy.mmm" || dateFormat == "mmm/dd/yyyy" || dateFormat == "mmm-dd-yyyy" || dateFormat == "mmm.dd.yyyy" || dateFormat == "mmm/yyyy/dd" || dateFormat == "mmm-yyyy-dd" || dateFormat == "mmm.yyyy.dd" || dateFormat == "yyyy/mmm/dd" || dateFormat == "yyyy-mmm-dd" || dateFormat == "yyyy.mmm.dd" || dateFormat == "yyyy/dd/mmm" || dateFormat == "yyyy-dd-mmm" || dateFormat == "yyyy.dd.mmm") {
    dateFormat = dateFormat.replace("mmm", "mm");
    inputText = inputText.replace("jan", "01");
    inputText = inputText.replace("feb", "02");
    inputText = inputText.replace("mar", "03");
    inputText = inputText.replace("apr", "04");
    inputText = inputText.replace("may", "05");
    inputText = inputText.replace("jun", "06");
    inputText = inputText.replace("jul", "07");
    inputText = inputText.replace("aug", "08");
    inputText = inputText.replace("sep", "09");
    inputText = inputText.replace("oct", "10");
    inputText = inputText.replace("nov", "11");
    inputText = inputText.replace("dec", "12");
  }


  var w;
  var q;
  var delm;
  delm1 = "/";

  for (w = 0; w < inputText.length; w++) {
    q = inputText.charAt(w);
    if (q == '0' || q == '1' || q == '2' || q == '3' || q == '4' || q == '5' || q == '6' || q == '7' || q == '8' || q == '9' || q == '/') {} else {
      delm1 = "";
    }
  }
  delm2 = "-";

  for (w = 0; w < inputText.length; w++) {
    q = inputText.charAt(w);
    if (q == '0' || q == '1' || q == '2' || q == '3' || q == '4' || q == '5' || q == '6' || q == '7' || q == '8' || q == '9' || q == '-') {} else {
      delm2 = "";
    }
  }

  delm3 = ".";

  for (w = 0; w < inputText.length; w++) {
    q = inputText.charAt(w);
    if (q == '0' || q == '1' || q == '2' || q == '3' || q == '4' || q == '5' || q == '6' || q == '7' || q == '8' || q == '9' || q == '.') {} else {
      delm3 = "";
    }
  }

  var delm;
  if (delm1 == "/" && (dateFormat == "dd/mm/yyyy" || dateFormat == "mm/dd/yyyy" || dateFormat == "dd/yyyy/mm" || dateFormat == "mm/yyyy/dd" || dateFormat == "yyyy/mm/dd" || dateFormat == "yyyy/dd/mm")) {
    delm = "/";
  }

  if (delm2 == "-" && (dateFormat == "dd-mm-yyyy" || dateFormat == "mm-dd-yyyy" || dateFormat == "dd-yyyy-mm" || dateFormat == "mm-yyyy-dd" || dateFormat == "yyyy-mm-dd" || dateFormat == "yyyy-dd-mm")) {
    delm = "-";
  }
  if (delm3 == "." && (dateFormat == "dd.mm.yyyy" || dateFormat == "mm.dd.yyyy" || dateFormat == "dd.yyyy.mm" || dateFormat == "mm.yyyy.dd" || dateFormat == "yyyy.mm.dd" || dateFormat == "yyyy.dd.mm")) {
    delm = ".";
  }

  var invalid;
  var f = "31/12/2000";
  f = inputText;
  var ln = f.length;
  var dt;
  var mn;
  var yr;
  var t = f.split(delm);
  var j = t.length;
  if (j == 3) {
    dt = t[0];
    mn = t[1];
    yr = t[2];

    if (dateFormat == "mm.dd.yyyy" || dateFormat == "mm/dd/yyyy" || dateFormat == "mm-dd-yyyy") {
      var tmp = mn;
      mn = dt;
      dt = tmp;
    }

    if (dateFormat == "dd.yyyy.mm" || dateFormat == "dd/yyyy/mm" || dateFormat == "dd-yyyy-mm") {
      var tmp = mn;
      mn = yr;
      yr = tmp;
    }
    if (dateFormat == "mm.yyyy.dd" || dateFormat == "mm/yyyy/dd" || dateFormat == "mm-yyyy-dd") {
      var m1 = mn;
      var d1 = dt;
      var y1 = yr;
      mn = d1;
      yr = m1;
      dt = y1;
    }

    if (dateFormat == "yyyy.mm.dd" || dateFormat == "yyyy/mm/dd" || dateFormat == "yyyy-mm-dd") {
      var m1 = mn;
      var d1 = dt;
      var y1 = yr;
      mn = m1;
      yr = d1;
      dt = y1;
    }

    if (dateFormat == "yyyy.dd.mm" || dateFormat == "yyyy/dd/mm" || dateFormat == "yyyy-dd-mm") {
      var m1 = mn;
      var d1 = dt;
      var y1 = yr;
      mn = y1;
      yr = d1;
      dt = m1;
    }

    if (parseInt(yr) >= parseInt(minYear) && parseInt(yr) <= parseInt(maxYear)) {
      // do nothing
    } else {
      invalid = true;
    }
    if (mn.length > 2) {
      invalid = true;
    }
    if (dt.length > 2) {
      invalid = true;
    }

    if (t[0] == "") {
      invalid = true;
    }
    if (t[1] == "") {
      invalid = true;
    }
    if (t[2] == "") {
      invalid = true;
    }

    if (j != 3) {
      invalid = true;
    }
    var dc;
    var daysArray = "0-31-28-31-30-31-30-31-31-30-31-30-31";

    if ((yr % 4) == 0) {
      daysArray = "0-31-29-31-30-31-30-31-31-30-31-30-31";
    }
    var days = daysArray.split("-");
    if (parseInt(dt) >= 1 && parseInt(dt) <= days[parseInt(mn)]) {} else {
      invalid = true;
    }

    if (yr.length != 4) {
      invalid = true;
    }

    var i;
    var m;

    for (i = 0; i < ln; i++) {
      m = f.charAt(i);
      if (m == '0' || m == '1' || m == '2' || m == '3' || m == '4' || m == '5' || m == '6' || m == '7' || m == '8' || m == '9' || m == delm) {} else {
        invalid = true;
      }
    }
  } else {
    invalid = true;
  }

  console.log(inputText,invalid ? "Invalid Date" : "Valid Date");

}
Paternal answered 26/6, 2021 at 19:13 Comment(3)
This is a long solution. When you're converting capital letters to lower case letters instead of using many String.prototype.replace methods you could use one String.prototype.toLowerCase. You also use /, -, and . as delimiters between days, months, and years. Instead of hardcoding this you could generate these formats with the delimiters.Spherics
This is a lengthy code but it is implementable and in working condition in almost every date format if you want to validate datePaternal
There is way better and shorter code for validation than this. This code is completely unnecessarily complex and doesn't even return the result and instead uses the annoying alert.Pun

© 2022 - 2024 — McMap. All rights reserved.