Unobtrusive validation in Chrome won't validate with dd/mm/yyyy
Asked Answered
L

12

55

I'm trying to use the simplest possible scenario using a date picker in different browsers. I suspect I'm doing something very simple the wrong way but after lots of searching around I still haven't found a solution. Below is some sample code that represents what I'm attempting.

If I use Chrome (v12.0.742.122) and pick a date from the picker like 13/08/2011 the jQuery validation logic will not allow the page to submit even though I've explicitly specified the format as 'dd/mm/yy'.

If I change the format to 'dd/M/yy' and choose a date like 13/Aug/2011 it works in Chrome but then won't submit for me in IE (v8.0.7600.16385). In FireFox (v3.6.18) both formats work.

What validation script do I need to be able to support date formats of 'dd/mm/yy' in Chrome?

<html>
 <head>
  <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
  <script type="text/javascript" src="jquery-1.4.4.js"></script>
  <script type="text/javascript" src="jquery.validate.js"></script>
  <script type="text/javascript" src="jquery.validate.unobtrusive.js"></script>
  <script type="text/javascript" src="jquery-ui.js"></script>
  <script type="text/javascript">
      $(document).ready(function () {
    $('.date').datepicker({ dateFormat: 'dd/mm/yy' });
            $.validator.addMethod("dateRule", function(value, element) {
      return true;
    },
    "Error message");
      });
  </script>
 </head>
 <body>
    <form>
        Date: <input type="text" name="myDate" class="date dateRule" />
        <input type="submit" />
    </form>
 </body>
</html>
Leptorrhine answered 2/8, 2011 at 2:41 Comment(0)
L
52

Four hours later I finally stumbled across the answer. For some reason Chrome seems to have some inbuilt predilection to use US date formats where IE and FireFox are able to be sensible and use the regional settings on the OS.

jQuery.validator.methods["date"] = function (value, element) { return true; } 
Leptorrhine answered 2/8, 2011 at 6:15 Comment(5)
It took me about an hour to find your answer here. This line of code works perfectly.Parsley
Where is this line supposed to be placed?Shark
@Shark you could put it pretty much anywhere that will execute it prior to your date validation needing to occur. I have it in the $(document).ready function.Leptorrhine
This ignores the validation !! Are you serious ?!Cataphoresis
IE and FireFox DO NOT use the regional settings on the OS - its just that that if your enter 76/85/2015 they produce a date even through its not a valid date. Only Chome reports it correctly as an invalid date. This answer means you never get client side validation.Shiah
T
51

You can use the Globalize.js plugin available here: https://github.com/jquery/globalize

Then simply redefine the validate method in your web site's main script file like so (avoid editing the jquery.validate.js library file as you may want to update it in future):

$.validator.methods.date = function (value, element) {
    return this.optional(element) || Globalize.parseDate(value, "d/M/y", "en");
}
Tierza answered 23/11, 2012 at 12:2 Comment(2)
This should be considered as the answer. +1Pyxidium
To anyone else looking for this... there should be a big "M" i.e d/M/y as a small signify's minutes which works when it shouldn't!Tuppeny
E
22

I know I'm a bit late to the party, but here's the solution I used to Chrome validation not accepting UK format dates. A simple plug and play validation, it doesn't rely on any plugins or modifying any files. It will accept any date between 1/1/1900 and 31/31/2999, so US or UK format. Obviously there are invalid dates that will sneak past, but you can tweak the regex to your heart's content. This met my needs as it will be used on a low traffic area of the site, with server-side validation. The area of the site in question is built with ASP.net MVC.

jQuery.validator.methods.date = function(value, element) {
    var dateRegex = /^(0?[1-9]\/|[12]\d\/|3[01]\/){2}(19|20)\d\d$/;
    return this.optional(element) || dateRegex.test(value);
};
Estep answered 4/4, 2013 at 12:45 Comment(6)
I used a regex that's a bit more complex than this one, but less complex than the massive one in another answer. It doesn't check for the end of the string, in order to allow times to follow. var dateRegex = /^(0?[1-9]|[12]\d|3[01])\/(0?[1-9]|10|11|12)\/(19|20)\d\d\D/; Out of range issues are handled by the constraint of the date or datetime picker.Morris
Actually, make that var dateRegex = /^(0?[1-9]|[12]\d|3[01])\/(0?[1-9]|10|11|12)\/(19|20)\d\d(\D.*)?$/; Now it supports no trailing characters in cases where it's only a date (I was working with datetimes)Morris
Thanks for those David :). Just to clarify for anyone finding this, the top one accepts a UK date followed by a non-digit and then anything else. The bottom one will accept a UK format date only. They provide a much better match for UK format only dates, although there will still be a few edge cases missed (such as 31/02).Estep
Thanks you! AwesomeRegulation
This is the best pragmatic response combining client and server side validation. I've just spent several hours wrestling with the globalize and related globalize js files without getting them to work in all of IE, Chrome and Firefox and eventually backing everything out. If I'd used this from the start I would have spent 10 minutes with no issues evident to the user.Beryl
Thank You...This is so much cleaner then adding yet another jquery library.Babbette
K
18

