7

Once I have set the minDate property of a datepicker with the convenient string syntax

$(elem).datepicker('option','minDate','+1d +3m'); 

how can I get the date object of the minDate? To help illustrate, there is a method

 $(elem).datepicker('getDate');

which returns the date that is entered in the input in the format of a date object. I would like the same thing but for datepicker('getMinDate'). There is an option like this

$(elem).datepicker('option','minDate');

but this returns '+1d +3m' which is not helpful. I need the actual date object to compare with another date object. Any ideas?

Adrian Adkison
  • 3,537
  • 5
  • 33
  • 36
  • I want to add that, when one sets minDate with datepicker, jQuery UI must parse the date object in order to create the date range that the user can select on the ui. Is that minDate date object that was calculated, accessible in any way is really what I am asking. – Adrian Adkison May 21 '10 at 20:34

2 Answers2

8

jQuery uses its _determineDate() function to calculate the minDate date object based on its attribute. I modified its behaviour and made a function. Note that it only deals with the "offset" type of values and nothing else.

/* minDateAttr is the minDate option of the datepicker, eg '+1d +3m' */
function getMinDate(minDateAttr) {
    var minDate = new Date();
    var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
    var matches = pattern.exec(minDateAttr);
    while (matches) {
        switch (matches[2] || 'd') {
            case 'd' : case 'D' :
                minDate.setDate(minDate.getDate() + parseInt(matches[1],10));
                break;
            case 'w' : case 'W' :
                minDate.setDate(minDate.getDate() + parseInt(matches[1],10) * 7);
                break;
            case 'm' : case 'M' :
                minDate.setMonth(minDate.getMonth() + parseInt(matches[1],10));
                break;
            case 'y': case 'Y' :
                minDate.setYear(minDate.getFullYear() + parseInt(matches[1],10));
                break;
        }
        matches = pattern.exec(minDateAttr);
    }
    return minDate;
}


I originally planned on answering the following, but came up with a (better) solution - the one above. However, I'm going to include it, in case it's needed for debugging reasons etc.

The _determineDate() function is technically availible for use, but it's not supposed to be used and may change in the future. Nevertheless, this would be how to use it:

var minDateAttr = $(elem).datepicker("option", "minDate");
var inst = $(elem).data("datepicker");
var minDateObj = $.datepicker._determineDate(inst, minDateAttr, new Date());
Simen Echholt
  • 11,243
  • 2
  • 34
  • 26
  • Wow, Stackoverflow, you never cease to amaze me. This is great! I would prefer the first solution. Hate breaking away from framework update paths :). – Adrian Adkison May 22 '10 at 08:05
  • Agreed this awesome. We're using this in a project and it's possible the bug is in our code or a time zone issue, but today 8/30/2012, if i pass -6m to this function, i'm getting 3/01/2012. While if i use $.datepicker("setDate" , "-6m") on a datepicker with a date of today i get 2/29/2012. Could it be a leap year bug? – Dan Aug 30 '12 at 20:40
  • another note, changed computer clock to 8/30/2011 and the same issue occurs so it appears to not be related to leap year but instead occur when current date has higher than the amount of days in target month. somehow jquery ui version is solving for this but looking at source can't figure out how. – Dan Aug 31 '12 at 16:54
2

This update fixes a few bugs surrounding month calculation bugs, hours and leap years. Big props to Simen for the first version which was the foundation.

Also this version will allow for optional second param dateVal where you can pass a date to calculate from instead of using today's date.

function determineDate(dateAttr, dateVal) {
    var date = dateVal === undefined ? new Date() : new Date(dateVal);
    var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
    var matches = pattern.exec(dateAttr);

    var year = date.getFullYear();
    var month = date.getMonth();
    var day = date.getDate();

    while (matches) {
        switch (matches[2] || 'd') {
            case 'd' : case 'D' :
                day += parseInt(matches[1],10); break;
            case 'w' : case 'W' :
                day += parseInt(matches[1],10) * 7; break;
            case 'm' : case 'M' :
                month += parseInt(matches[1],10);
                day = Math.min(day, getDaysInMonth(year, month));
                break;
            case 'y': case 'Y' :
                year += parseInt(matches[1],10);
                day = Math.min(day, getDaysInMonth(year, month));
                break;
        }
        matches = pattern.exec(dateAttr);
    }

    var newdate =  new Date(year, month, day);

    newdate.setHours(0);
    newdate.setMinutes(0);
    newdate.setSeconds(0);
    newdate.setMilliseconds(0);


    return daylightSavingAdjust(newdate);

}

function daylightSavingAdjust(date){
    if (!date){
        return null;
    }
    date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
    return date;
}

function getDaysInMonth(year, month){
    return 32 - daylightSavingAdjust(new Date(year, month, 32)).getDate();
}
Dan
  • 194
  • 1
  • 9