Dels
Dels

Reputation: 2425

javascript regexp, validating date problem

I have some code for validating date below:


function validateForm() {
var errFound = 0;       
//var patt_date = new RegExp("^((((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))$");
var patt_date = new RegExp("^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$");
if (patt_date.test(document.getElementById("datefrom").value) == false){errFound = errFound + 1;document.getElementById("datefrom").className = "error";}

if (errFound > 0)
    alert('Please correct red colored field!');
else
    return true;
return false;   
}


Above code should work with YYYY-MM-DD format, but fail to validate date such as "2009-02-29"

The commented code should work (//var patt_date = new RegExp...), it can catch "2009-02-29",
but it ruin the validation when i put invalid data and try to correct it, it keeps complain there something wrong with form value after i had correct them (especially on form with multiple input)

Maybe someone can fix the current regex?


Edited, what i want just a simple replacement for above regexp, mean a new regexp pattern not the whole new method to validate date
And for reference, i simply grab the regexp pattern from:
http://www.regexlib.com/REDetails.aspx?regexp_id=694 and
http://www.regexlib.com/REDetails.aspx?regexp_id=933

Tested with 2009-02-29, 1st link work & 2nd not. Again the problem was only the 2nd regexp didn't detect value 2009-02-29 as invalid while 1st can (but it ruin my code? so it's must be there something wrong with it).

Thanks,
Dels

Upvotes: 1

Views: 16182

Answers (3)

Yosri
Yosri

Reputation: 1

This javascript code validates date exactly. You can copy it and test it in your browser.

 var regDate = '^(19[0-9]{2}|2[0-9]{3})-(0[1-9]{1}|1[0-2]{1}){1}-(0[1-9]|(1|2)[0-9]|3[0-1]){1}$';
 var txt='2010-01-31';
 if(txt.match(regDate))
 {
    alert('date match');
 }

Upvotes: -1

Cerebrus
Cerebrus

Reputation: 25775

I kinda agree with David on this... Regex matches should not be used as an exclusive criterion to decide if the passed date is, in fact, valid. The usual procedure in Javascript validation involves a few steps :

a. The first step is to ensure that the passed string matches expected date formats by matching it against a Regex. The following may be a stricter Regex pattern.

// Assuming that the only allowed separator is a forward slash.
// Expected format: yyyy-mm-dd
/^[12][90][\d][\d]-[0-3]?[\d]-[01]?[\d]$/

b. The second step is to parse the string into a Date object which returns the no. of milliseconds since 1970. Use this number as a parameter for the Date constructor.

c. Since JS automatically rolls over the passed date to the nearest valid value, you still cannot be certain if the Date object created matches that which was passed. To determine if this happened, the best way is to split the passed string according to the separator and compare individual date components:

// d is the created Date object as explained above.
var arrDateParts = inputDate.split("-");
if ((d.getFullYear() == arrDateParts[0]) && (d.getMonth() == arrDateParts[1]) && (d.getDate() == arrDateParts[2]))
  return true;
else
  return false;

Upvotes: 3

David Z
David Z

Reputation: 131550

Don't do the whole date validation with a regular expression, that's really pushing the limits of what regexps were designed for. I would suggest this procedure instead:

  1. Check date against regexp /^\d{4}-\d{2}-\d{2}$/
  2. Extract year, month, and day using substr() and convert to integers
  3. Use some if statements to validate the integers. Like so:
    if (month == 2) {
        if (day == 29) {
            if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) {
                // fail
            }
        }
        else if (day > 28) {
            // fail
        }
    }
    else if (month == 4 || month == 6 || month  == 9 || month == 11) {
        if (day > 30) {
            // fail
        }
    }
    else {
        if (day > 31) {
            // fail
    }

(That could certainly be written more concisely) Alternatively, you could probably perform this validation using Javascript's Date class - you might have to do something like parsing the date, converting it back to a string, and checking if the two strings are equal. (I'm not a Javascript expert)

Upvotes: 8

Related Questions