Validation of Bad date in Javascript
using momentjs
moment("02/30/2019", "MM/DD/YYYY", true).isValid(); // false
moment("03/30/2019", "MM/DD/YYYY", true).isValid(); // true
from current docs of the library here: isValid momentjs
moment("not a real date").isValid(); // false
You can still write your own solution by splitting the string and evaluating for each section. the problem with this approach is that not only February that is not 31 days, there are other months too that are only 30 days. so it will take time before you develop a "not buggy" solution.
It's not recommended to parse dates using new Date('02/31/2019')
(which implicitly calls Date.parse
) because of inconsistencies between implementations.
It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated).
Source: MDN
Instead you can use a regular expression to extract parts of the date, and then construct the date object using either new Date(year, monthIndex, day)
or new Date(Date.UTC(year, monthIndex, day))
depending on which timezone you assume.
Then you can format your newly created date object as a string and check if it's the same as your initial string. If the date wraps over to the next month (e.g. Feb 30 to Mar 1) the strings won't match.
function parseMMDDYYY(str) {
const match = str.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
if (!match) {
throw new Error(`Invalid date format ${str}`);
}
const [, m, d, y] = match;
const date = new Date(Date.UTC(y, m - 1, d));
if (!date.toISOString().startsWith(`${y}-${m}-${d}`)) {
throw new Error(`Invalid date ${str}`);
}
return date;
}
try {
console.log(parseMMDDYYY('02/31/2019'));
} catch (e) {
console.log(e.toString());
}
try {
console.log(parseMMDDYYY('12/21/2019'));
} catch (e) {
console.log(e.toString());
}
A lot depends on allowed input formats, but this seem to be possible solution for your examples (pure JS, no extra libraries):
const trueDate = '12/21/2019'
const falseDate = '02/31/2019'
const checkDate = (dateStr) => {
const dateObj = new Date(dateStr)
const actualDate = dateObj.getDate()
const actualMonth = dateObj.getMonth() + 1 // months are from 0 to 11 in JS
const actualFullYear = dateObj.getFullYear()
const [strMonth, strDate, strFullYear] = dateStr.split('/').map(Number)
return strMonth === actualMonth && strDate === actualDate && strFullYear === actualFullYear
}
console.log(checkDate(trueDate)) // true
console.log(checkDate(falseDate)) // false