From ea75bd3221b4453fb496b80aec06bcf77ef902ea Mon Sep 17 00:00:00 2001 From: Matthew Wartman Date: Wed, 22 Jan 2020 11:52:17 -0600 Subject: [PATCH 1/4] Datepicker: Add leading zeros when formatting dates < 1000 with "yy" --- tests/unit/datepicker/options.js | 4 +++- ui/widgets/datepicker.js | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/unit/datepicker/options.js b/tests/unit/datepicker/options.js index 7711e741233..9287aceeb89 100644 --- a/tests/unit/datepicker/options.js +++ b/tests/unit/datepicker/options.js @@ -1066,7 +1066,7 @@ QUnit.test( "Ticket #7244: date parser does not fail when too many numbers are p } ); QUnit.test( "formatDate", function( assert ) { - assert.expect( 16 ); + assert.expect( 17 ); testHelper.init( "#inp" ); var gmtDate, fr, settings; assert.equal( $.datepicker.formatDate( "d m y", new Date( 2001, 2 - 1, 3 ) ), @@ -1090,6 +1090,8 @@ QUnit.test( "formatDate", function( assert ) { assert.equal( $.datepicker.formatDate( "'day' d 'of' MM (''DD''), yy", new Date( 2001, 2 - 1, 3 ) ), "day 3 of February ('Saturday'), 2001", "Format date 'day' d 'of' MM ('DD'), yy" ); + assert.equal( $.datepicker.formatDate( "yy-mm-dd", $.datepicker._newDate( 999, 2 - 1, 3 ) ), + "0999-02-03", "Format ancient date yy-mm-dd"); gmtDate = new Date( 2001, 2 - 1, 3 ); gmtDate.setMinutes( gmtDate.getMinutes() - gmtDate.getTimezoneOffset() ); assert.equal( $.datepicker.formatDate( "@", gmtDate ), "981158400000", "Format date @" ); diff --git a/ui/widgets/datepicker.js b/ui/widgets/datepicker.js index 5e6321e1d44..44b513d1a82 100644 --- a/ui/widgets/datepicker.js +++ b/ui/widgets/datepicker.js @@ -1409,8 +1409,7 @@ $.extend( Datepicker.prototype, { output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); break; case "y": - output += ( lookAhead( "y" ) ? date.getFullYear() : - ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 ); + output += ( "0000" + date.getFullYear() ).slice( lookAhead( "y" ) ? -4 : -2 ); break; case "@": output += date.getTime(); @@ -2023,6 +2022,18 @@ $.extend( Datepicker.prototype, { this._daylightSavingAdjust( new Date( year, month, day ) ) ) : this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); + }, + + /* Create a Date from a year, month, and day, accounting for years 0-99. */ + _newDate: function( year, month, day ) { + var date = new Date( year, month, day ); + + // Offset dates in the incorrect range. Blindly calling setFullYear(year) would not handle out-of-range + // months/days causing the year to shift. + if ( year >= 0 && year <= 99 ) { + date.setFullYear( date.getFullYear() - 1900 ); + } + return date; } } ); From 862121ea6eccfd24106a1997fd258a6549d7703a Mon Sep 17 00:00:00 2001 From: Matthew Wartman Date: Wed, 22 Jan 2020 13:32:44 -0600 Subject: [PATCH 2/4] Datepicker: Parse dates before year 100 4-digit years, unix times, and windows times now handle years between 0 and 99. Additionally, negative unix times can be parsed. --- tests/unit/datepicker/helper.js | 4 ++-- tests/unit/datepicker/options.js | 7 ++++++- ui/widgets/datepicker.js | 12 +++++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/unit/datepicker/helper.js b/tests/unit/datepicker/helper.js index 7fd149bf156..7c9964d8d77 100644 --- a/tests/unit/datepicker/helper.js +++ b/tests/unit/datepicker/helper.js @@ -18,8 +18,8 @@ return $.extend( helper, { assert.ok( false, message + " - missing date" ); return; } - d1 = new Date( d1.getFullYear(), d1.getMonth(), d1.getDate() ); - d2 = new Date( d2.getFullYear(), d2.getMonth(), d2.getDate() ); + d1 = $.datepicker._newDate( d1.getFullYear(), d1.getMonth(), d1.getDate() ); + d2 = $.datepicker._newDate( d2.getFullYear(), d2.getMonth(), d2.getDate() ); assert.equal( d1.toString(), d2.toString(), message ); }, diff --git a/tests/unit/datepicker/options.js b/tests/unit/datepicker/options.js index 9287aceeb89..328a834d4a0 100644 --- a/tests/unit/datepicker/options.js +++ b/tests/unit/datepicker/options.js @@ -926,7 +926,7 @@ QUnit.test( "iso8601Week", function( assert ) { } ); QUnit.test( "parseDate", function( assert ) { - assert.expect( 26 ); + assert.expect( 29 ); testHelper.init( "#inp" ); var currentYear, gmtDate, fr, settings, zh; assert.ok( $.datepicker.parseDate( "d m y", "" ) == null, "Parse date empty" ); @@ -953,6 +953,8 @@ QUnit.test( "parseDate", function( assert ) { testHelper.equalsDate( assert, $.datepicker.parseDate( "'day' d 'of' MM (''DD''), yy", "day 3 of February ('Saturday'), 2001" ), new Date( 2001, 2 - 1, 3 ), "Parse date 'day' d 'of' MM (''DD''), yy" ); + testHelper.equalsDate( assert, $.datepicker.parseDate( "yy-mm-dd", "0001-02-03" ), + $.datepicker._newDate( 1, 2 - 1, 3 ), "Parse ancient date yy-mm-dd" ); currentYear = new Date().getFullYear(); testHelper.equalsDate( assert, $.datepicker.parseDate( "y-m-d", ( currentYear - 2000 ) + "-02-03" ), new Date( currentYear, 2 - 1, 3 ), "Parse date y-m-d - default cutuff" ); @@ -972,6 +974,9 @@ QUnit.test( "parseDate", function( assert ) { gmtDate.setMinutes( gmtDate.getMinutes() - gmtDate.getTimezoneOffset() ); testHelper.equalsDate( assert, $.datepicker.parseDate( "@", "981158400000" ), gmtDate, "Parse date @" ); testHelper.equalsDate( assert, $.datepicker.parseDate( "!", "631167552000000000" ), gmtDate, "Parse date !" ); + gmtDate = $.datepicker._newDate( 1, 2 - 1, 3 ); + testHelper.equalsDate( assert, $.datepicker.parseDate( "@", "-62132724000000" ), gmtDate, "Parse ancient date @" ); + testHelper.equalsDate( assert, $.datepicker.parseDate( "!", "28728000000000" ), gmtDate, "Parse ancient date !" ); fr = $.datepicker.regional.fr; settings = { dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames, diff --git a/ui/widgets/datepicker.js b/ui/widgets/datepicker.js index 44b513d1a82..3f6368c25ff 100644 --- a/ui/widgets/datepicker.js +++ b/ui/widgets/datepicker.js @@ -1151,6 +1151,7 @@ $.extend( Datepicker.prototype, { monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, year = -1, + isFullYear = false, month = -1, day = -1, doy = -1, @@ -1172,11 +1173,14 @@ $.extend( Datepicker.prototype, { size = ( match === "@" ? 14 : ( match === "!" ? 20 : ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), minSize = ( match === "y" ? size : 1 ), - digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ), + digits = new RegExp( "^" + (match === "@" ? "-?" : "") + "\\d{" + minSize + "," + size + "}" ), num = value.substring( iValue ).match( digits ); if ( !num ) { throw "Missing number at position " + iValue; } + if ( match === "y" ) { + isFullYear = isDoubled; + } iValue += num[ 0 ].length; return parseInt( num[ 0 ], 10 ); }, @@ -1243,12 +1247,14 @@ $.extend( Datepicker.prototype, { case "@": date = new Date( getNumber( "@" ) ); year = date.getFullYear(); + isFullYear = true; month = date.getMonth() + 1; day = date.getDate(); break; case "!": date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 ); year = date.getFullYear(); + isFullYear = true; month = date.getMonth() + 1; day = date.getDate(); break; @@ -1274,7 +1280,7 @@ $.extend( Datepicker.prototype, { if ( year === -1 ) { year = new Date().getFullYear(); - } else if ( year < 100 ) { + } else if ( year < 100 && !isFullYear ) { year += new Date().getFullYear() - new Date().getFullYear() % 100 + ( year <= shortYearCutoff ? 0 : -100 ); } @@ -1292,7 +1298,7 @@ $.extend( Datepicker.prototype, { } while ( true ); } - date = this._daylightSavingAdjust( new Date( year, month - 1, day ) ); + date = this._daylightSavingAdjust( this._newDate( year, month - 1, day ) ); if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { throw "Invalid date"; // E.g. 31/02/00 } From d0b8329eb04e1d983bf98276ed76e2a261e0e761 Mon Sep 17 00:00:00 2001 From: Matthew Wartman Date: Wed, 22 Jan 2020 11:54:50 -0600 Subject: [PATCH 3/4] Datepicker: Handle dates before year 100 Fixes #7098 --- tests/unit/datepicker/core.js | 6 +++++- tests/unit/datepicker/options.js | 23 ++++++++++++++++++--- ui/widgets/datepicker.js | 34 ++++++++++++++++---------------- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/tests/unit/datepicker/core.js b/tests/unit/datepicker/core.js index 2cc89cd21b9..0c0ca6fa654 100644 --- a/tests/unit/datepicker/core.js +++ b/tests/unit/datepicker/core.js @@ -457,7 +457,7 @@ QUnit.test( "keystrokes", function( assert ) { } ); QUnit.test( "mouse", function( assert ) { - assert.expect( 15 ); + assert.expect( 16 ); var inl, inp = testHelper.init( "#inp" ), dp = $( "#ui-datepicker-div" ), @@ -470,6 +470,10 @@ QUnit.test( "mouse", function( assert ) { $( ".ui-datepicker-calendar tbody a:contains(12)", dp ).simulate( "click", {} ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), new Date( 2008, 2 - 1, 12 ), "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( "" ).datepicker( "show" ); $( "button.ui-datepicker-close", dp ).simulate( "click", {} ); diff --git a/tests/unit/datepicker/options.js b/tests/unit/datepicker/options.js index 328a834d4a0..74062241ca7 100644 --- a/tests/unit/datepicker/options.js +++ b/tests/unit/datepicker/options.js @@ -267,7 +267,7 @@ QUnit.test( "otherMonths", function( assert ) { } ); QUnit.test( "defaultDate", function( assert ) { - assert.expect( 16 ); + assert.expect( 18 ); var inp = testHelper.init( "#inp" ), date = new Date(); inp.val( "" ).datepicker( "show" ). @@ -350,6 +350,11 @@ QUnit.test( "defaultDate", function( assert ) { simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); date = new Date( 2007, 7 - 1, 4 ); 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" } ). datepicker( "hide" ).val( "" ).datepicker( "show" ). simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); @@ -362,6 +367,11 @@ QUnit.test( "defaultDate", function( assert ) { datepicker( "hide" ).val( "" ).datepicker( "show" ). simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); 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 ) { @@ -537,14 +547,17 @@ QUnit.test( "minMax", function( assert ) { } ); QUnit.test( "setDate", function( assert ) { - assert.expect( 24 ); + assert.expect( 26 ); var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, inp = testHelper.init( "#inp" ), 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" ); inp.datepicker( "setDate", date1 ); 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.setDate( date1.getDate() + 7 ); inp.datepicker( "setDate", +7 ); @@ -568,6 +581,10 @@ QUnit.test( "setDate", function( assert ) { date1.setDate( date1.getDate() - 21 ); inp.datepicker( "setDate", "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 inl = testHelper.init( "#inl" ); diff --git a/ui/widgets/datepicker.js b/ui/widgets/datepicker.js index 3f6368c25ff..28160e9e615 100644 --- a/ui/widgets/datepicker.js +++ b/ui/widgets/datepicker.js @@ -1406,7 +1406,7 @@ $.extend( Datepicker.prototype, { break; case "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; case "m": output += formatNumber( "m", date.getMonth() + 1, 2 ); @@ -1563,7 +1563,7 @@ $.extend( Datepicker.prototype, { } 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 ) : ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); @@ -1615,7 +1615,7 @@ $.extend( Datepicker.prototype, { /* Retrieve the date(s) directly. */ _getDate: function( inst ) { var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : - this._daylightSavingAdjust( new Date( + this._daylightSavingAdjust( this._newDate( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); return startDate; }, @@ -1667,7 +1667,7 @@ $.extend( Datepicker.prototype, { printDate, dRow, tbody, daySettings, otherMonth, unselectable, tempDate = new Date(), 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" ), showButtonPanel = this._get( inst, "showButtonPanel" ), hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), @@ -1677,7 +1677,7 @@ $.extend( Datepicker.prototype, { stepMonths = this._get( inst, "stepMonths" ), isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), 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" ), maxDate = this._getMinMaxDate( inst, "max" ), drawMonth = inst.drawMonth - showCurrentAtPos, @@ -1688,10 +1688,10 @@ $.extend( Datepicker.prototype, { drawYear--; } 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() ) ); 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--; if ( drawMonth < 0 ) { drawMonth = 11; @@ -1704,7 +1704,7 @@ $.extend( Datepicker.prototype, { prevText = this._get( inst, "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 ) ) ); prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ? @@ -1714,7 +1714,7 @@ $.extend( Datepicker.prototype, { nextText = this._get( inst, "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 ) ) ); next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ? @@ -1752,7 +1752,7 @@ $.extend( Datepicker.prototype, { group = ""; this.maxRows = 4; 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"; calender = ""; if ( isMultiMonth ) { @@ -1790,7 +1790,7 @@ $.extend( Datepicker.prototype, { 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) 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 calender += ""; tbody = ( !showWeek ? "" : "" + @@ -1920,7 +1920,7 @@ $.extend( Datepicker.prototype, { var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), month = inst.selectedMonth + ( period === "M" ? 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.drawMonth = inst.selectedMonth = date.getMonth(); @@ -1960,18 +1960,18 @@ $.extend( Datepicker.prototype, { /* Find the number of days in a given 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. */ _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. */ _canAdjustMonth: function( inst, offset, curYear, curMonth ) { 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 ) ); if ( offset < 0 ) { @@ -2025,8 +2025,8 @@ $.extend( Datepicker.prototype, { inst.currentYear = inst.selectedYear; } var date = ( day ? ( typeof day === "object" ? day : - this._daylightSavingAdjust( new Date( year, month, day ) ) ) : - this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); + this._daylightSavingAdjust( this._newDate( year, month, day ) ) ) : + this._daylightSavingAdjust( this._newDate( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); }, From 10972be7adec8f25e8ad7a0bceee7f9f5e9d4723 Mon Sep 17 00:00:00 2001 From: Matthew Wartman Date: Wed, 22 Jan 2020 16:08:52 -0600 Subject: [PATCH 4/4] Datepicker: Show four-digit years in title --- tests/unit/datepicker/core.js | 13 +++++++++---- tests/unit/datepicker/options.js | 6 +++--- ui/widgets/datepicker.js | 15 +++++++++++---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/tests/unit/datepicker/core.js b/tests/unit/datepicker/core.js index 0c0ca6fa654..c5106718f32 100644 --- a/tests/unit/datepicker/core.js +++ b/tests/unit/datepicker/core.js @@ -39,9 +39,11 @@ QUnit.test( "widget method", function( assert ) { QUnit.test( "baseStructure", function( assert ) { var ready = assert.async(); - assert.expect( 58 ); + assert.expect( 60 ); var header, title, table, thead, week, panel, inl, child, - inp = testHelper.initNewInput(), + inp = testHelper.initNewInput( { + defaultDate: $.datepicker._newDate( 1, 2 - 1, 3 ) + } ), dp = $( "#ui-datepicker-div" ); function step1() { @@ -61,7 +63,7 @@ QUnit.test( "baseStructure", function( assert ) { assert.ok( title.is( "div.ui-datepicker-title" ) && title.html() !== "", "Structure - title division" ); assert.equal( title.children().length, 2, "Structure - title child count" ); assert.ok( title.children().first().is( "span.ui-datepicker-month" ) && title.children().first().text() !== "", "Structure - month text" ); - assert.ok( title.children().last().is( "span.ui-datepicker-year" ) && title.children().last().text() !== "", "Structure - year text" ); + assert.ok( title.children().last().is( "span.ui-datepicker-year" ) && title.children().last().text() === "0001", "Structure - year text" ); table = dp.children().eq( 1 ); assert.ok( table.is( "table.ui-datepicker-calendar" ), "Structure - month table" ); @@ -90,12 +92,15 @@ QUnit.test( "baseStructure", function( assert ) { inp = testHelper.initNewInput( { changeMonth: true, changeYear: true, - showButtonPanel: true + showButtonPanel: true, + defaultDate: $.datepicker._newDate( 1, 2 - 1, 3 ) } ); testHelper.onFocus( inp, function() { title = dp.find( "div.ui-datepicker-title" ); assert.ok( title.children().first().is( "select.ui-datepicker-month" ), "Structure - month selector" ); assert.ok( title.children().last().is( "select.ui-datepicker-year" ), "Structure - year selector" ); + assert.equal( title.children().last().children().first().text(), "-9" ); + assert.equal( title.children().last().children().last().text(), "0011" ); panel = dp.children().last(); assert.ok( panel.is( "div.ui-datepicker-buttonpane" ), "Structure - button panel division" ); diff --git a/tests/unit/datepicker/options.js b/tests/unit/datepicker/options.js index 74062241ca7..60f22cf37c3 100644 --- a/tests/unit/datepicker/options.js +++ b/tests/unit/datepicker/options.js @@ -581,9 +581,9 @@ QUnit.test( "setDate", function( assert ) { date1.setDate( date1.getDate() - 21 ); inp.datepicker( "setDate", "c -3 w" ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date1, "Set date - c -3 w" ); - date3 = new Date(date1); + date3 = new Date( date1 ); date3.setFullYear( 1 ); - inp.datepicker( "setDate", "c " + (1 - date1.getFullYear()) + " y" ); + inp.datepicker( "setDate", "c " + ( 1 - date1.getFullYear() ) + " y" ); testHelper.equalsDate( assert, inp.datepicker( "getDate" ), date3, "Set date - 0001 relatively" ); // Inline @@ -1113,7 +1113,7 @@ QUnit.test( "formatDate", function( assert ) { new Date( 2001, 2 - 1, 3 ) ), "day 3 of February ('Saturday'), 2001", "Format date 'day' d 'of' MM ('DD'), yy" ); assert.equal( $.datepicker.formatDate( "yy-mm-dd", $.datepicker._newDate( 999, 2 - 1, 3 ) ), - "0999-02-03", "Format ancient date yy-mm-dd"); + "0999-02-03", "Format ancient date yy-mm-dd" ); gmtDate = new Date( 2001, 2 - 1, 3 ); gmtDate.setMinutes( gmtDate.getMinutes() - gmtDate.getTimezoneOffset() ); assert.equal( $.datepicker.formatDate( "@", gmtDate ), "981158400000", "Format date @" ); diff --git a/ui/widgets/datepicker.js b/ui/widgets/datepicker.js index 28160e9e615..1e20f521171 100644 --- a/ui/widgets/datepicker.js +++ b/ui/widgets/datepicker.js @@ -1173,7 +1173,7 @@ $.extend( Datepicker.prototype, { size = ( match === "@" ? 14 : ( match === "!" ? 20 : ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), minSize = ( match === "y" ? size : 1 ), - digits = new RegExp( "^" + (match === "@" ? "-?" : "") + "\\d{" + minSize + "," + size + "}" ), + digits = new RegExp( "^" + ( match === "@" ? "-?" : "" ) + "\\d{" + minSize + "," + size + "}" ), num = value.substring( iValue ).match( digits ); if ( !num ) { throw "Missing number at position " + iValue; @@ -1415,7 +1415,7 @@ $.extend( Datepicker.prototype, { output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); break; case "y": - output += ( "0000" + date.getFullYear() ).slice( lookAhead( "y" ) ? -4 : -2 ); + output += lookAhead( "y" ) ? this._formatYear( date.getFullYear() ) : ( "00" + date.getFullYear() ).slice( -2 ); break; case "@": output += date.getTime(); @@ -1878,7 +1878,7 @@ $.extend( Datepicker.prototype, { if ( !inst.yearshtml ) { inst.yearshtml = ""; if ( secondary || !changeYear ) { - html += "" + drawYear + ""; + html += "" + this._formatYear( drawYear ) + ""; } else { // determine range of years to display @@ -1898,7 +1898,7 @@ $.extend( Datepicker.prototype, { for ( ; year <= endYear; year++ ) { inst.yearshtml += ""; + ">" + this._formatYear( year ) + ""; } inst.yearshtml += ""; @@ -2040,6 +2040,13 @@ $.extend( Datepicker.prototype, { date.setFullYear( date.getFullYear() - 1900 ); } return date; + }, + + /* Add leading zeros to produce an at-least-four-digit year. */ + _formatYear: function( year ) { + var yearString = "" + year; + return year < 0 ? yearString : + yearString.length < 4 ? ( "0000" + yearString ).slice( -4 ) : yearString; } } ); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy