diff --git a/tests/unit/datepicker/core.js b/tests/unit/datepicker/core.js index 2cc89cd21b9..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" ); @@ -457,7 +462,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 +475,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/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 7711e741233..60f22cf37c3 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" ); @@ -926,7 +943,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 +970,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 +991,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, @@ -1066,7 +1088,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 +1112,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..1e20f521171 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 } @@ -1400,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 ); @@ -1409,8 +1415,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 += lookAhead( "y" ) ? this._formatYear( date.getFullYear() ) : ( "00" + date.getFullYear() ).slice( -2 ); break; case "@": output += date.getTime(); @@ -1558,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() ) ) ) ); @@ -1610,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; }, @@ -1662,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" ), @@ -1672,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, @@ -1683,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; @@ -1699,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 ) ? @@ -1709,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 ) ? @@ -1747,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 ) { @@ -1785,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 ? "" : "" + @@ -1873,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 @@ -1893,7 +1898,7 @@ $.extend( Datepicker.prototype, { for ( ; year <= endYear; year++ ) { inst.yearshtml += ""; + ">" + this._formatYear( year ) + ""; } inst.yearshtml += ""; @@ -1915,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(); @@ -1955,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 ) { @@ -2020,9 +2025,28 @@ $.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 ) ); + }, + + /* 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; + }, + + /* 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