jquery.validate and chrome doesn't validate australian dates

Whats that? Chrome doesn't nicely convert date strings? new Date("19/11/2011") fails?!
November 19 2012

I'm currently working on an ASP.NET MVC 4 website using unobtrusive jquery validation.  My browser of choice is Chrome.  In my app I have a required Date of Birth.  ASP.NET MVC 4 hooks up the client side validation for me and whenever I enter a date in dd/mm/yyyy format that is not a valid date in mm/dd/yyyy fomat I get an error (eg 19/11/2012 - there is no 19th month).

Jqu Validate And Chrome Doesnt Validate B1C2 Image Thumb

To validate a date the jQuery validation plugin simply tries to call new Date(myDateString), as seen here;

// http://docs.jquery.com/Plugins/Validation/Methods/date
date: function(value, element) {
    return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
},

 

See line 1098 in jquery.validate.js.

I need something a little more robust, so I created a parser.

function getDateFormat(formatString) {

    var separator = formatString.match(/[.\/\-\s].*?/),
        parts = formatString.split(/\W+/);
    if (!separator || !parts || parts.length === 0) {
        throw new Error("Invalid date format.");
    }
    return { separator: separator, parts: parts };
}
function MyParseDate(date, format) {
    var parts = date.split(format.separator),
        date = new Date(),
        val;
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    if (parts.length === format.parts.length) {
        console.log(parts.length);
        for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
            val = parseInt(parts[i], 10) || 1;

            switch (format.parts[i]) {
                case 'dd':
                case 'd':
                    date.setDate(val);
                    break;
                case 'mm':
                case 'm':
                    date.setMonth(val);
                    break;
                case 'yy':
                    date.setFullYear(2000 + val);
                    break;
                case 'yyyy':
                    date.setFullYear(val);
                    break;
            }
        }
    }

    return date;
}


In the above I am building up the date based on the value and format passed into MyParseDate.  I’m going to always pass in a format of “dd/mm/yyyy” in my current locale, but I want that to change based on where the user is.  getDateFormat() takes a date format string.

Then I need to override the jquery validation code with my own.

 jQuery.validator.addMethod('date',
                function (value, element, params) {                    
                    if (this.optional(element)) {
                        return true;
                    }
                    var result = false;
                    try {                        
                        var format = getDateFormat('dd/mm/yyyy');
                        MyParseDate(value, format);                        
                        result = true;
                    } catch(err) {
                        console.log(err);
                        result = false;
                    }
                    return result;
                });

 

You’ll need to put in every page that uses dates.  I’m using ASP.NET MVC 4 so I decided to add it to my jquery validator bundle, so I can be sure that wherever I’m using jquery validators, I’m getting my date validator.  I also called the above method from $(document).ready();

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
            "~/Scripts/jquery.unobtrusive*",
            "~/Scripts/jquery.validate*",
            "~/Scripts/custom.jquery.validate.js"));

To be fair, the RFC does say only ISO dates should be converted, which Chrome does do.  What is alarming is that IE 10 (as tested on my Windows 8 machine) handles new Date('19/11/2012') and new Date('11/19/2012').  I wonder what month I'll get on IE :S

Post a comment

comments powered by Disqus