diff --git a/docs/absolute.md b/docs/absolute.md index 9a50dc3239..7efd0a2ff3 100644 --- a/docs/absolute.md +++ b/docs/absolute.md @@ -296,7 +296,7 @@ Temporal.now.absolute().minus(oneDay); **Returns:** a `Temporal.Duration` representing the difference between `absolute` and `other`. This method computes the difference between the two times represented by `absolute` and `other`, and returns it as a `Temporal.Duration` object. -The difference is always positive, no matter the order of `absolute` and `other`, because `Temporal.Duration` objects cannot represent negative durations. +A `RangeError` will be thrown if `other` is later than `absolute`, because `Temporal.Duration` objects cannot represent negative durations. The `largestUnit` option controls how the resulting duration is expressed. The returned `Temporal.Duration` object will not have any nonzero fields that are larger than the unit in `largestUnit`. @@ -312,25 +312,25 @@ Example usage: ```js startOfMoonMission = Temporal.Absolute.from('1969-07-16T13:32:00Z'); endOfMoonMission = Temporal.Absolute.from('1969-07-24T16:50:35Z'); -missionLength = startOfMoonMission.difference(endOfMoonMission, { largestUnit: 'days' }); - // => P8DT3H18M35S -endOfMoonMission.difference(startOfMoonMission, { largestUnit: 'days' }); +missionLength = endOfMoonMission.difference(startOfMoonMission, { largestUnit: 'days' }); // => P8DT3H18M35S +startOfMoonMission.difference(endOfMoonMission, { largestUnit: 'days' }); + // => throws RangeError missionLength.toLocaleString(); // example output: '8 days 3 hours 18 minutes 35 seconds' // A billion (10^9) seconds since the epoch in different units epoch = new Temporal.Absolute(0n); billion = Temporal.Absolute.fromEpochSeconds(1e9); -epoch.difference(billion); // => PT1000000000S -epoch.difference(billion, { largestUnit: 'hours' }) // => PT277777H46M40S -epoch.difference(billion, { largestUnit: 'days' }) // => P11574DT1H46M40S +billion.difference(epoch); // => PT1000000000S +billion.difference(epoch, { largestUnit: 'hours' }) // => PT277777H46M40S +billion.difference(epoch, { largestUnit: 'days' }) // => P11574DT1H46M40S // If you really need to calculate the difference between two Absolutes // in years, you can eliminate the ambiguity by choosing your starting // point explicitly. For example, using the corresponding UTC date: utc = Temporal.TimeZone.from('UTC'); -epoch.inTimeZone(utc).difference(billion.inTimeZone(utc), { largestUnit: 'years' }); +billion.inTimeZone(utc).difference(epoch.inTimeZone(utc), { largestUnit: 'years' }); // => P31Y8M8DT1H46M40S ``` diff --git a/docs/calendar.md b/docs/calendar.md index 2630fd7b4c..e175327591 100644 --- a/docs/calendar.md +++ b/docs/calendar.md @@ -257,12 +257,12 @@ For example: ```javascript d1 = Temporal.Date.from('2020-07-29').withCalendar('chinese'); d2 = Temporal.Date.from('2020-08-29').withCalendar('chinese'); -d1.difference(d2, { largestUnit: 'months' }) // => P1M2D +d2.difference(d1, { largestUnit: 'months' }) // => P1M2D // same result, but calling the method directly: Temporal.Calendar.from('chinese').difference( - Temporal.Date.from('2020-07-29'), Temporal.Date.from('2020-08-29'), + Temporal.Date.from('2020-07-29'), { largestUnit: 'months' } ) // => P1M2D ``` diff --git a/docs/cookbook/futureDateForm.js b/docs/cookbook/futureDateForm.js index 343040ecd9..3c3a172d3a 100644 --- a/docs/cookbook/futureDateForm.js +++ b/docs/cookbook/futureDateForm.js @@ -14,8 +14,8 @@ function englishPlural(n, singular, plural) { if (futuredateParam !== null) { const futureDate = Temporal.Date.from(futuredateParam); const today = Temporal.now.date(); - const until = today.difference(futureDate, { largestUnit: 'days' }); - const untilMonths = today.difference(futureDate, { largestUnit: 'months' }); + const until = futureDate.difference(today, { largestUnit: 'days' }); + const untilMonths = futureDate.difference(today, { largestUnit: 'months' }); const dayString = englishPlural(until.days, 'day', 'days'); const monthString = diff --git a/docs/cookbook/getElapsedDurationSinceInstant.mjs b/docs/cookbook/getElapsedDurationSinceInstant.mjs index 3aec81c880..1db6b60164 100644 --- a/docs/cookbook/getElapsedDurationSinceInstant.mjs +++ b/docs/cookbook/getElapsedDurationSinceInstant.mjs @@ -14,7 +14,7 @@ */ function getElapsedDurationSinceInstant(then, now, largestUnit = 'days') { const sign = Temporal.Absolute.compare(now, then) < 0 ? '-' : '+'; - const duration = now.difference(then, { largestUnit }); + const duration = sign === '-' ? then.difference(now, { largestUnit }) : now.difference(then, { largestUnit }); return { sign, duration }; } diff --git a/docs/cookbook/getTripDurationInHrMinSec.mjs b/docs/cookbook/getTripDurationInHrMinSec.mjs index 03d802549e..792e32ca67 100644 --- a/docs/cookbook/getTripDurationInHrMinSec.mjs +++ b/docs/cookbook/getTripDurationInHrMinSec.mjs @@ -9,7 +9,7 @@ function getTripDurationInHrMinSec(parseableDeparture, parseableArrival) { const departure = Temporal.Absolute.from(parseableDeparture); const arrival = Temporal.Absolute.from(parseableArrival); - return departure.difference(arrival, { largestUnit: 'hours' }); + return arrival.difference(departure, { largestUnit: 'hours' }); } const flightTime = getTripDurationInHrMinSec( diff --git a/docs/date.md b/docs/date.md index 7ed7b56e16..bd02c82b18 100644 --- a/docs/date.md +++ b/docs/date.md @@ -338,7 +338,7 @@ date.minus({ months: 1 }, { disambiguation: 'reject' }) // => throws **Returns:** a `Temporal.Duration` representing the difference between `date` and `other`. This method computes the difference between the two dates represented by `date` and `other`, and returns it as a `Temporal.Duration` object. -The difference is always positive, no matter the order of `date` and `other`, because `Temporal.Duration` objects cannot represent negative durations. +A `RangeError` will be thrown if `other` is later than `date`, because `Temporal.Duration` objects cannot represent negative durations. The `largestUnit` option controls how the resulting duration is expressed. The returned `Temporal.Duration` object will not have any nonzero fields that are larger than the unit in `largestUnit`. @@ -351,10 +351,11 @@ Unlike other Temporal types, hours and lower are not allowed, because the data m Usage example: ```javascript -date = Temporal.Date.from('2006-08-24'); -other = Temporal.Date.from('2019-01-31'); +date = Temporal.Date.from('2019-01-31'); +other = Temporal.Date.from('2006-08-24'); date.difference(other) // => P4543D date.difference(other, { largestUnit: 'years' }) // => P12Y5M7D +other.difference(date, { largestUnit: 'years' }) // => throws RangeError // If you really need to calculate the difference between two Dates in // hours, you can eliminate the ambiguity by explicitly choosing the diff --git a/docs/datetime.md b/docs/datetime.md index 7a38eaf374..aff9d7eca3 100644 --- a/docs/datetime.md +++ b/docs/datetime.md @@ -394,7 +394,7 @@ dt.minus({ months: 1 }) // => throws **Returns:** a `Temporal.Duration` representing the difference between `datetime` and `other`. This method computes the difference between the two times represented by `datetime` and `other`, and returns it as a `Temporal.Duration` object. -The difference is always positive, no matter the order of `datetime` and `other`, because `Temporal.Duration` objects cannot represent negative durations. +A `RangeError` will be thrown if `other` is later than `datetime`, because `Temporal.Duration` objects cannot represent negative durations. The `largestUnit` option controls how the resulting duration is expressed. The returned `Temporal.Duration` object will not have any nonzero fields that are larger than the unit in `largestUnit`. @@ -408,15 +408,16 @@ Usage example: ```javascript dt1 = Temporal.DateTime.from('1995-12-07T03:24:30.000003500'); dt2 = Temporal.DateTime.from('2019-01-31T15:30'); -dt1.difference(dt2); // => P8456DT12H5M29.999996500S -dt1.difference(dt2), { largestUnit: 'years' }) // => P23Y1M24DT12H5M29.999996500S +dt2.difference(dt1); // => P8456DT12H5M29.999996500S +dt2.difference(dt1), { largestUnit: 'years' }) // => P23Y1M24DT12H5M29.999996500S +dt1.difference(dt2), { largestUnit: 'years' }) // => throws RangeError // Months and years can be different lengths [jan1, feb1, mar1] = [1, 2, 3].map(month => Temporal.DateTime.from({year: 2020, month, day: 1})); -jan1.difference(feb1); // => P31D -jan1.difference(feb1, { largestUnit: 'months' }); // => P1M -feb1.difference(mar1); // => P29D -feb1.difference(mar1, { largestUnit: 'months' }); // => P1M +feb1.difference(jan1); // => P31D +feb1.difference(jan1, { largestUnit: 'months' }); // => P1M +mar1.difference(feb1); // => P29D +mar1.difference(feb1, { largestUnit: 'months' }); // => P1M ``` ### datetime.**equals**(_other_: Temporal.DateTime) : boolean diff --git a/docs/time.md b/docs/time.md index c42c512487..16aacadec7 100644 --- a/docs/time.md +++ b/docs/time.md @@ -245,23 +245,21 @@ time.minus({ minutes: 5, nanoseconds: 800 }) // => 19:34:09.068345405 **Returns:** a `Temporal.Duration` representing the difference between `time` and `other`. This method computes the difference between the two times represented by `time` and `other`, and returns it as a `Temporal.Duration` object. -The difference is always positive, and always 12 hours or less, no matter the order of `time` and `other`, because `Temporal.Duration` objects cannot represent negative durations. +A `RangeError` will be thrown if `other` is later than `time`, because `Temporal.Duration` objects cannot represent negative durations. The `largestUnit` parameter controls how the resulting duration is expressed. The returned `Temporal.Duration` object will not have any nonzero fields that are larger than the unit in `largestUnit`. -A difference of two hours will become 7200 seconds when `largestUnit` is `"seconds"`, for example. -However, a difference of 30 seconds will still be 30 seconds even if `largestUnit` is `"hours"`. +A difference of two hours will become 7200 seconds when `largestUnit` is `'seconds'`, for example. +However, a difference of 30 seconds will still be 30 seconds even if `largestUnit` is `'hours'`. -The default largest unit in the result is technically days, for consistency with other Temporal types' `difference` methods. -However, since this method never returns any duration longer than 12 hours, largest units of years, months, or days, are by definition treated as hours. +The default largest unit in the result is technically `'days'`, for consistency with other Temporal types' `difference` methods. +However, since time differences are always shorter than one day, largest units of `'years'`, `'months'`, or `'days'` are treated as `'hours'`. Usage example: ```javascript -time = Temporal.Time.from('19:39:09.068346205'); -time.difference(Temporal.Time.from('20:13:20.971398099')) // => PT34M11.903051894S - -// The difference is always less than 12 hours, crossing midnight if needed -Temporal.Time.from('01:00').difference(Temporal.Time.from('23:00')) // => P2H +time = Temporal.Time.from('20:13:20.971398099'); +time.difference(Temporal.Time.from('19:39:09.068346205')) // => PT34M11.903051894S +time.difference(Temporal.Time.from('22:39:09.068346205')) // => throws RangeError ``` ### time.**equals**(_other_: Temporal.Time) : boolean diff --git a/docs/yearmonth.md b/docs/yearmonth.md index fef98ba9a5..f02127cd0f 100644 --- a/docs/yearmonth.md +++ b/docs/yearmonth.md @@ -284,7 +284,7 @@ ym.minus({years: 20, months: 4}) // => 1999-02 **Returns:** a `Temporal.Duration` representing the difference between `yearMonth` and `other`. This method computes the difference between the two months represented by `yearMonth` and `other`, and returns it as a `Temporal.Duration` object. -The difference is always positive, no matter the order of `yearMonth` and `other`, because `Temporal.Duration` objects cannot represent negative durations. +A `RangeError` will be thrown if `other` is later than `yearMonth`, because `Temporal.Duration` objects cannot represent negative durations. The `largestUnit` option controls how the resulting duration is expressed. The returned `Temporal.Duration` object will not have any nonzero fields that are larger than the unit in `largestUnit`. @@ -299,6 +299,7 @@ ym = Temporal.YearMonth.from('2019-06'); other = Temporal.YearMonth.from('2006-08'); ym.difference(other) // => P12Y10M ym.difference(other, { largestUnit: 'months' }) // => P154M +other.difference(ym, { largestUnit: 'months' }) // => throws RangeError // If you really need to calculate the difference between two YearMonths // in days, you can eliminate the ambiguity by explicitly choosing the diff --git a/polyfill/lib/absolute.mjs b/polyfill/lib/absolute.mjs index 63c8a75161..29cb87985e 100644 --- a/polyfill/lib/absolute.mjs +++ b/polyfill/lib/absolute.mjs @@ -95,9 +95,10 @@ export class Absolute { if (!ES.IsTemporalAbsolute(other)) throw new TypeError('invalid Absolute object'); const largestUnit = ES.ToLargestTemporalUnit(options, 'seconds', ['years', 'months', 'weeks']); - const [one, two] = [this, other].sort(Absolute.compare); - const onens = GetSlot(one, EPOCHNANOSECONDS); - const twons = GetSlot(two, EPOCHNANOSECONDS); + const comparison = Absolute.compare(this, other); + if (comparison < 0) throw new RangeError('other instance cannot be larger than `this`'); + const onens = GetSlot(other, EPOCHNANOSECONDS); + const twons = GetSlot(this, EPOCHNANOSECONDS); const diff = twons.minus(onens); const ns = +diff.mod(1e3); diff --git a/polyfill/lib/date.mjs b/polyfill/lib/date.mjs index 3d4aeba612..b0a36c3319 100644 --- a/polyfill/lib/date.mjs +++ b/polyfill/lib/date.mjs @@ -126,8 +126,9 @@ export class Date { if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver'); if (!ES.IsTemporalDate(other)) throw new TypeError('invalid Date object'); const largestUnit = ES.ToLargestTemporalUnit(options, 'days', ['hours', 'minutes', 'seconds']); - const [smaller, larger] = [this, other].sort(Date.compare); - const { years, months, weeks, days } = ES.DifferenceDate(smaller, larger, largestUnit); + const comparison = Date.compare(this, other); + if (comparison < 0) throw new RangeError('other instance cannot be larger than `this`'); + const { years, months, weeks, days } = ES.DifferenceDate(other, this, largestUnit); const Duration = GetIntrinsic('%Temporal.Duration%'); return new Duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0); } diff --git a/polyfill/lib/datetime.mjs b/polyfill/lib/datetime.mjs index 15992b89fa..fedc206fde 100644 --- a/polyfill/lib/datetime.mjs +++ b/polyfill/lib/datetime.mjs @@ -239,12 +239,13 @@ export class DateTime { if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver'); if (!ES.IsTemporalDateTime(other)) throw new TypeError('invalid DateTime object'); const largestUnit = ES.ToLargestTemporalUnit(options, 'days'); - const [smaller, larger] = [this, other].sort(DateTime.compare); + const comparison = DateTime.compare(this, other); + if (comparison < 0) throw new RangeError('other instance cannot be larger than `this`'); let { deltaDays, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.DifferenceTime( - smaller, - larger + other, + this ); - let { year, month, day } = larger; + let { year, month, day } = this; day += deltaDays; ({ year, month, day } = ES.BalanceDate(year, month, day)); @@ -253,7 +254,7 @@ export class DateTime { dateLargestUnit = largestUnit; } - let { years, months, weeks, days } = ES.DifferenceDate(smaller, { year, month, day }, dateLargestUnit); + let { years, months, weeks, days } = ES.DifferenceDate(other, { year, month, day }, dateLargestUnit); ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceDuration( days, diff --git a/polyfill/lib/time.mjs b/polyfill/lib/time.mjs index cb7ff86cf5..9833211c3b 100644 --- a/polyfill/lib/time.mjs +++ b/polyfill/lib/time.mjs @@ -168,8 +168,10 @@ export class Time { if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver'); if (!ES.IsTemporalTime(other)) throw new TypeError('invalid Time object'); const largestUnit = ES.ToLargestTemporalUnit(options, 'hours'); - const [earlier, later] = [this, other].sort(Time.compare); - let { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.DifferenceTime(earlier, later); + const comparison = Time.compare(this, other); + if (comparison < 0) throw new RangeError('other instance cannot be larger than `this`'); + let { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.DifferenceTime(other, this); + /* if (hours >= 12) { hours = 24 - hours; minutes *= -1; @@ -178,6 +180,7 @@ export class Time { microseconds *= -1; nanoseconds *= -1; } + */ ({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceDuration( 0, hours, diff --git a/polyfill/lib/yearmonth.mjs b/polyfill/lib/yearmonth.mjs index 4c14c7fd7c..adee358fe5 100644 --- a/polyfill/lib/yearmonth.mjs +++ b/polyfill/lib/yearmonth.mjs @@ -100,9 +100,10 @@ export class YearMonth { if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver'); if (!ES.IsTemporalYearMonth(other)) throw new TypeError('invalid YearMonth object'); const largestUnit = ES.ToLargestTemporalUnit(options, 'years', ['weeks', 'days', 'hours', 'minutes', 'seconds']); - const [one, two] = [this, other].sort(YearMonth.compare); - let years = two.year - one.year; - let months = two.month - one.month; + const comparison = YearMonth.compare(this, other); + if (comparison < 0) throw new RangeError('other instance cannot be larger than `this`'); + let years = this.year - other.year; + let months = this.month - other.month; if (months < 0) { years -= 1; months += 12; diff --git a/polyfill/test/absolute.mjs b/polyfill/test/absolute.mjs index fd716525a9..58920eabf4 100644 --- a/polyfill/test/absolute.mjs +++ b/polyfill/test/absolute.mjs @@ -423,9 +423,10 @@ describe('Absolute', () => { describe('Absolute.difference works', () => { const earlier = Absolute.from('1976-11-18T15:23:30.123456789Z'); const later = Absolute.from('2019-10-29T10:46:38.271986102Z'); - const diff = earlier.difference(later); - it(`(${earlier}).difference(${later}) == (${later}).difference(${earlier})`, () => - equal(`${later.difference(earlier)}`, `${diff}`)); + const diff = later.difference(earlier); + // it(`(${earlier}).difference(${later}) == (${later}).difference(${earlier})`, () => + // equal(`${later.difference(earlier)}`, `${diff}`)); + it('throws if out of order', () => throws(() => earlier.difference(later), RangeError)); it(`(${earlier}).plus(${diff}) == (${later})`, () => assert(earlier.plus(diff).equals(later))); it(`(${later}).minus(${diff}) == (${earlier})`, () => assert(later.minus(diff).equals(earlier))); it("doesn't cast argument", () => { diff --git a/polyfill/test/date.mjs b/polyfill/test/date.mjs index 520fe7ce50..32ac37ae17 100644 --- a/polyfill/test/date.mjs +++ b/polyfill/test/date.mjs @@ -162,7 +162,8 @@ describe('Date', () => { equal(duration.nanoseconds, 0); }); it('date.difference({ year: 2019, month: 11, day: 18 }, { largestUnit: "years" })', () => { - const duration = date.difference(Date.from({ year: 2019, month: 11, day: 18 }), { largestUnit: 'years' }); + const later = Date.from({ year: 2019, month: 11, day: 18 }); + const duration = later.difference(date, { largestUnit: 'years' }); equal(duration.years, 43); equal(duration.months, 0); equal(duration.weeks, 0); @@ -182,12 +183,12 @@ describe('Date', () => { const date1 = Date.from('2019-01-01'); const date2 = Date.from('2019-02-01'); const date3 = Date.from('2019-03-01'); - equal(`${date1.difference(date2)}`, 'P31D'); - equal(`${date2.difference(date3)}`, 'P28D'); + equal(`${date2.difference(date1)}`, 'P31D'); + equal(`${date3.difference(date2)}`, 'P28D'); const date4 = Date.from('2020-02-01'); const date5 = Date.from('2020-03-01'); - equal(`${date4.difference(date5)}`, 'P29D'); + equal(`${date5.difference(date4)}`, 'P29D'); }); it('takes days per year into account', () => { const date1 = Date.from('2019-01-01'); @@ -196,10 +197,10 @@ describe('Date', () => { const date4 = Date.from('2020-06-01'); const date5 = Date.from('2021-01-01'); const date6 = Date.from('2021-06-01'); - equal(`${date1.difference(date3)}`, 'P365D'); - equal(`${date3.difference(date5)}`, 'P366D'); - equal(`${date2.difference(date4)}`, 'P366D'); - equal(`${date4.difference(date6)}`, 'P365D'); + equal(`${date3.difference(date1)}`, 'P365D'); + equal(`${date5.difference(date3)}`, 'P366D'); + equal(`${date4.difference(date2)}`, 'P366D'); + equal(`${date6.difference(date4)}`, 'P365D'); }); const feb20 = Date.from('2020-02-01'); const feb21 = Date.from('2021-02-01'); diff --git a/polyfill/test/datetime.mjs b/polyfill/test/datetime.mjs index 9bb6166594..426b065148 100644 --- a/polyfill/test/datetime.mjs +++ b/polyfill/test/datetime.mjs @@ -300,9 +300,12 @@ describe('DateTime', () => { const earlier = DateTime.from('1976-11-18T15:23:30.123456789'); const later = DateTime.from('2019-10-29T10:46:38.271986102'); ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'].forEach((largestUnit) => { - const diff = earlier.difference(later, { largestUnit }); + const diff = later.difference(earlier, { largestUnit }); + /* it(`(${earlier}).difference(${later}, ${largestUnit}) == (${later}).difference(${earlier}, ${largestUnit})`, () => equal(`${later.difference(earlier, { largestUnit })}`, `${diff}`)); + */ + it('throws if out of order', () => throws(() => earlier.difference(later), RangeError)); it(`(${earlier}).plus(${diff}) == (${later})`, () => earlier.plus(diff).equals(later)); it(`(${later}).minus(${diff}) == (${earlier})`, () => later.minus(diff).equals(earlier)); }); diff --git a/polyfill/test/time.mjs b/polyfill/test/time.mjs index d1954f9fcb..9b643e5be4 100644 --- a/polyfill/test/time.mjs +++ b/polyfill/test/time.mjs @@ -215,6 +215,7 @@ describe('Time', () => { const duration = time.difference(two); equal(`${duration}`, 'PT1H53M'); }); + /* it('always returns a duration of 12 hours or less', () => { const start1 = new Temporal.Time(11); const start2 = new Temporal.Time(23); @@ -249,6 +250,7 @@ describe('Time', () => { end = start2.plus(duration); equal(`${start2.difference(end)}`, 'PT11H'); }); + */ it('returns the same duration no matter when the start time is', () => { const hours = Array(24) .fill() @@ -256,7 +258,11 @@ describe('Time', () => { hours.forEach((hour) => { const time1 = new Temporal.Time(hour); const time2 = time1.plus(Temporal.Duration.from('PT9H')); - equal(`${time1.difference(time2)}`, 'PT9H'); + if (Temporal.Time.compare(time2, time1) < 0) { + throws(() => time2.difference(time1), RangeError); + } else { + equal(`${time2.difference(time1)}`, 'PT9H'); + } }); const zeroTo59 = Array(60) @@ -265,11 +271,19 @@ describe('Time', () => { zeroTo59.forEach((num) => { const minute1 = new Temporal.Time(23, num); const minute2 = minute1.plus(Temporal.Duration.from('PT45M')); - equal(`${minute1.difference(minute2)}`, 'PT45M'); + if (Temporal.Time.compare(minute2, minute1) < 0) { + throws(() => minute2.difference(minute1), RangeError); + } else { + equal(`${minute2.difference(minute1)}`, 'PT45M'); + } const second1 = new Temporal.Time(23, 59, num); const second2 = second1.plus(Temporal.Duration.from('PT45S')); - equal(`${second1.difference(second2)}`, 'PT45S'); + if (Temporal.Time.compare(second2, second1) < 0) { + throws(() => second2.difference(second1), RangeError); + } else { + equal(`${second2.difference(second1)}`, 'PT45S'); + } }); const last10 = Array(10) @@ -278,15 +292,27 @@ describe('Time', () => { last10.forEach((num) => { const ms1 = new Temporal.Time(23, 59, 59, num); const ms2 = ms1.plus(Temporal.Duration.from('PT0.008S')); - equal(`${ms1.difference(ms2)}`, 'PT0.008S'); + if (Temporal.Time.compare(ms2, ms1) < 0) { + throws(() => ms2.difference(ms1), RangeError); + } else { + equal(`${ms2.difference(ms1)}`, 'PT0.008S'); + } const µs1 = new Temporal.Time(23, 59, 59, 999, num); const µs2 = µs1.plus(Temporal.Duration.from('PT0.000008S')); - equal(`${µs1.difference(µs2)}`, 'PT0.000008S'); + if (Temporal.Time.compare(µs2, µs1) < 0) { + throws(() => µs2.difference(µs1), RangeError); + } else { + equal(`${µs2.difference(µs1)}`, 'PT0.000008S'); + } const ns1 = new Temporal.Time(23, 59, 59, 999, 999, num); const ns2 = ns1.plus(Temporal.Duration.from('PT0.000000008S')); - equal(`${ns1.difference(ns2)}`, 'PT0.000000008S'); + if (Temporal.Time.compare(ns2, ns1) < 0) { + throws(() => ns2.difference(ns1), RangeError); + } else { + equal(`${ns2.difference(ns1)}`, 'PT0.000000008S'); + } }); }); it("doesn't cast argument", () => { @@ -296,18 +322,18 @@ describe('Time', () => { const time1 = Time.from('10:23:15'); const time2 = Time.from('17:15:57'); it('the default largest unit is at least hours', () => { - equal(`${time1.difference(time2)}`, 'PT6H52M42S'); - equal(`${time1.difference(time2, { largestUnit: 'hours' })}`, 'PT6H52M42S'); + equal(`${time2.difference(time1)}`, 'PT6H52M42S'); + equal(`${time2.difference(time1, { largestUnit: 'hours' })}`, 'PT6H52M42S'); }); it('higher units have no effect', () => { - equal(`${time1.difference(time2, { largestUnit: 'days' })}`, 'PT6H52M42S'); - equal(`${time1.difference(time2, { largestUnit: 'weeks' })}`, 'PT6H52M42S'); - equal(`${time1.difference(time2, { largestUnit: 'months' })}`, 'PT6H52M42S'); - equal(`${time1.difference(time2, { largestUnit: 'years' })}`, 'PT6H52M42S'); + equal(`${time2.difference(time1, { largestUnit: 'days' })}`, 'PT6H52M42S'); + equal(`${time2.difference(time1, { largestUnit: 'weeks' })}`, 'PT6H52M42S'); + equal(`${time2.difference(time1, { largestUnit: 'months' })}`, 'PT6H52M42S'); + equal(`${time2.difference(time1, { largestUnit: 'years' })}`, 'PT6H52M42S'); }); it('can return lower units', () => { - equal(`${time1.difference(time2, { largestUnit: 'minutes' })}`, 'PT412M42S'); - equal(`${time1.difference(time2, { largestUnit: 'seconds' })}`, 'PT24762S'); + equal(`${time2.difference(time1, { largestUnit: 'minutes' })}`, 'PT412M42S'); + equal(`${time2.difference(time1, { largestUnit: 'seconds' })}`, 'PT24762S'); }); }); describe('Time.compare() works', () => { diff --git a/polyfill/test/yearmonth.mjs b/polyfill/test/yearmonth.mjs index 705f9b6a55..d32699f720 100644 --- a/polyfill/test/yearmonth.mjs +++ b/polyfill/test/yearmonth.mjs @@ -167,9 +167,10 @@ describe('YearMonth', () => { describe('YearMonth.difference() works', () => { const nov94 = YearMonth.from('1994-11'); const jun13 = YearMonth.from('2013-06'); - const diff = nov94.difference(jun13); - it(`${nov94}.difference(${jun13}) == ${jun13}.difference(${nov94})`, () => - equal(`${diff}`, `${jun13.difference(nov94)}`)); + const diff = jun13.difference(nov94); + it('throws if out of order', () => throws(() => nov94.difference(jun13), RangeError)); + // it(`${nov94}.difference(${jun13}) == ${jun13}.difference(${nov94})`, () => + // equal(`${diff}`, `${jun13.difference(nov94)}`)); it(`${nov94}.plus(${diff}) == ${jun13}`, () => nov94.plus(diff).equals(jun13)); it(`${jun13}.minus(${diff}) == ${nov94}`, () => jun13.minus(diff).equals(nov94)); it("doesn't cast argument", () => { diff --git a/spec/absolute.html b/spec/absolute.html index a54000650a..d808c150f2 100644 --- a/spec/absolute.html +++ b/spec/absolute.html @@ -287,8 +287,7 @@

Temporal.Absolute.prototype.difference ( _other_ [, _options_ ] )

1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalAbsolute]]). 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"years"*, *"months"*, *"weeks"* », *"seconds"*). 1. If ! CompareTemporalAbsolute(_absolute_, _other_) < 0, then - 1. Let _greater_ be _otherAbsolute_. - 1. Let _smaller_ be _absolute_. + 1. Throw a *RangeError* exception. 1. Else, 1. Let _greater_ be _absolute_. 1. Let _smaller_ be _otherAbsolute_. diff --git a/spec/date.html b/spec/date.html index d8b5bab333..901be04aea 100644 --- a/spec/date.html +++ b/spec/date.html @@ -366,8 +366,7 @@

