diff options
author | janekptacijarabaci <janekptacijarabaci@seznam.cz> | 2018-03-30 23:50:34 +0200 |
---|---|---|
committer | janekptacijarabaci <janekptacijarabaci@seznam.cz> | 2018-03-30 23:50:34 +0200 |
commit | e14c686ac0ad5e6cfdd933049c11b80a425283dc (patch) | |
tree | 2898de2582c3ea07ac781fafbf079fed790ef888 /toolkit/content/widgets/datekeeper.js | |
parent | 77fbaff2faf6fc341e30a309f7e68458f2864ad9 (diff) | |
download | UXP-e14c686ac0ad5e6cfdd933049c11b80a425283dc.tar UXP-e14c686ac0ad5e6cfdd933049c11b80a425283dc.tar.gz UXP-e14c686ac0ad5e6cfdd933049c11b80a425283dc.tar.lz UXP-e14c686ac0ad5e6cfdd933049c11b80a425283dc.tar.xz UXP-e14c686ac0ad5e6cfdd933049c11b80a425283dc.zip |
Bug 1381421 - (Part 1) Handle dates earlier than 0001-01-01 and later than 275760-09-13 correctly
Diffstat (limited to 'toolkit/content/widgets/datekeeper.js')
-rw-r--r-- | toolkit/content/widgets/datekeeper.js | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/toolkit/content/widgets/datekeeper.js b/toolkit/content/widgets/datekeeper.js index 4959b9609..5d70416a9 100644 --- a/toolkit/content/widgets/datekeeper.js +++ b/toolkit/content/widgets/datekeeper.js @@ -19,9 +19,11 @@ function DateKeeper(props) { // The min value is 0001-01-01 based on HTML spec: // https://html.spec.whatwg.org/#valid-date-string MIN_DATE = -62135596800000, - // The max value is derived from the ECMAScript spec: + // The max value is derived from the ECMAScript spec (275760-09-13): // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 - MAX_DATE = 8640000000000000; + MAX_DATE = 8640000000000000, + MAX_YEAR = 275760, + MAX_MONTH = 9; DateKeeper.prototype = { get year() { @@ -32,10 +34,6 @@ function DateKeeper(props) { return this.state.dateObj.getUTCMonth(); }, - get day() { - return this.state.dateObj.getUTCDate(); - }, - get selection() { return this.state.selection; }, @@ -55,7 +53,6 @@ function DateKeeper(props) { */ init({ year, month, day, min, max, step, stepBase, firstDayOfWeek = 0, weekends = [0], calViewSize = 42 }) { const today = new Date(); - const isDateSet = year != undefined && month != undefined && day != undefined; this.state = { step, firstDayOfWeek, weekends, calViewSize, @@ -66,28 +63,34 @@ function DateKeeper(props) { today: this._newUTCDate(today.getFullYear(), today.getMonth(), today.getDate()), weekHeaders: this._getWeekHeaders(firstDayOfWeek, weekends), years: [], - months: [], - days: [], + dateObj: new Date(0), selection: { year, month, day }, }; - this.state.dateObj = isDateSet ? - this._newUTCDate(year, month, day) : - new Date(this.state.today); + this.setCalendarMonth({ + year: year === undefined ? today.getFullYear() : year, + month: month === undefined ? today.getMonth() : month + }); }, /** - * Set new date. The year is always treated as full year, so the short-form - * is not supported. + * Set new calendar month. The year is always treated as full year, so the + * short-form is not supported. * @param {Object} date parts * { * {Number} year [optional] * {Number} month [optional] - * {Number} date [optional] * } */ - set({ year = this.year, month = this.month, day = this.day }) { + setCalendarMonth({ year = this.year, month = this.month }) { + // Make sure the date is valid before setting. // Use setUTCFullYear so that year 99 doesn't get parsed as 1999 - this.state.dateObj.setUTCFullYear(year, month, day); + if (year > MAX_YEAR || year === MAX_YEAR && month >= MAX_MONTH) { + this.state.dateObj.setUTCFullYear(MAX_YEAR, MAX_MONTH - 1, 1); + } else if (year < 1 || year === 1 && month < 0) { + this.state.dateObj.setUTCFullYear(1, 0, 1); + } else { + this.state.dateObj.setUTCFullYear(year, month, 1); + } }, /** @@ -107,10 +110,7 @@ function DateKeeper(props) { * @param {Number} month */ setMonth(month) { - const lastDayOfMonth = this._newUTCDate(this.year, month + 1, 0).getUTCDate(); - this.set({ year: this.year, - month, - day: Math.min(this.day, lastDayOfMonth) }); + this.setCalendarMonth({ year: this.year, month }); }, /** @@ -118,10 +118,7 @@ function DateKeeper(props) { * @param {Number} year */ setYear(year) { - const lastDayOfMonth = this._newUTCDate(year, this.month + 1, 0).getUTCDate(); - this.set({ year, - month: this.month, - day: Math.min(this.day, lastDayOfMonth) }); + this.setCalendarMonth({ year, month: this.month }); }, /** @@ -129,10 +126,7 @@ function DateKeeper(props) { * @param {Number} offset */ setMonthByOffset(offset) { - const lastDayOfMonth = this._newUTCDate(this.year, this.month + offset + 1, 0).getUTCDate(); - this.set({ year: this.year, - month: this.month + offset, - day: Math.min(this.day, lastDayOfMonth) }); + this.setCalendarMonth({ year: this.year, month: this.month + offset }); }, /** @@ -178,10 +172,13 @@ function DateKeeper(props) { currentYear >= lastItem.value - YEAR_BUFFER_SIZE) { // The year is set in the middle with items on both directions for (let i = -(YEAR_VIEW_SIZE / 2); i < YEAR_VIEW_SIZE / 2; i++) { - years.push({ - value: currentYear + i, - enabled: true - }); + const year = currentYear + i; + if (year >= 1 && year <= MAX_YEAR) { + years.push({ + value: year, + enabled: true + }); + } } this.state.years = years; } @@ -193,6 +190,7 @@ function DateKeeper(props) { * @return {Array<Object>} * { * {Date} dateObj + * {Number} content * {Array<String>} classNames * {Boolean} enabled * } @@ -206,9 +204,22 @@ function DateKeeper(props) { const dateObj = this._newUTCDate(firstDayOfMonth.getUTCFullYear(), firstDayOfMonth.getUTCMonth(), firstDayOfMonth.getUTCDate() + i); + let classNames = []; let enabled = true; + const isValid = dateObj.getTime() >= MIN_DATE && dateObj.getTime() <= MAX_DATE; + if (!isValid) { + classNames.push("out-of-range"); + enabled = false; + + days.push({ + classNames, + enabled, + }); + continue; + } + const isWeekend = this.state.weekends.includes(dateObj.getUTCDay()); const isCurrentMonth = month == dateObj.getUTCMonth(); const isSelection = this.state.selection.year == dateObj.getUTCFullYear() && @@ -244,6 +255,7 @@ function DateKeeper(props) { } days.push({ dateObj, + content: dateObj.getUTCDate(), classNames, enabled, }); @@ -275,7 +287,7 @@ function DateKeeper(props) { * @param {Array<Number>} weekends * @return {Array<Object>} * { - * {Number} textContent + * {Number} content * {Array<String>} classNames * } */ @@ -285,7 +297,7 @@ function DateKeeper(props) { for (let i = 0; i < DAYS_IN_A_WEEK; i++) { headers.push({ - textContent: dayOfWeek % DAYS_IN_A_WEEK, + content: dayOfWeek % DAYS_IN_A_WEEK, classNames: weekends.includes(dayOfWeek % DAYS_IN_A_WEEK) ? ["weekend"] : [] }); dayOfWeek++; @@ -318,7 +330,7 @@ function DateKeeper(props) { * @return {Date} */ _newUTCDate(...parts) { - return new Date(Date.UTC(...parts)); - } + return new Date(new Date(0).setUTCFullYear(...parts)); + }, }; } |