Cannot select years BC

Viewed 1539

I'm working on a project that need to handle dates BC (eg 100BC, or 2000BC) as well as 2014AC etc..

In the API documentation of Datepicker, it is stated that minDate and maxDate can be set using javascript Date object (with has min and max of aprox 285,616 years on either side of 1970).

It seems to be impossible to set years in BC or even before 1/1/99.

$("#date").datepicker({
    dateFormat: 'dd-mm-yy',
    showButtonPanel: true,
    changeMonth: true,
    changeYear: true,
    yearRange: '0:2010',
    inline: true });

How can I surpass this limit?

3 Answers

I think the root issue is a math/logic bug. Initially, when the year drop down appears, it shows 19, currently for the year 2019. Switch to 1492, all good. Switch to 666, all good. Switch to 121, all good. Switch to 99... uh oh it's now 1999.

You can test this here:

$(function() {
  $("#datepicker").datepicker({
    dateFormat: 'dd/mm/yy',
    showButtonPanel: true,
    changeMonth: true,
    changeYear: true,
    yearRange: 'c-22019:c+1',
    inline: true
  });
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<p>Date: <input type="text" id="datepicker"></p>

This causes an issue if you try to work your way back to anything under 100 AD, like -1, or 1 BC.

It looks like the logic that builds the year drop down needs some help. You can select a date in BC, yet it's just hard to get there from the range. Will need to research it a bit and update later.

Update

I was looking at yearRange with a different logic than what is used. To get desired results, it's best to work based on the Current Year format c-nn:c+nn.

$(function() {
  $("#datepicker").datepicker({
    dateFormat: 'dd/mm/yy',
    showButtonPanel: true,
    changeMonth: true,
    changeYear: true,
    yearRange: '-2000:2020',
    inline: true
  });
  
  var oldD = new Date();
  oldD.setYear(-1);
  
  $("#datepicker").datepicker("option", "defaultDate", oldD);
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<p>Date: <input type="text" id="datepicker"></p>

There is still a 0 to 99 issue that I think is related to Date assuming and adding the 19 when it gets a year passed to it. I think this can be fixed by using a Date object, yet this was not done in this part of the jQuery UI Code:

    // Year selection
    if ( !inst.yearshtml ) {
        inst.yearshtml = "";
        if ( secondary || !changeYear ) {
            html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
        } else {

            // determine range of years to display
            years = this._get( inst, "yearRange" ).split( ":" );
            thisYear = new Date().getFullYear();
            determineYear = function( value ) {
                var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
                    ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
                    parseInt( value, 10 ) ) );
                return ( isNaN( year ) ? thisYear : year );
            };
            year = determineYear( years[ 0 ] );
            endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
            year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
            endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
            inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
            for ( ; year <= endYear; year++ ) {
                inst.yearshtml += "<option value='" + year + "'" +
                    ( year === drawYear ? " selected='selected'" : "" ) +
                    ">" + year + "</option>";
            }
            inst.yearshtml += "</select>";

            html += inst.yearshtml;
            inst.yearshtml = null;
        }
    }
Related