Search code examples
jqueryjquery-ui-datepicker

jQuery DatePicker d/m/yy format


Working on a problem, and the formatting of the dateFormat is not working as It thought it would. Can anyone see anything that stands out? It works if I change the date to a different format

var check_in = [["25/11/2021", "28/11/2021"]];

if ($(window).width() > 700) {
    $('#arrival, #contact-arrival').datepicker({
        minDate: '0M',
        numberOfMonths: 2,
        beforeShowDay: function(date) {
            var string = jQuery.datepicker.formatDate('d/m/yy', date);
            for (var i = 0; i < check_in.length; i++) {
              if (Array.isArray(check_in[i])) {
                var from = new Date(check_in[i][0]);
                var to = new Date(check_in[i][1]);
                var current = new Date(string);
                if (current >= from && current <= to) return false;
              }
            }
            return [check_in.indexOf(string) == -1]
          },
        dateFormat: 'dd M yy',
        onSelect: function (dateText, inst) {
            $('#departure, #contact-departure').datepicker("option", "minDate", dateText);
        }
    });

In the above script, the jQuery.datepicker.formatDate('d/m/yy', date); is not recognizing var check_in = [["25/11/2021", "28/11/2021"]];

If I change the code to var string = jQuery.datepicker.formatDate('d/M/yy', date); and the format of the array to var check_in = [["25/Nov/2021", "28/Nov/2021"]]; Everything works, but the data is being pulled in the first format 1/1/2021

Hope someone with a fresh pair of eyes can see what I am doing wrong.

Many thanks.


Solution

  • The problem is that you are trying to use Date() with strings that it does not recognise. Date() accepts strings like 2011-10-10, but not 25/11/2021. I confirmed this by some simple console.log()ing, which shows lots of Invalid date errors.

    So your from and to variables are never set, and tests against them do not work. The problem is not with jQuery.datepicker.formatDate() at all (this wording in the question confused me and it took some tinkering to understand what you mean).

    So first, we need to somehow generate dates from those strings. There are many examples of how to parse strings into JS Dates here on SO (here's one), but jQueryUI's Datepicker has a handy utility for that built in: $.datepicker.parseDate. We can use that to set your vars correctly:

    var from = $.datepicker.parseDate('dd/mm/yy', check_in[i][0]);
    var to   = $.datepicker.parseDate('dd/mm/yy', check_in[i][1]);
    

    I did that and re-ran your code, and was still getting Invalid date errors, specifically for the line which sets current. That suffers from exactly the same problem - string is in a format Date does not understand.

    But before fixing that, take a step back - the code takes the date object beforeShowDay() gets as a parameter (date), converts it to a string (string), then converts that string back into a date (current), and uses that to compare with other date objects (from, to). If we start with a date, and want to compare it with dates, there's no need for all that converting. We can get rid of string entirely, and just use date.

    There's one last problem - that string is still used in the very last test:

    return [check_in.indexOf(string) == -1]
    

    We can't just use date in place of string here, bcs it's a Date object, and the check_in elements are strings. So we really need to convert date to a string to make that comparison.

    But again stepping back, if I've understood your code correctly, this test is redundant. The code above has already checked for dates inside the check_in range, and blocked them. Everything else should be allowed, right? So we can simply return [true]; here?

    Here's a simplified, working snippet with all these fixes applied. Click run to see it in action.

    var check_in = [
      ["25/11/2021", "28/11/2021"]
    ];
    
    $('#arrival').datepicker({
      minDate: '0M',
      numberOfMonths: 2,
      beforeShowDay: function(date) {
    
        for (var i = 0; i < check_in.length; i++) {
          if (Array.isArray(check_in[i])) {
    
            var from = $.datepicker.parseDate('dd/mm/yy', check_in[i][0]);
            var to = $.datepicker.parseDate('dd/mm/yy', check_in[i][1]);
    
            console.log(date, from, to);
            if (date >= from && date <= to) return [false];
          }
        }
        return [true];
      },
      dateFormat: 'dd M yy',
    });
    <link href="https://code.jquery.com/ui/1.13.0-alpha.1/themes/smoothness/jquery-ui.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
    </script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    
    <div id="arrival"></div>