JSFiddle - React, Tailwind, and code Playground
by andrewmacheret
JavaScript
let dateRegexString = `
^ # start
(
( # non-leap months & days
(0[1-9]|1[012])/(?!00|29)([012]\\d) # all months, days 01-28, uses negative lookahead
|
(0[13-9]|1[012])/(29|30) # all months except feb, days 29,30
|
(0[13578]|1[02])/31 # all 31 day months, day 31 only
)
/
(18|19|20)\\d{2} # all years
|
02/29 # leap months & days
/
(
(18|19|20)(0[48]|[2468][048]|[13579][26]) # leap years not divisible by 100
|
2000 # leap years divisible by 100
)
)
$ # end
`;
let dateRegex = new RegExp(
dateRegexString.replace(/ #.*\n/g, '') // remove comments
.replace(/[ \n]/g, '') // remove whitespace
);
console.log('Regular expression being tested:', dateRegex);
function validateRegex(input) {
return input.match(dateRegex) !== null;
}
function validateDate(input) {
let date = new Date(input + ' 00:00:00');
input = input.split('/');
return date.getDate() === +input[1] &&
date.getMonth() + 1 === +input[0] &&
date.getFullYear() === +input[2];
}
function test1800to2099() {
return new Promise((resolve, reject) => {
let centuries = Array.from({length: 3}, (_, index) => (index + 18).toString()); // 18, 19, 20
let digits = Array.from({length: 10}, (_, index) => (index).toString()); // 0 thru 9
centuries.forEach((y12) => {
digits.forEach((y3) => {
digits.forEach((y4) => {
digits.forEach((m1) => {
digits.forEach((m2) => {
digits.forEach((d1) => {
digits.forEach((d2) => {
let date = `${m1}${m2}/${d1}${d2}/${y12}${y3}${y4}`;
let expected = validateDate(date);
let actual = validateRegex(date);
if (expected !== actual) {
reject(`Failed on ${date}, expected: ${expected}, actual: ${actual}`);
}
});
...