Looks like this issue has been raised with the JQuery team.

https://github.com/jzaefferer/jquery-validation/issues/153

Looks like the workaround for now is to use dateITA in additional-methods.js

It looks like this:

jQuery.validator.addMethod(
    "dateITA",
    function(value, element) {
        var check = false;
        var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
        if( re.test(value)){
            var adata = value.split('/');
            var gg = parseInt(adata[0],10);
            var mm = parseInt(adata[1],10);
            var aaaa = parseInt(adata[2],10);
            var xdata = new Date(aaaa,mm-1,gg);
            if ( ( xdata.getFullYear() == aaaa ) 
                   && ( xdata.getMonth () == mm - 1 ) 
                   && ( xdata.getDate() == gg ) )
                check = true;
            else
                check = false;
        } else
            check = false;
        return this.optional(element) || check;
    },
    "Please enter a correct date"
);

If you add that validator you can then attach your datepicker to the '.dateITA' class.

Thus far this has worked well for me to get me beyond this stupid issue in Chrome.

Ketonuria answered 2/11, 2011 at 5:53 Comment(0)
V
2

This remains a problem in .net mvc4, where the EditorFor DateTime still produces a data-val-date attribute, despite clear documentation in the jQuery validation plugin not to use it!!! Hopefully microsoft fixes this and data-val-date is never heard of again!

In the meantime you could use the suggested library via modernizr:

yepnope({
    test: isNaN(Date.parse("23/2/2012")),
    nope: 'http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/additional-methods.min.js',
    complete: function () {
        $.validator.methods.date = $.validator.methods.dateITA
    }
});

or if not wanting to use yepnope/modernizr, and to get rid of the UTC component of the dateITA method (if using this library to enter a local time, dates will not always validate on the 1st or last day of the month unless on the Greenwich line - i.e. UTC +0):

