The following code is a long, branched if-statement. When I use node to run it, the console ouput is undefined (this behaviour is also replicated in the code snippet below). So essentially, the full if-statement isn't getting executed, and (I assume) the synchronous nature of javascript causes the function to end before the if-statement is executed in its totality. How can I wait for the if-statement to run before the function ends (maybe async-await or a promise)?
The code is as follows (it's a DIY date-validator that ensures dates are in the form DD/MM/YYYY and that the date is today's date or in the future):
function validDate(input){
let monthLengths = [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (input[2] !== "/" || input[5] !== "/"){
return false;
} else if (!Number.isInteger(+input[0]) || !Number.isInteger(+input[1]) || !Number.isInteger(+input[3]) || !Number.isInteger(+input[4]) || !Number.isInteger(+input[6]) || !Number.isInteger(+input[7]) || !Number.isInteger(+input[8]) || !Number.isInteger(+input[9])){
return false;
} else if (input.length !== 10){
return false;
} else if (input.substr(3, 2) === "02"){
// check if leap year
if (+input.substr(0, 2) > 29){
return false;
} else if (input.substr(0, 2) === "29" && +input.substr(6, 4)%4 != 0){
return false;
}
} else if (+input.substr(0, 2) > monthLengths[+input.substr(3, 2) - 1]){
return false;
} else if (Date.now() - Date.now()%86400000 - 86400000/3 > Date.parse(input.substr(3, 2) + "/" + input.substr(0, 2) + "/" + input.substr(6, 4))){
return false;
} else {
return true;
}
}
console.log(validDate("02/02/2022"))
function validDate(input){
let monthLengths = [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (input.substr(3, 2) === "02"){
// check if leap year
if (+input.substr(0, 2) > 29){
return false;
} else if (input.substr(0, 2) === "29" && +input.substr(6, 4) % 4 != 0){
return false;
}
}
if (input[2] !== "/" || input[5] !== "/"){
return false;
} else if (!Number.isInteger(+input[0]) || !Number.isInteger(+input[1]) || !Number.isInteger(+input[3]) || !Number.isInteger(+input[4]) || !Number.isInteger(+input[6]) || !Number.isInteger(+input[7]) || !Number.isInteger(+input[8]) || !Number.isInteger(+input[9])){
return false;
} else if (input.length !== 10){
return false;
} else if (+input.substr(0, 2) > monthLengths[+input.substr(3, 2) - 1]){
return false;
} else if (Date.now() - Date.now()%86400000 - 86400000/3 > Date.parse(input.substr(3, 2) + "/" + input.substr(0, 2) + "/" + input.substr(6, 4))){
return false;
} else {
return true;
}
}
console.log(validDate("02/02/2022"))
There are a couple of things we can do to make this code work a bit better. There is no need for using the else keyword that much, if you are returning a value inside a function you are already making sure that all lines of code after the if statements are not going to be run.
With that being said we can make these changes:
function validDate(input){
let monthLengths = [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (input[2] !== "/" || input[5] !== "/") return false;
if (!Number.isInteger(+input[0]) || !Number.isInteger(+input[1]) || !Number.isInteger(+input[3]) || !Number.isInteger(+input[4]) || !Number.isInteger(+input[6]) || !Number.isInteger(+input[7]) || !Number.isInteger(+input[8]) || !Number.isInteger(+input[9])) return false;
if (input.length !== 10) return false;
if (input.substr(3, 2) === "02") {
// check if leap year
if (+input.substr(0, 2) > 29) return false;
if (input.substr(0, 2) === "29" && +input.substr(6, 4)%4 != 0) return false;
}
if (+input.substr(0, 2) > monthLengths[+input.substr(3, 2) - 1]) return false;
if (Date.now() - Date.now()%86400000 - 86400000/3 > Date.parse(input.substr(3, 2) + "/" + input.substr(0, 2) + "/" + input.substr(6, 4))) return false;
return true;
}
Now that the code is a bit cleaner, we can simply add a return true statement where no if statement is accomplished inside the leap year block of code.
function validDate(input){
let monthLengths = [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (input[2] !== "/" || input[5] !== "/") return false;
if (!Number.isInteger(+input[0]) || !Number.isInteger(+input[1]) || !Number.isInteger(+input[3]) || !Number.isInteger(+input[4]) || !Number.isInteger(+input[6]) || !Number.isInteger(+input[7]) || !Number.isInteger(+input[8]) || !Number.isInteger(+input[9])) return false;
if (input.length !== 10) return false;
if (input.substr(3, 2) === "02") {
// check if leap year
if (+input.substr(0, 2) > 29) return false;
if (input.substr(0, 2) === "29" && +input.substr(6, 4)%4 != 0) return false;
return true; // <----- This line we need to add.
}
if (+input.substr(0, 2) > monthLengths[+input.substr(3, 2) - 1]) return false;
if (Date.now() - Date.now()%86400000 - 86400000/3 > Date.parse(input.substr(3, 2) + "/" + input.substr(0, 2) + "/" + input.substr(6, 4))) return false;
return true;
}
We can take advantage of the Date object that JS has already built in. I suggest this next function:
const validDate = (input) => {
if (input.length !== 10) return false;
const [ day, month, year ] = input.split("/");
if(day.length !== 2 || month.length !== 2 || year.length !== 4) return false;
if(!day || !month || !year || isNaN(+day)|| isNaN(+month)|| isNaN(+year)) return false;
const now = new Date(), inputDate = new Date(+year, +month - 1, +day, 23, 59, 59);
return inputDate >= now;
}
validDate("02/02/2022");
I would suggest you to move everything into switch statement. Would be needer and will cause no your explained problems.