diff --git a/src/datetime.js b/src/datetime.js index 09a389e7..92972dbe 100644 --- a/src/datetime.js +++ b/src/datetime.js @@ -387,8 +387,8 @@ function normalizeUnitWithLocalWeeks(unit) { // single timestamp for all zones to make things a bit more predictable. // // This is safe for quickDT (used by local() and utc()) because we don't fill in -// higher-order units from tsNow (as we do in fromObject, this requires that -// offset is calculated from tsNow). +// higher-order units from tsRef (as we do in fromObject, this requires that +// offset is calculated from tsRef). function guessOffsetForZone(zone) { if (!zoneOffsetGuessCache[zone]) { if (zoneOffsetTs === undefined) { @@ -745,8 +745,10 @@ export default class DateTime { * @param {string} [opts.locale='system\'s locale'] - a locale to set on the resulting DateTime instance * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @param {DateTime|Date|Object} opts.referenceDate - the reference date to take for missing parts * @example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25' * @example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01' + * @example DateTime.fromObject({ year: 1982 }, { referenceDate: { day: 10 } }).toISODate() //=> '1982-01-10' * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06 * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }), * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' }) @@ -766,10 +768,12 @@ export default class DateTime { const normalized = normalizeObject(obj, normalizeUnitWithLocalWeeks); const { minDaysInFirstWeek, startOfWeek } = usesLocalWeekValues(normalized, loc); - const tsNow = Settings.now(), + const tsRef = isUndefined(opts.referenceDate) + ? Settings.now() + : friendlyDateTime(opts.referenceDate).toUnixInteger(), offsetProvis = !isUndefined(opts.specificOffset) ? opts.specificOffset - : zoneToUse.offset(tsNow), + : zoneToUse.offset(tsRef), containsOrdinal = !isUndefined(normalized.ordinal), containsGregorYear = !isUndefined(normalized.year), containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), @@ -797,7 +801,7 @@ export default class DateTime { // configure ourselves to deal with gregorian dates or week stuff let units, defaultValues, - objNow = tsToObj(tsNow, offsetProvis); + objNow = tsToObj(tsRef, offsetProvis); if (useWeekData) { units = orderedWeekUnits; defaultValues = defaultWeekUnitValues; @@ -874,6 +878,7 @@ export default class DateTime { * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance * @param {string} [opts.outputCalendar] - the output calendar to set on the resulting DateTime instance * @param {string} [opts.numberingSystem] - the numbering system to set on the resulting DateTime instance + * @param {DateTime|Date|Object} opts.referenceDate - the reference date to take for missing parts * @example DateTime.fromISO('2016-05-25T09:08:34.123') * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00') * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00', {setZone: true}) @@ -895,6 +900,7 @@ export default class DateTime { * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @param {DateTime|Date|Object} opts.referenceDate - the reference date to take for missing parts * @example DateTime.fromRFC2822('25 Nov 2016 13:23:12 GMT') * @example DateTime.fromRFC2822('Fri, 25 Nov 2016 13:23:12 +0600') * @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z') @@ -915,6 +921,7 @@ export default class DateTime { * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance + * @param {DateTime|Date|Object} opts.referenceDate - the reference date to take for missing parts * @example DateTime.fromHTTP('Sun, 06 Nov 1994 08:49:37 GMT') * @example DateTime.fromHTTP('Sunday, 06-Nov-94 08:49:37 GMT') * @example DateTime.fromHTTP('Sun Nov 6 08:49:37 1994') @@ -936,6 +943,7 @@ export default class DateTime { * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {DateTime|Date|Object} opts.referenceDate - the reference date to take for missing parts * @return {DateTime} */ static fromFormat(text, fmt, opts = {}) { @@ -974,6 +982,7 @@ export default class DateTime { * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance + * @param {DateTime|Date|Object} opts.referenceDate - the reference date to take for missing parts * @example DateTime.fromSQL('2017-05-15') * @example DateTime.fromSQL('2017-05-15 09:12:34') * @example DateTime.fromSQL('2017-05-15 09:12:34.342') diff --git a/test/datetime/create.test.js b/test/datetime/create.test.js index 67613a61..ffe72ed9 100644 --- a/test/datetime/create.test.js +++ b/test/datetime/create.test.js @@ -883,6 +883,12 @@ test("DateTime.fromObject takes a undefined to mean {}", () => { expect(res.year).toBe(new Date().getFullYear()); }); +test("DateTime.fromObject respects `referenceDate`", () => { + const res = DateTime.fromObject(undefined, { referenceDate: { day: 10 } }); + expect(res.year).toBe(new Date().getFullYear()); + expect(res.day).toBe(10); +}); + test("private language subtags don't break unicode subtags", () => { const res = DateTime.fromObject( {},