(function ($) {
    var invokeTestDate = function () {
        return $.validator.methods.date.call({
            optional: function () {
                return false;
            }, (new Date(2012,8,23)).toLocaleDateString(), null);
    };
    if (invokeTestDate()) {
        return;
    }

    // http://docs.jquery.com/Plugins/Validation/Methods/date

    $.validator.methods.date = function (value, element) {
        //ES - Chrome does not use the locale when new Date objects instantiated:
        //return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
        var d = new Date();
        return this.optional(element) || !/Invalid|NaN/.test(new Date(d.toLocaleDateString(value)));
    }
})(jQuery);
Vaccaro answered 26/9, 2013 at 10:17 Comment(0)
O
2

I found the simplest correction of this error to be the following code snippet after calling your validation file;

    jQuery.validator.methods["date"] = function (value, element){
        var shortDateFormat = "dd/mm/yy";
        var res = true;
        try {
            $.datepicker.parseDate(shortDateFormat, value);
        } catch (error) {
            res = false;
        }
        return res;
    }

Even in versions found in 2016 im still having this issue without the above code in Chrome and not Firefox.

This is my preferred solution as it does not require any additional libraries or plugins to work.

I found this code snippet while googling the issue here.

Operatic answered 28/4, 2016 at 1:14 Comment(0)
B
2

We use the following to work on our projects;

if ($.validator) {
    $.validator.addMethod("date",
        function (value, element, params) {
            if (this.optional(element)) {
                return true;
            }

            var ok = true;
            try {
                $.datepicker.parseDate("dd/mm/yy", value);
            }
            catch (err) {
                ok = false;
            }
            return ok;
        });
}
Blabber answered 26/9, 2016 at 14:39 Comment(0)
V
1

May this code help you.

$.validator.addMethod(
         "date",
         function(value, element) {
              var check = false;
              var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
              var reBR = /^\d{4}\-\d{1,2}\-\d{1,2}$/;
              if( re.test(value)){
                   var adata = value.split('/');
                   var gg = parseInt(adata[0],10);
                   var mm = parseInt(adata[1],10);
                   var aaaa = parseInt(adata[2],10);
                   var xdata = new Date(aaaa,mm-1,gg);
                   if ( ( xdata.getFullYear() == aaaa ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == gg ) )
                        check = true;
                   else
                        check = false;
              } else if( reBR.test(value)){
                   var adata = value.split('-');
                   var aaaa = parseInt(adata[0],10);
                   var mm = parseInt(adata[1],10);
                   var gg = parseInt(adata[2],10);
                   var xdata = new Date(aaaa,mm-1,gg);
                   if ( ( xdata.getFullYear() == aaaa ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == gg ) )
                        check = true;
                   else
                        check = false;
              } else
                   check = false;
                   console.log(check);
              return this.optional(element) || check;
         },
         "Por favor insira uma data válida"
    );
Villada answered 13/12, 2016 at 20:47 Comment(1)
Where did you get this code? Did you create it yourself? Why do you think it will work?Constitutionalism
L
0

should change the dateRule method you define in validate to (the regex is just a simple one for example):

$.validator.addMethod(
    "dateRule",
    function(value, element) {
        return value.match(/^\d\d?\/\d\d?\/\d\d$/);
    },
    "Please enter a date in the format dd/mm/yy"
);

you can switch the regex for whatever you wish. I got this regex for date from here which supports M/D/YY or M/D/YYYY or MM/DD/YYYY or MM/DD/YY: 1/1/1920 through 12/31/2019; Feb 29 and 30 always allowed

^((0?[13578]|10|12)(-|\/)(([1-9])|(0[1-9])|([12])([0-9]?)|(3[01]?))(-|\/)((19)([2-9])(\d{1})|(20)([01])(\d{1})|([8901])(\d{1}))|(0?[2469]|11)(-|\/)(([1-9])|(0[1-9])|([12])([0-9]?)|(3[0]?))(-|\/)((19)([2-9])(\d{1})|(20)([01])(\d{1})|([8901])(\d{1})))$
Laterality answered 2/8, 2011 at 3:21 Comment(5)
That would be the next step. At the moment I can't even get Chrome to pass the validation by always returning true.Leptorrhine
i can't replicate your problem. i seem to be able to submit a form. could you try not including jquery.validate.unobtrusive.js and adding a $('form').validate();Laterality
Excluding the jquery.validate.unobtrusive.js gets Chrome submitting the form. Now I need to understand how to configure the unobtrusive validation rule to work.Leptorrhine
this might help: click hereLaterality
This doesn't seem to help in getting Chrome to validate dd/mm/yyyy since it also allows mm/dd/yyyyKetonuria
C
0

I also found a solution that appears to work for any culture.

http://devdens.blogspot.com/2011/11/jquery-validation-fix-for-date-format_29.html

It requires you to modify the actual jquery.valdiation.min.js file, but so far it's working for me.

Comitative answered 19/9, 2012 at 15:57 Comment(1)
Answers should contain more information than simply a link. You should (as a bear minimum) summarise some of the content into your answer.Acidulate
T
0

This is the only solution that worked for me: http://www.codeproject.com/Tips/579279/Fixing-jQuery-non-US-Date-Validation-for-Chrome

 jQuery.extend(jQuery.validator.methods, {
        date: function (value, element) {
            var isChrome = window.chrome;
            // make correction for chrome
            if (isChrome) {
                var d = new Date();
                return this.optional(element) || 
                !/Invalid|NaN/.test(new Date(d.toLocaleDateString(value)));
            }
            // leave default behavior
            else {
                return this.optional(element) || 
                !/Invalid|NaN/.test(new Date(value));
            }
        }
    }); 
Thing answered 11/3, 2015 at 10:1 Comment(0)
S
0

Or we might try to overwrite the validator instead of ignoring it.

$.validator.addMethod("date", function (value, element) {
    var result = true;
    try {
        $.datepicker.parseDate('dd/mm/yy', value);
    }
    catch (err) {
        result = false;
    }
    return result;
});
Startle answered 18/1, 2018 at 2:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.