Skip to content

Instantly share code, notes, and snippets.

@mlconnor
Last active December 16, 2015 09:49
Show Gist options
  • Save mlconnor/5415469 to your computer and use it in GitHub Desktop.
Save mlconnor/5415469 to your computer and use it in GitHub Desktop.
Regex to validate yyyymmdd with all leaps since 1582. This is bad ass. The final regex is... var regex = new RegExp("^(?:(?:(?:(?:[13579][26]|[2468][048])00)|(?:[0-9]{2}(?:(?:[13579][26])|(?:[2468][048]|0[48]))))(?:(?:(?:09|04|06|11)(?:0[1-9]|1[0-9]|2[0-9]|30))|(?:(?:01|03|05|07|08|10|12)(?:0[1-9]|1[0-9]|2[0-9]|3[01]))|(?:02(?:0[1-9]|1[0-9]|2[0-…
var regex = /^(?:\d{4})(?:(?:(09|04|06|11)(?:01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30))|(?:(?:01|03|05|07|08|10|12)(?:01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31))|(?:02(?:01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29)))$/;
var m30 = "(?:(?:09|04|06|11)(?:0[1-9]|1[0-9]|2[0-9]|30))";
var m31 = "(?:(?:01|03|05|07|08|10|12)(?:0[1-9]|1[0-9]|2[0-9]|3[01]))";
var fLeap = "(?:02(?:0[1-9]|1[0-9]|2[0-9]))";
var fNonLeap = "(?:02(?:[01][0-9]|2[0-8]))";
var nonLeapMonths = "(?:" + m30 + "|" + m31 + "|" + fNonLeap + ")";
var leapMonths = "(?:" + m30 + "|" + m31 + "|" + fLeap + ")";
var evenDecadeLeap = "(?:[2468][048]|0[48])";
var oddDecadeLeap = "(?:[13579][26])";
var leapCentury = "(?:(?:[13579][26]|[2468][048])00)";
//var leapYears = "(?:" + leapCentury + "|(?:[0-9]{2}" + evenDecadeLeap + "|" + oddDecadeLeap + "))";
var leapNoCentury = "(?:[0-9]{2}(?:" + oddDecadeLeap + "|" + evenDecadeLeap + "))";
var leapYears = "(?:" + leapCentury + "|" + leapNoCentury + ")";
new RegExp(evenDecadeLeap);
new RegExp(oddDecadeLeap);
new RegExp(leapCentury);
new RegExp(leapYears);
//var leapYears = "(?:(?:[13579][26]|[2468][048])00)|(?:[0-9]{2}(?:(?:[13579][26])|(?:[2468][048]|0[48])))";
//var leapYears = /^(?:(?:[13579][26]|[2468][048])00)|(?:\d\d(?:[13579][26])|(?:[2468][048]|0[48]))$/;
for ( var year = 1582; year <= 3000; year++ ) {
var isLeap = new Date(year, 1, 29).getMonth() == 1;
var test = new RegExp("^" + leapYears + "$");
var match = test.exec(year.toString());
//console.log('' + year +' ' + match);
if ( isLeap && ! match ) {
console.log('leap fail [' + year + ']');
console.log(match);
}
if ( ! isLeap && match ) {
console.log('leap false match [' + year + ']');
}
}
var finalRegex = new RegExp("^(?:" + leapYears + leapMonths + ")|(?:[0-9]{4}" + nonLeapMonths + ")$");
var finalPattern = "^(?:" + leapYears + leapMonths + ")|(?:[0-9]{4}" + nonLeapMonths + ")$";
console.log("P=" + finalPattern);
var finalRegex = new RegExp(finalPattern);
//regex = /^[0-9]{4}(?:0[1-9]|1[0-2])(?:[0-2]?[0-9]|3[01])$/;
var d = new Date(1582, 0, 1);
for ( var i = 0; i < 365 * 8000; i++ ) {
//console.log(d.toString());
var yyyymmdd = "" + d.getFullYear() +
(d.getMonth() < 9 ? "0" + (d.getMonth() + 1) : (d.getMonth() + 1)) +
(d.getDate() < 10 ? "0" + d.getDate() : d.getDate());
//console.log(yyyymmdd);
//console.log(" =" + yyyymmdd.match(regex));
if ( ! finalRegex.test(yyyymmdd) ) {
console.log('fail ' + yyyymmdd);
console.log("m30: " + new RegExp(m30).test(yyyymmdd.substring(4)));
console.log("m31: " + new RegExp(m31).test(yyyymmdd.substring(4)));
console.log("fLeep: " + new RegExp(fLeap).test(yyyymmdd.substring(4)));
console.log("fNonLeap: " + new RegExp(fNonLeap).test(yyyymmdd.substring(4)));
console.log("nonLeapMonth: " + new RegExp(nonLeapMonths).test(yyyymmdd.substring(4)));
console.log("leapMonths: " + new RegExp(leapMonths).test(yyyymmdd.substring(4)));
console.log("================");
}
d = new Date(d.getTime() + 24 * 60 * 60 * 1000);
}
var check = ['abcdefh', '20120132', '20120230','20120200', '20121232', '2012131', '20120230'];
for ( var i = 0; i < check.length; i++ ) {
if ( finalRegex.exec(check[0]) ) {
console.log('this should have failed but it didnt ' + check[i]);
}
}
for ( var year = 1582; year <= 3000; year++ ) {
var isLeap = new Date(year, 1, 29).getMonth() == 1;
if ( isLeap && ! finalRegex.test(year.toString() + '0229') ) {
console.log('EPIC FAIL');
}
if ( ! isLeap && finalRegex.test(year.toString() + '0229') ) {
console.log('EPIC FAIL X');
}
var check = { "01" : 32, "02" : 30, "03" : 32, "04":31, "05":32, "06" : 31, "07":32, "08" : 32 , "09":31, "10":32, "11":31, "12":32};
for ( var key in check) {
for ( var i = check[key]; i < 100; i++ ) {
var checkThis = year.toString() + key + i;
console.log('checking ' + checkThis);
if ( finalRegex.test(checkThis) ) {
console.log("Bound fail for " + checkThis );
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment