1

I wrote a function to check if a date is valid

I wrote all except one small part

The function does not work and I cannot find the error, can you kindly help?

I can see that because the number 29 is not in the array it's not working however am confuddled how to get it to work

function isValidDate() {
  var dateformat = /^(0?[1-9]|[12][0-9]|3[01])[-](0?[1-9]|1[012])[-]\d{4}$/;

  var readDate = document.getElementById("myDate").value;

  if (readDate.length <= 10) {
    <!--debug-->
    //console.log(readDate);

    /* split date into DD-MM-YYYY format */
    var splitDate = readDate.split('-');

    var day = splitDate[0];

    var month = splitDate[1];

    var year = splitDate[2];

    /* DEBUG - print split date into DD-MM-YYYY format */
    console.log('day ' + day);
    console.log('month ' + month);
    console.log('year ' + year);

    // Create list of days of a month [assume there is no leap year by default]  
    var ListofDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    //if month is between 1-12
    if (month == 1 || month < 13) {
      //check for invalid month
      if (month == 00) {
        console.log('0 - Invalid MONTH format!');
        return 0;
      }

      //check for invalid day
      if (day == 00) {
        console.log('0 - Invalid DAY format!');
        return 0;
      }

      //check DAY exists in the MONTH
      if (day > ListofDays[month - 1]) {
        console.log('1 - Invalid DATE format!');
        return 0;
      } else {
        console.log('1 - Valid DATE format!');
        return 1
      }
    } else {
      console.log("Invalid MONTH");
      return 0;
    }

    //check for leap year
    if (year % 4 === 0 && year % 100 !== 0) {
      console.log('The year ' + year + ' is a leap year.');
      return 1;
    } else if (year % 4 === 0 && year % 100 === 0 && year % 400 === 0) {
      console.log('The year ' + year + ' is a leap year.');
      return 1;
    } else {
      console.log('The year ' + year + ' is NOT a leap year');
      return 0;
    }
  } else {
    console.log("Invalid DATE length")
  }
}


/*    This is the only bit I did not write:
    
     if (day > ListofDays[month-1])  
     {  
        console.log('1 - Invalid DATE format!');  
        return 0;  
     } 
     else
        {
        console.log('1 - Valid DATE format!');  
        return 1
    }

*/
<p>Input a date and check it's in a)correct format and b)it is a valid date</p>

<input type="text" id="myDate" placeholder="DD-MM-YYYY"> <br><br>

