Datepicker: Handle dates before year 100

Fixes #7098
This commit is contained in:
Matthew Wartman 2020-01-22 11:54:50 -06:00
parent 862121ea6e
commit d0b8329eb0
3 changed files with 42 additions and 21 deletions

View File

@ -457,7 +457,7 @@ QUnit.test( "keystrokes", function( assert ) {
} ); } );
QUnit.test( "mouse", function( assert ) { QUnit.test( "mouse", function( assert ) {
assert.expect( 15 ); assert.expect( 16 );
var inl, var inl,
inp = testHelper.init( "#inp" ), inp = testHelper.init( "#inp" ),
dp = $( "#ui-datepicker-div" ), dp = $( "#ui-datepicker-div" ),
@ -470,6 +470,10 @@ QUnit.test( "mouse", function( assert ) {
$( ".ui-datepicker-calendar tbody a:contains(12)", dp ).simulate( "click", {} ); $( ".ui-datepicker-calendar tbody a:contains(12)", dp ).simulate( "click", {} );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), new Date( 2008, 2 - 1, 12 ), testHelper.equalsDate( assert, inp.datepicker( "getDate" ), new Date( 2008, 2 - 1, 12 ),
"Mouse click - preset" ); "Mouse click - preset" );
inp.val( "02/04/0001" ).datepicker( "show" );
$( ".ui-datepicker-calendar tbody a:contains(12)", dp ).simulate( "click", {} );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), $.datepicker._newDate( 1, 2 - 1, 12 ),
"Mouse click - year 0-99" );
inp.val( "02/04/2008" ).datepicker( "show" ); inp.val( "02/04/2008" ).datepicker( "show" );
inp.val( "" ).datepicker( "show" ); inp.val( "" ).datepicker( "show" );
$( "button.ui-datepicker-close", dp ).simulate( "click", {} ); $( "button.ui-datepicker-close", dp ).simulate( "click", {} );

View File

@ -267,7 +267,7 @@ QUnit.test( "otherMonths", function( assert ) {
} ); } );
QUnit.test( "defaultDate", function( assert ) { QUnit.test( "defaultDate", function( assert ) {
assert.expect( 16 ); assert.expect( 18 );
var inp = testHelper.init( "#inp" ), var inp = testHelper.init( "#inp" ),
date = new Date(); date = new Date();
inp.val( "" ).datepicker( "show" ). inp.val( "" ).datepicker( "show" ).
@ -350,6 +350,11 @@ QUnit.test( "defaultDate", function( assert ) {
simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
date = new Date( 2007, 7 - 1, 4 ); date = new Date( 2007, 7 - 1, 4 );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date, "Default date 07/04/2007" ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date, "Default date 07/04/2007" );
inp.datepicker( "option", { defaultDate: "07/04/0001" } ).
datepicker( "hide" ).val( "" ).datepicker( "show" ).
simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
date = $.datepicker._newDate( 1, 7 - 1, 4 );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date, "Default date 07/04/0001" );
inp.datepicker( "option", { dateFormat: "yy-mm-dd", defaultDate: "2007-04-02" } ). inp.datepicker( "option", { dateFormat: "yy-mm-dd", defaultDate: "2007-04-02" } ).
datepicker( "hide" ).val( "" ).datepicker( "show" ). datepicker( "hide" ).val( "" ).datepicker( "show" ).
simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
@ -362,6 +367,11 @@ QUnit.test( "defaultDate", function( assert ) {
datepicker( "hide" ).val( "" ).datepicker( "show" ). datepicker( "hide" ).val( "" ).datepicker( "show" ).
simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date, "Default date 01/26/2007" ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date, "Default date 01/26/2007" );
date = $.datepicker._newDate( 1, 1 - 1, 26 );
inp.datepicker( "option", { defaultDate: date } ).
datepicker( "hide" ).val( "" ).datepicker( "show" ).
simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date, "Default date 01/26/0001" );
} ); } );
QUnit.test( "miscellaneous", function( assert ) { QUnit.test( "miscellaneous", function( assert ) {
@ -537,14 +547,17 @@ QUnit.test( "minMax", function( assert ) {
} ); } );
QUnit.test( "setDate", function( assert ) { QUnit.test( "setDate", function( assert ) {
assert.expect( 24 ); assert.expect( 26 );
var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone,
inp = testHelper.init( "#inp" ), inp = testHelper.init( "#inp" ),
date1 = new Date( 2008, 6 - 1, 4 ), date1 = new Date( 2008, 6 - 1, 4 ),
date2 = new Date(); date2 = new Date(),
date3 = $.datepicker._newDate( 1, 4 - 1, 1 );
assert.ok( inp.datepicker( "getDate" ) == null, "Set date - default" ); assert.ok( inp.datepicker( "getDate" ) == null, "Set date - default" );
inp.datepicker( "setDate", date1 ); inp.datepicker( "setDate", date1 );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date1, "Set date - 2008-06-04" ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date1, "Set date - 2008-06-04" );
inp.datepicker( "setDate", date3 );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date3, "Set date - 0001-04-01" );
date1 = new Date(); date1 = new Date();
date1.setDate( date1.getDate() + 7 ); date1.setDate( date1.getDate() + 7 );
inp.datepicker( "setDate", +7 ); inp.datepicker( "setDate", +7 );
@ -568,6 +581,10 @@ QUnit.test( "setDate", function( assert ) {
date1.setDate( date1.getDate() - 21 ); date1.setDate( date1.getDate() - 21 );
inp.datepicker( "setDate", "c -3 w" ); inp.datepicker( "setDate", "c -3 w" );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date1, "Set date - c -3 w" ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date1, "Set date - c -3 w" );
date3 = new Date(date1);
date3.setFullYear( 1 );
inp.datepicker( "setDate", "c " + (1 - date1.getFullYear()) + " y" );
testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date3, "Set date - 0001 relatively" );
// Inline // Inline
inl = testHelper.init( "#inl" ); inl = testHelper.init( "#inl" );

View File

@ -1406,7 +1406,7 @@ $.extend( Datepicker.prototype, {
break; break;
case "o": case "o":
output += formatNumber( "o", output += formatNumber( "o",
Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 ); Math.round( ( this._newDate( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - this._newDate( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
break; break;
case "m": case "m":
output += formatNumber( "m", date.getMonth() + 1, 2 ); output += formatNumber( "m", date.getMonth() + 1, 2 );
@ -1563,7 +1563,7 @@ $.extend( Datepicker.prototype, {
} }
matches = pattern.exec( offset ); matches = pattern.exec( offset );
} }
return new Date( year, month, day ); return $.datepicker._newDate( year, month, day );
}, },
newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) : newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
@ -1615,7 +1615,7 @@ $.extend( Datepicker.prototype, {
/* Retrieve the date(s) directly. */ /* Retrieve the date(s) directly. */
_getDate: function( inst ) { _getDate: function( inst ) {
var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
this._daylightSavingAdjust( new Date( this._daylightSavingAdjust( this._newDate(
inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
return startDate; return startDate;
}, },
@ -1667,7 +1667,7 @@ $.extend( Datepicker.prototype, {
printDate, dRow, tbody, daySettings, otherMonth, unselectable, printDate, dRow, tbody, daySettings, otherMonth, unselectable,
tempDate = new Date(), tempDate = new Date(),
today = this._daylightSavingAdjust( today = this._daylightSavingAdjust(
new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time this._newDate( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
isRTL = this._get( inst, "isRTL" ), isRTL = this._get( inst, "isRTL" ),
showButtonPanel = this._get( inst, "showButtonPanel" ), showButtonPanel = this._get( inst, "showButtonPanel" ),
hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
@ -1677,7 +1677,7 @@ $.extend( Datepicker.prototype, {
stepMonths = this._get( inst, "stepMonths" ), stepMonths = this._get( inst, "stepMonths" ),
isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) : currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ), this._newDate( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
minDate = this._getMinMaxDate( inst, "min" ), minDate = this._getMinMaxDate( inst, "min" ),
maxDate = this._getMinMaxDate( inst, "max" ), maxDate = this._getMinMaxDate( inst, "max" ),
drawMonth = inst.drawMonth - showCurrentAtPos, drawMonth = inst.drawMonth - showCurrentAtPos,
@ -1688,10 +1688,10 @@ $.extend( Datepicker.prototype, {
drawYear--; drawYear--;
} }
if ( maxDate ) { if ( maxDate ) {
maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), maxDraw = this._daylightSavingAdjust( this._newDate( maxDate.getFullYear(),
maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) ); maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw ); maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) { while ( this._daylightSavingAdjust( this._newDate( drawYear, drawMonth, 1 ) ) > maxDraw ) {
drawMonth--; drawMonth--;
if ( drawMonth < 0 ) { if ( drawMonth < 0 ) {
drawMonth = 11; drawMonth = 11;
@ -1704,7 +1704,7 @@ $.extend( Datepicker.prototype, {
prevText = this._get( inst, "prevText" ); prevText = this._get( inst, "prevText" );
prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText, prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), this._daylightSavingAdjust( this._newDate( drawYear, drawMonth - stepMonths, 1 ) ),
this._getFormatConfig( inst ) ) ); this._getFormatConfig( inst ) ) );
prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ? prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?
@ -1714,7 +1714,7 @@ $.extend( Datepicker.prototype, {
nextText = this._get( inst, "nextText" ); nextText = this._get( inst, "nextText" );
nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText, nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), this._daylightSavingAdjust( this._newDate( drawYear, drawMonth + stepMonths, 1 ) ),
this._getFormatConfig( inst ) ) ); this._getFormatConfig( inst ) ) );
next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ? next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?
@ -1752,7 +1752,7 @@ $.extend( Datepicker.prototype, {
group = ""; group = "";
this.maxRows = 4; this.maxRows = 4;
for ( col = 0; col < numMonths[ 1 ]; col++ ) { for ( col = 0; col < numMonths[ 1 ]; col++ ) {
selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) ); selectedDate = this._daylightSavingAdjust( this._newDate( drawYear, drawMonth, inst.selectedDay ) );
cornerClass = " ui-corner-all"; cornerClass = " ui-corner-all";
calender = ""; calender = "";
if ( isMultiMonth ) { if ( isMultiMonth ) {
@ -1790,7 +1790,7 @@ $.extend( Datepicker.prototype, {
curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043) numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
this.maxRows = numRows; this.maxRows = numRows;
printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) ); printDate = this._daylightSavingAdjust( this._newDate( drawYear, drawMonth, 1 - leadDays ) );
for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
calender += "<tr>"; calender += "<tr>";
tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
@ -1920,7 +1920,7 @@ $.extend( Datepicker.prototype, {
var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
month = inst.selectedMonth + ( period === "M" ? offset : 0 ), month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ), day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) ); date = this._restrictMinMax( inst, this._daylightSavingAdjust( this._newDate( year, month, day ) ) );
inst.selectedDay = date.getDate(); inst.selectedDay = date.getDate();
inst.drawMonth = inst.selectedMonth = date.getMonth(); inst.drawMonth = inst.selectedMonth = date.getMonth();
@ -1960,18 +1960,18 @@ $.extend( Datepicker.prototype, {
/* Find the number of days in a given month. */ /* Find the number of days in a given month. */
_getDaysInMonth: function( year, month ) { _getDaysInMonth: function( year, month ) {
return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate(); return 32 - this._daylightSavingAdjust( this._newDate( year, month, 32 ) ).getDate();
}, },
/* Find the day of the week of the first of a month. */ /* Find the day of the week of the first of a month. */
_getFirstDayOfMonth: function( year, month ) { _getFirstDayOfMonth: function( year, month ) {
return new Date( year, month, 1 ).getDay(); return this._newDate( year, month, 1 ).getDay();
}, },
/* Determines if we should allow a "next/prev" month display change. */ /* Determines if we should allow a "next/prev" month display change. */
_canAdjustMonth: function( inst, offset, curYear, curMonth ) { _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
var numMonths = this._getNumberOfMonths( inst ), var numMonths = this._getNumberOfMonths( inst ),
date = this._daylightSavingAdjust( new Date( curYear, date = this._daylightSavingAdjust( this._newDate( curYear,
curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) ); curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
if ( offset < 0 ) { if ( offset < 0 ) {
@ -2025,8 +2025,8 @@ $.extend( Datepicker.prototype, {
inst.currentYear = inst.selectedYear; inst.currentYear = inst.selectedYear;
} }
var date = ( day ? ( typeof day === "object" ? day : var date = ( day ? ( typeof day === "object" ? day :
this._daylightSavingAdjust( new Date( year, month, day ) ) ) : this._daylightSavingAdjust( this._newDate( year, month, day ) ) ) :
this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); this._daylightSavingAdjust( this._newDate( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
}, },