Reputation: 85
Hello I am trying to validate a date in the format: 03-Mar-2011 or 12-Dec-2007. I currently have a regexp that fails on the 3 character Month. I probably just need to tweak that to get it to work properly.
//function isDate(txtDate) {
function isDate(sender, args) {
var currVal = document.getElementById('<%=txtChange_Date.ClientID%>').value;
if (currVal == '')
return false;
//Declare Regex
var rxDatePattern = /^(\d{1,2})(\/|-)[a-zA-Z]{3}(\/|-)(\d{4})$/;
var dtArray = currVal.match(rxDatePattern); // is format OK?
if (dtArray == null)
return false;
//formerly //Checks for dd/mm/yyyy format.
//Checks for dd-MMM-yyyy format.
var dtDay = dtArray[1];
var dtMonth = dtArray[3];
var dtYear = dtArray[4];
switch(dtMonth)
{
case 'Jan':
dtMonth = '01';
break;
case 'Feb':
dtMonth = '02';
break;
case 'Mar':
dtMonth = '03';
break;
case 'Apr':
dtMonth = '04';
break;
case 'May':
dtMonth = '05';
break;
case 'Jun':
dtMonth = '06';
break;
case 'Jul':
dtMonth = '07';
break;
case 'Aug':
dtMonth = '08';
break;
case 'Sep':
dtMonth = '09';
break;
case 'Oct':
dtMonth = '10';
break;
case 'Nov':
dtMonth = '11';
break;
case 'Dec':
dtMonth = '12';
break;
}
if (dtMonth < 1 || dtMonth > 12)
return false;
else if (dtDay < 1 || dtDay > 31)
return false;
else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31)
return false;
else if (dtMonth == 2) {
var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
if (dtDay > 29 || (dtDay == 29 && !isleap))
return false;
}
return true;
}
Upvotes: 2
Views: 11508
Reputation: 20494
There were a few problems with your code, but your regular expression was fine except that month wasn't being grouped.
Other Changes
switch
that converts the month needed to have dtMonth
converted to lower case and the case statements needed to match the case.parseInt
. I don't know if it was an issue with dtDay
or dtYear
, but it was causing an issue with dtMonth
.parseInt
change I added a not a number check and dtMonth
.Code
function isDate(currVal) {
if (currVal == '') return false;
//Declare Regex
var rxDatePattern = /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/;
var dtArray = currVal.match(rxDatePattern); // is format OK?
if (dtArray == null) return false;
var dtDay = parseInt(dtArray[1]);
var dtMonth = dtArray[3];
var dtYear = parseInt(dtArray[4]);
// need to change to lowerCase because switch is
// case sensitive
switch (dtMonth.toLowerCase()) {
case 'jan':
dtMonth = '01';
break;
case 'feb':
dtMonth = '02';
break;
case 'mar':
dtMonth = '03';
break;
case 'apr':
dtMonth = '04';
break;
case 'may':
dtMonth = '05';
break;
case 'jun':
dtMonth = '06';
break;
case 'jul':
dtMonth = '07';
break;
case 'aug':
dtMonth = '08';
break;
case 'sep':
dtMonth = '09';
break;
case 'oct':
dtMonth = '10';
break;
case 'nov':
dtMonth = '11';
break;
case 'dec':
dtMonth = '12';
break;
}
// convert date to number
dtMonth = parseInt(dtMonth);
if (isNaN(dtMonth)) return false;
else if (dtMonth < 1 || dtMonth > 12) return false;
else if (dtDay < 1 || dtDay > 31) return false;
else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31) return false;
else if (dtMonth == 2) {
var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
if (dtDay > 29 || (dtDay == 29 && !isleap)) return false;
}
return true;
}
Alternate Solution
You might not like a really complicated regex, but you can really reduce your code by handling the switching in the regex itself. The following gets the matched month by looping through the matched group into an undefined one is not encountered and then offsetting the value.
function isDate(currVal) {
if (currVal == '') return false;
//Declare Regex
var rxDatePattern = /^(\d{1,2})(\/|-)(?:(\d{1,2})|(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec))(\/|-)(\d{4})$/i;
var dtArray = currVal.match(rxDatePattern);
if (dtArray == null) return false;
var dtDay = parseInt(dtArray[1]);
var dtMonth = parseInt(dtArray[3]);
var dtYear = parseInt(dtArray[17]);
if (isNaN(dtMonth)) {
for (var i = 4; i <= 15; i++) {
if ((dtArray[i])) {
dtMonth = i - 3;
break;
}
}
}
if (dtMonth < 1 || dtMonth > 12) return false;
else if (dtDay < 1 || dtDay > 31) return false;
else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31) return false;
else if (dtMonth == 2) {
var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
if (dtDay > 29 || (dtDay == 29 && !isleap)) return false;
}
return true;
}
Upvotes: 3
Reputation: 6230
Here is the code, no regexp required and use of javascript build in date parsing.
var isDate = (function() {
var MONTHS = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
];
return function (date) {
var v = new Date(date);
var day = v.getDate();
if(day < 10) {
day = "0" + day;
}
var month = MONTHS[v.getMonth()];
var year = v.getFullYear();
var total = day + "-" + month + "-" + year;
return date.toUpperCase() == total.toUpperCase();
}
}());
Upvotes: 0
Reputation: 17238
your regex is ok, you haven't enclosed the month subpattern with parentheses so you haven't defined a capture group. consequently, your switch statement fails:
try
var rxDatePattern = /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/;
and
var dtYear = dtArray[5]; // now 5 instead of 4
Upvotes: 2
Reputation: 17266
It looks like there's just brackets missing around the month section to make it a separate group.
/^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/
var dtDay = dtArray[1];
var dtMonth = dtArray[3];
var dtYear = dtArray[5];
Upvotes: 0
Reputation: 78650
You need parentheses around the month to capture it:
/^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/
Which will mean you then need to adjust the index of your year:
var dtYear = dtArray[5]; // now 5 instead of 4
Upvotes: 0