Temporal.Date.prototype.difference ( _other_ [ , _options_ ] )

1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalDate]]). 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"hours"*, *"minutes"*, *"seconds"* », *"days"*). 1. If ! CompareTemporalDate(_temporalDate_, _other_) < 0, then - 1. Let _greater_ be _other_. - 1. Let _smaller_ be _temporalDate_. + 1. Throw a *RangeError* exception. 1. Else, 1. Let _greater_ be _temporalDate_. 1. Let _smaller_ be _other_. diff --git a/spec/datetime.html b/spec/datetime.html index a07c5054ec..98e7c42410 100644 --- a/spec/datetime.html +++ b/spec/datetime.html @@ -422,8 +422,7 @@

Temporal.DateTime.prototype.difference ( _other_ [ , _options_ ] )

1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalDateTime]]). 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « », *"days"*). 1. If ! CompareTemporalDateTime(_dateTime_, _other_) < 0, then - 1. Let _greater_ be _other_. - 1. Let _smaller_ be _dateTime_. + 1. Throw a *RangeError* exception. 1. Else, 1. Let _greater_ be _dateTime_. 1. Let _smaller_ be _other_. diff --git a/spec/time.html b/spec/time.html index fbe882c0e7..24ef841f4c 100644 --- a/spec/time.html +++ b/spec/time.html @@ -291,8 +291,7 @@

Temporal.Time.prototype.difference ( _other_ [ , _options_ ] )

1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalTime]]). 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « », *"hours"*). 1. If ! CompareTemporalTime(_temporalTime_, _other_) < 0, then - 1. Let _greater_ be _other_. - 1. Let _smaller_ be _temporalTime_. + 1. Throw a *RangeError* exception. 1. Else, 1. Let _greater_ be _temporalTime_. 1. Let _smaller_ be _other_. diff --git a/spec/yearmonth.html b/spec/yearmonth.html index fe1f6fc47f..bd7e7dfaf1 100644 --- a/spec/yearmonth.html +++ b/spec/yearmonth.html @@ -257,8 +257,7 @@

Temporal.YearMonth.prototype.difference ( _other_ [ , _options_ ] )

1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalYearMonth]]). 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"weeks"*, *"days"*, *"hours"*, *"minutes"*, *"seconds"* », *"years"*). 1. If ! CompareTemporalYearMonth(_yearMonth_, _other_) < 0, then - 1. Let _greater_ be _other_. - 1. Let _smaller_ be _yearMonth_. + 1. Throw a *RangeError* exception. 1. Else, 1. Let _greater_ be _yearMonth_. 1. Let _smaller_ be _other_.