0

I'm working on a JavaScript program that takes user input for year, month and day values and has to check if it is a valid date. After getting the values I construct a date object, thinking it would throw an error on any incorrect values. Not just obvious errors like 2018-34-17 but also more subtle things like 2018-11-31, figuring I could Try-Catch these errors and report it back to the user.

However, it turns out JavaScript will happily accept any nonsense values as date. I've boiled my problem down to this:

// try invalid values
var year = 2018;
var month = 31;
var day = 12;

// construct date
var dt = new Date(year, (month-1), day);

// result; valid date 12-july-2020

It results in a valid date value, no error is raised, and the resulting value is 12-jul-2020. I can see that it does a modulo operation adding the quotient to the years with the remainder as the new month value, like an automatic overflow, but that is not what I expected. Btw I get the same result in both Chrome and in Edge.

My question is, how can I force JavaScript to throw an error on these kind of invalid date values?

EDIT: Just want to mention that the JavaScript Date object (in both Chrome and Edge) behaves quite odd imho. If you use the string constructor, it will accept anything as long as the day is not larger than 31 and month not larger than 12.

var dt = new Date("2019-02-29 00:00"); // valid, March 1, 2019
var dt = new Date("2018-02-30 00:00"); // valid, March 2, 2019
var dt = new Date("2018-02-31 00:00"); // valid, March 3, 2019
var dt = new Date("2018-02-32 00:00"); // invalid date
var dt = new Date("2018-11-30 00:00"); // valid, November 30, 2018
var dt = new Date("2018-11-31 00:00"); // valid, December 1, 2018
var dt = new Date("2018-11-32 00:00"); // invalid date
var dt = new Date("2018-13-30 00:00"); // invalid date

If you use the integer constructor it will accept everything and you never get an invalid date, negative values are allowed too.

var dt = new Date(2019, 11, 31); // valid, December 31, 2019
var dt = new Date(2019, 12, 31); // valid, January 31, 2020
var dt = new Date(2019, 13, 32); // valid, March 3, 2020
var dt = new Date(2019, 14, 33); // valid, April 2, 2020
var dt = new Date(2019, 99, 99); // valid, July 8, 2027
BdR
  • 2,770
  • 2
  • 17
  • 36

1 Answers1

1

why not just use if statements:

var year = 2018, month = 31, day = 11;
if(year<1900||year>2100){// or whatever you want a valid year to be
    alert('Year is invalid');
}
else if(month<1||month>12){
    alert('Month is invalid');
}
else if(day<1||day>31){
    alert('Day is invalid');
}
else if((month===4||month===6||month===9||month===11)&&day>30){
    alert('Day is invalid for that month');
}
else if(month===2&&day>28&&year%4!==0){
    alert("February doesn't have that many days");
}
else if(month===2&&year%4===0&&day>29){
    alert("February doesn't have that many days during that year");
}
else{
    alert('Date is valid');
}
KhanKudo
  • 82
  • 1
  • 3
  • `year%4!==0` is an insufficient test for leap years. All those if..else statements aren't necessary. – RobG Nov 01 '19 at 21:38
  • In other words just "roll your own" ;) This is what I ended up using -> https://github.com/BdR76/datasetmultitool/blob/master/datatool.js#L131 – BdR Dec 17 '19 at 16:00