<button type="button" onclick="isValidDate()"> Check Date </button>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
simon
  • 13
  • 4
  • 1
    https://stackoverflow.com/a/1353711/7239480 – acnn Oct 31 '17 at 15:18
  • Do yourself a favour and [use moment.js](https://stackoverflow.com/a/38177124/542251). This has done a lot of the hard work for you. – Liam Oct 31 '17 at 15:31
  • @Liam what will that teach him. Also highly wasteful for such a simple task – mplungjan Oct 31 '17 at 15:31
  • It is a LOT simpler to split the date string on "-", create a new Date object from the parts (remember to start months at 0): `var testDate = new Date(year,month-1,day,0,0,0)` and test that the parts are the same as the date parts. Also I do not see you use the regex – mplungjan Oct 31 '17 at 15:33
  • Sorry I am new to JS i thought it was using regex? How can I get it to use Regex? Also what does this do? (day > ListofDays[month - 1]) just cannot work that out – simon Oct 31 '17 at 15:35
  • You have `var dateformat = /^(0?[1-9]|[12][0-9]|3[01])[-](0?[1-9]|1[012])[-]\d{4}$/;` but you are not testing your date against it – mplungjan Oct 31 '17 at 15:38
  • sorry im so new to JS how to I test my date against it? – simon Oct 31 '17 at 15:44
  • ok I see I am now - var dateformat = new RegExp(/^(0?[1-9]|[12][0-9]|3[01])[-](0?[1-9]|1[012])[-]\d{4}$/); var readDate = document.getElementById("myDate").value; if(dateformat.test(readDate)) – simon Oct 31 '17 at 15:55

3 Answers3

1
  1. Test the date against the regex you have to reduce the tests
  2. do NOT return when you want to continue

Here is a solution that keeps the code as close to what you want to do as possible. The simpler solution using a Date Object I already suggested in a comment and has been elaborated on by others

function showError(str) {
  console.log(str)
  return false;
}

function isValidDate() {
  var dateformat = /^(0?[1-9]|[12][0-9]|3[01])[-](0?[1-9]|1[012])[-]\d{4}$/;

  var readDate = document.getElementById("myDate").value;

  if (readDate.length != 10) return showError("Invalid DATE length") // not correct length
  console.log(dateformat.test(readDate));

  if (!dateformat.test(readDate)) {
    return showError("Invalid DATE format") // not matching regex
  }

  /* split date into DD-MM-YYYY format */
  var splitDate = readDate.split('-');

  var day = splitDate[0];
  var month = splitDate[1];
  var year = splitDate[2];

  /* DEBUG - print split date into DD-MM-YYYY format */
  console.log('day ' + day);
  console.log('month ' + month);
  console.log('year ' + year);

  // Create list of days of a month [assume there is no leap year by default]  
  var ListofDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

  //if month is not between 1-12
  if (month <= 0 || month > 12) {
    return showError('0 - Invalid MONTH format!');
  }

  var isLeap = false;
  //check for leap year
  if (year % 4 === 0 && year % 100 !== 0) {
    console.log('The year ' + year + ' is a leap year.');
    isLeap = true;
  } else if (year % 4 === 0 && year % 100 === 0 && year % 400 === 0) {
    console.log('The year ' + year + ' is a leap year.');
    isLeap = true;
  } else {
    console.log('The year ' + year + ' is NOT a leap year');
  }

  //check DAY exists in the MONTH
  var testDay = ListofDays[month - 1]; // array starts at 0
  // testDay += isLeap ? 1 : 0; // add one to testDay using ternary operator
  if (isLeap) testDay++; // less code, does the same as above
  if (day > testDay) {
    return showError('1 - Invalid DATE format!');
  }

  console.log('1 - Valid DATE format!');
  // You can return true here if you want


}
<p>Input a date and check it's in a)correct format and b)it is a valid date</p>

<input type="text" id="myDate" placeholder="DD-MM-YYYY"> <br><br>

<button type="button" onclick="isValidDate()"> Check Date </button>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • thank you so much, I am on the road atm so cannot test, will test later....by the way how can I amend that regex so I don't allow letters to be inserted into text box? thanks – simon Oct 31 '17 at 19:41
  • do NOT return when you want to continue - ahh I see – simon Oct 31 '17 at 19:43
  • testDay += isLeap ? 1 : 0 // how can this be simplified as I do not understand this and don't write IF statements like this, I really honestly don't mind it being long version, its for my learning – simon Oct 31 '17 at 19:44
  • the `testDay +=` is shorthand for `testDay = testDay + ...` and the `isLeap ? 1 : 0` is called a ternary and is shorthand for `if (isLeap) testDay = testDay+1; else testDay = testDay + 0;` it could also be written `if (isLeap) testDay++;` – mplungjan Oct 31 '17 at 19:47
  • return will leave the function. You can use the return value like this: `if (isValidDate()) this.form.submit();` – mplungjan Oct 31 '17 at 19:50
  • ahh thanks man and also how can I amend that regex so I don't allow letters to be inserted into text box only numbers? – simon Oct 31 '17 at 19:50
  • You cannot. You can add an event handler to test the key entered: https://stackoverflow.com/questions/19966417/prevent-typing-non-numeric-in-input-type-number – mplungjan Oct 31 '17 at 19:55
  • I see because its a textbox.....however if I use input type=number then it will automatically put the up and down buttons on the input box which I don't want...any ways around it? – simon Oct 31 '17 at 19:59
  • Yes input type=date :) or test yourself – mplungjan Oct 31 '17 at 20:00
  • thank you so much my reputation is <15 so I cannot up vote your great work - thanks so much – simon Nov 01 '17 at 15:27
0

Discard all that.

<input type="date" />

Job done.


Alternatively, since you're specifying the format you can do something like this:

var input = document.getElementById("myDate").value;
var parts = input.split("-");
var date = new Date(parts[2],parts[1]-1,parts[0]);
return date.getFullYear() == parts[2]
    && date.getMonth() == parts[1]-1
    && date.getDate() == parts[0];

This works because JavaScript will "fix" the date if it falls outside of valid bounds (eg. January 32nd is corrected to February 1st), so just check to see if it changed anything when it received the date.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 1
    Thanks but I don't need JS to fix the date. I really wanted it to work the way I'm doing it for my own learning and then later try and improve – simon Oct 31 '17 at 15:39
0

function validate(value) {
  var v = false;
  if (value) {
    var r = value.match(/([0-9]{1,2}).?([0-9]{1,2}).?([0-9]{4})/);
    
    if (r) {
      var day1 = parseInt(r[1]);
      var month1 = parseInt(r[2]);
      var year1 = parseInt(r[3]);

      var d = new Date(year1, month1 - 1, day1);

      var day2 = d.getDate();
      var month2 = d.getMonth() + 1;
      var year2 = d.getFullYear();

      v = day1    == day2   &&
          month1  == month2 &&
          year1   == year2;
    }
  }
  
  return v;
}
<input type="text" id="toCheck" />
<button onclick="console.log(validate(document.getElementById('toCheck').value))">Check</button>

You can try with any separator, this is only an example (I used a trick to check a real date). You can modify this function for your personal use.

Laurianti
  • 903
  • 1
  • 5
  • 19
  • thank you so much but how comes my code does not work? thats what I want to try and really fix – simon Oct 31 '17 at 16:01