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;
}
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;
}
Share
Improve this question
edited Sep 6, 2013 at 14:01
James Montagne
78.8k14 gold badges114 silver badges132 bronze badges
asked Sep 6, 2013 at 13:58
Jason TaylorJason Taylor
851 gold badge1 silver badge6 bronze badges
3
- 1 FYI regular expressions have nothing to do with jQuery. I've edited the title for you. – Rory McCrossan Commented Sep 6, 2013 at 14:01
- There are tested date validation scripts / libraries for JS which may be worth looking at. – Matthew Commented Sep 6, 2013 at 14:06
- 1 Easy answer is to use moment.js's isValid function – Daniel Gimenez Commented Sep 6, 2013 at 14:10
5 Answers
Reset to default 3There were a few problems with your code, but your regular expression was fine except that month wasn't being grouped.
Other Changes
- The
switch
that converts the month needed to havedtMonth
converted to lower case and the case statements needed to match the case. - I explicitly converted the date parts to integers with
parseInt
. I don't know if it was an issue withdtDay
ordtYear
, but it was causing an issue withdtMonth
. - With the
parseInt
change I added a not a number check anddtMonth
. - I also moved the validator out of the event handler. Just a good practice to follow if the validation isn't trivial.
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;
}
jsFiddle
Alternate Solution
You might not like a really plicated 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;
}
jsFiddle
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
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
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];
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();
}
}());
THE FIDDLE