The reason for client-side validation is that the jquery.validate.js
plugin used by jquery.validate.unobtrusive.js
checks dates based on the MM/dd/yyyy
format and input dates based on the dd/MM/yyyy
format.
The specific code used in jquery.validate.js
to verify
date: function(value, element) { return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); }
which, depending on the browser you use, will give different results (in Chrome new Date('22/12/1986')
1987-10-11T13:30:00.000Z
new Date('22/12/1986')
returns Invalid Date
, but in FireFox it returns 1987-10-11T13:30:00.000Z
, which is valid, not date when you entered)
You need to override $.validator
to format dates in your culture. One option is to use the jquery.globalize plugin.
Alternatively, you can write your own script. Note that the following script is taken from my own plugin, used with the @Html.DatePickerFor()
extension method, which generates a datupike. The extension method adds the html attributes for the date format based on the server culture and is read using a line of code var format = regex.exec(this.inputFormat);
which I commented out and replaced with your hard format. If you only need the dd/MM/yyyy
format, then the script can be simplified because you only need the little-endian format
<script type="text/javascript"> // Override default date validator format to allow culture specific format $.validator.methods.date = function (value, element) { return this.optional(element) || globalDate(value).isValid(); }; globalDate = function (value) { // Initialise a new date var date = new Date(); date.setHours(0, 0, 0, 0); if (value == undefined) { // Return todays date return date; } // Get the components of the format // The separator can be forward slash, hyphen, dot and/or space var regex = new RegExp(/([dMy]+)([\s/.-]+)([dMy]+)([\s/.-]+)([dMy]+)/); //------------- see notes above //var format = regex.exec(this.inputFormat); var format = regex.exec('dd/MM/yyyy'); //------------- // Get the components of the value regex = new RegExp(/(\d+)([\s/.-]+)(\d+)([\s/.-]+)(\d+)/); value = regex.exec(value); // Check the value is valid if (value === null || value[2] !== format[2] || value[4] !== format[4]) { // Its not valid date.setTime(Number.NaN); return date; } // TODO: What if year entered as 2 digits? var day = Number.NaN; var month = Number.NaN; var year = Number.NAN; if (format[1].charAt(0) === 'd') { // little-endian (day, month, year) day = parseInt(value[1]); month = parseInt(value[3]) - 1; year = parseInt(value[5]); } else if (format[1].charAt(0) === 'M') { // middle-endian (month, day, year) day = parseInt(value[3]); month = parseInt(value[1]) - 1; year = parseInt(value[5]); } else { // big endian (year, month, day) day = parseInt(value[5]); month = parseInt(value[3]) - 1; year = parseInt(value[1]); } date.setFullYear(year); date.setMonth(month); date.setDate(day); // Check its valid if (date.getDate() !== day || date.getMonth() !== month || date.getFullYear() !== year) { date.setTime(Number.NaN); return date; } return date; } // Methods Date.prototype.isValid = function () { return !isNaN(this.getTime()); } </script>
Side note: your [RegularExpression]
attribute [RegularExpression]
nothing and can be removed.