UPDATE 31 Jan 2013: We have encountered this issue after we have updated our MVC3 project to MVC5. A year ago we have moved MVC3 to MVC4. And suddenly Chrome started to insist on incorrect date format, but everywhere else we have set Globalise locale to be en-Gb
. The only other alternative was to disable date validations which can also work – I trust server side validation more than I trust JavaScript ;-)
Today I came across the magical problem in Chrome – it ignores locale information for date format. So it always uses US format: “mm/dd/yyyy”. But largest part of the world is not using this messed up month-first approach (wink-wink).
So I spent a large part of the day to figure out how to fix this problem for all browsers. And this is what I have:
function getDateFormat(formatString) {
var separator = formatString.match(/[.\/\-\s].*?/);
var parts = formatString.split(/\W+/);
if (!separator || !parts || parts.length === 0) {
throw new Error("Invalid date format.");
}
return { separator: separator, parts: parts };
}
function MyParseDate(value, format) {
var parts = value.split(format.separator);
//NEVER use Date(0), this is locale specific!
// * en-GB: 1970-JAN-01
// * pt-BR: 1969-DEC-31
//var date = new Date(0);
//An arbitrary date 1970-DEC-15
var date = new Date(1970, 11, 15);
var year = -1;
var month = -1;
var day = -1;
if (parts.length === format.parts.length) {
for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
var val = parseInt(parts[i], 10) || 1;
switch (format.parts[i]) {
case 'dd':
case 'd':
day = val;
break;
case 'mm':
case 'm':
month = val - 1; // month is zero-based
break;
case 'yyyy':
year = val;
break;
}
}
}
// must be in this particular order, otherwise 29th of Feb in leap year would not validate
date.setFullYear(year);
date.setMonth(month);
date.setDate(day);
console.log("Date validated to " + date.toString());
// we can't rely on setDay(), setMonth(), setYear() because if value passed in is greater than allowed, it just ticks over
// to the next month/year. But we can compare if it was ticked over or not.
// If numbers provided are the same as resulting number, then date is fine.
return date.getDate() === day && date.getMonth() === month && date.getFullYear() === year;
}
jQuery.validator.addMethod('date',
function (value, element, params) {
if (this.optional(element)) {
return true;
}
try {
var format = getDateFormat('dd/mm/yyyy');
var result = MyParseDate(value, format);
return result;
} catch (err) {
console.log(err);
return false;
}
});
Just include this with your javascript.
I’m pretty certain that there is a bug (or a dozen) somewhere in my code. Please feel free to rub it in my face.
I have used code from Robert Gray’s blog post and added validation bit from redphx from discussion on Codeproject