Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions tests/unit/datepicker/core.js
Original file line number Diff line number Diff line change
@@ -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", {} );
4 changes: 2 additions & 2 deletions tests/unit/datepicker/helper.js
Original file line number Diff line number Diff line change
@@ -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 );
},

34 changes: 29 additions & 5 deletions tests/unit/datepicker/options.js
Original file line number Diff line number Diff line change
@@ -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 @" );
72 changes: 48 additions & 24 deletions ui/widgets/datepicker.js
Original file line number Diff line number Diff line change
@@ -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 += "<tr>";
tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
@@ -1873,7 +1878,7 @@ $.extend( Datepicker.prototype, {
if ( !inst.yearshtml ) {
inst.yearshtml = "";
if ( secondary || !changeYear ) {
html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
html += "<span class='ui-datepicker-year'>" + this._formatYear( drawYear ) + "</span>";
} else {

// determine range of years to display
@@ -1893,7 +1898,7 @@ $.extend( Datepicker.prototype, {
for ( ; year <= endYear; year++ ) {
inst.yearshtml += "<option value='" + year + "'" +
( year === drawYear ? " selected='selected'" : "" ) +
">" + year + "</option>";
">" + this._formatYear( year ) + "</option>";
}
inst.yearshtml += "</select>";

@@ -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;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm honestly not sure how negative dates should be formatted.

}
} );