Skip to content

Commit

Permalink
Allow strings and property bags in difference() methods
Browse files Browse the repository at this point in the history
See: #592
  • Loading branch information
ptomato authored and Ms2ger committed Oct 21, 2020
1 parent 6f643bb commit 245e266
Show file tree
Hide file tree
Showing 21 changed files with 60 additions and 40 deletions.
6 changes: 4 additions & 2 deletions docs/date.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,11 @@ date.subtract({ months: 1 }); // => 2019-02-28
date.subtract({ months: 1 }, { overflow: 'reject' }); // => throws
```

### date.**difference**(_other_: Temporal.Date, _options_?: object) : Temporal.Duration
### date.**difference**(_other_: Temporal.Date | object | string, _options_?: object) : Temporal.Duration

**Parameters:**

- `other` (`Temporal.Date`): Another date with which to compute the difference.
- `other` (`Temporal.Date` or value convertible to one): Another date with which to compute the difference.
- `options` (optional object): An object with properties representing options for the operation.
The following options are recognized:
- `largestUnit` (optional string): The largest unit of time to allow in the resulting `Temporal.Duration` object.
Expand All @@ -457,6 +457,8 @@ date.subtract({ months: 1 }, { overflow: 'reject' }); // => throws
This method computes the difference between the two dates represented by `date` and `other`, optionally rounds it, and returns it as a `Temporal.Duration` object.
If `other` is later than `date` then the resulting duration will be negative.

If `other` is not a `Temporal.Date` object, then it will be converted to one as if it were passed to `Temporal.Date.from()`.

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`.
A difference of two years will become 24 months when `largestUnit` is `"months"`, for example.
Expand Down
6 changes: 4 additions & 2 deletions docs/datetime.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,11 @@ dt.subtract({ months: 1 }, { overflow: 'constrain' }); // => 2019-02-28T15:30
dt.subtract({ months: 1 }); // => throws
```

### datetime.**difference**(_other_: Temporal.DateTime, _options_?: object) : Temporal.Duration
### datetime.**difference**(_other_: Temporal.DateTime | object | string, _options_?: object) : Temporal.Duration

**Parameters:**

- `other` (`Temporal.DateTime`): Another date/time with which to compute the difference.
- `other` (`Temporal.DateTime` or value convertible to one): Another date/time with which to compute the difference.
- `options` (optional object): An object with properties representing options for the operation.
The following options are recognized:
- `largestUnit` (string): The largest unit of time to allow in the resulting `Temporal.Duration` object.
Expand All @@ -526,6 +526,8 @@ dt.subtract({ months: 1 }); // => throws
This method computes the difference between the two times represented by `datetime` and `other`, optionally rounds it, and returns it as a `Temporal.Duration` object.
If `other` is later than `datetime` then the resulting duration will be negative.

If `other` is not a `Temporal.DateTime` object, then it will be converted to one as if it were passed to `Temporal.DateTime.from()`.

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`.
A difference of two hours will become 7200 seconds when `largestUnit` is `"seconds"`, for example.
Expand Down
6 changes: 4 additions & 2 deletions docs/instant.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,11 @@ oneHour = Temporal.Duration.from({ hours: 1 });
Temporal.now.instant().subtract(oneHour);
```

### instant.**difference**(_other_: Temporal.Instant, _options_?: object) : Temporal.Duration
### instant.**difference**(_other_: Temporal.Instant | string, _options_?: object) : Temporal.Duration

**Parameters:**

- `other` (`Temporal.Instant`): Another exact time with which to compute the difference.
- `other` (`Temporal.Instant` or value convertible to one): Another exact time with which to compute the difference.
- `options` (optional object): An object with properties representing options for the operation.
The following options are recognized:
- `largestUnit` (string): The largest unit of time to allow in the resulting `Temporal.Duration` object.
Expand All @@ -427,6 +427,8 @@ Temporal.now.instant().subtract(oneHour);
This method computes the difference between the two exact times represented by `instant` and `other`, optionally rounds it, and returns it as a `Temporal.Duration` object.
If `other` is later than `instant` then the resulting duration will be negative.

If `other` is not a `Temporal.Instant` object, then it will be converted to one as if it were passed to `Temporal.Instant.from()`.

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`.
A difference of two hours will become 7200 seconds when `largestUnit` is `"seconds"`, for example.
Expand Down
6 changes: 4 additions & 2 deletions docs/time.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,11 +262,11 @@ time = Temporal.Time.from('19:39:09.068346205');
time.subtract({ minutes: 5, nanoseconds: 800 }); // => 19:34:09.068345405
```

### time.**difference**(_other_: Temporal.Time, _options_?: object) : Temporal.Duration
### time.**difference**(_other_: Temporal.Time | object | string, _options_?: object) : Temporal.Duration

**Parameters:**

- `other` (`Temporal.Time`): Another time with which to compute the difference.
- `other` (`Temporal.Time` or value convertible to one): Another time with which to compute the difference.
- `options` (optional object): An object with properties representing options for the operation.
The following options are recognized:
- `largestUnit` (string): The largest unit of time to allow in the resulting `Temporal.Duration` object.
Expand All @@ -286,6 +286,8 @@ time.subtract({ minutes: 5, nanoseconds: 800 }); // => 19:34:09.068345405
This method computes the difference between the two times represented by `time` and `other`, optionally rounds it, and returns it as a `Temporal.Duration` object.
If `other` is later than `time` then the resulting duration will be negative.

If `other` is not a `Temporal.Time` object, then it will be converted to one as if it were passed to `Temporal.Time.from()`.

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.
Expand Down
6 changes: 4 additions & 2 deletions docs/yearmonth.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,10 @@ ym = Temporal.YearMonth.from('2019-06');
ym.subtract({years: 20, months: 4}) // => 1999-02
```

### yearMonth.**difference**(_other_: Temporal.YearMonth, _options_?: object) : Temporal.Duration
### yearMonth.**difference**(_other_: Temporal.YearMonth | object | string, _options_?: object) : Temporal.Duration

**Parameters:**
- `other` (`Temporal.YearMonth`): Another month with which to compute the difference.
- `other` (`Temporal.YearMonth` or value convertible to one): Another month with which to compute the difference.
- `options` (optional object): An object with properties representing options for the operation.
The following options are recognized:
- `largestUnit` (string): The largest unit of time to allow in the resulting `Temporal.Duration` object.
Expand All @@ -332,6 +332,8 @@ ym.subtract({years: 20, months: 4}) // => 1999-02
This method computes the difference between the two months represented by `yearMonth` and `other`, optionally rounds it, and returns it as a `Temporal.Duration` object.
If `other` is later than `yearMonth` then the resulting duration will be negative.

If `other` is not a `Temporal.YearMonth` object, then it will be converted to one as if it were passed to `Temporal.YearMonth.from()`.

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`.
A difference of one year and two months will become 14 months when `largestUnit` is `"months"`, for example.
Expand Down
10 changes: 5 additions & 5 deletions polyfill/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export namespace Temporal {
add(durationLike: Temporal.Duration | DurationLike | string): Temporal.Instant;
subtract(durationLike: Temporal.Duration | DurationLike | string): Temporal.Instant;
difference(
other: Temporal.Instant,
other: Temporal.Instant | string,
options?: DifferenceOptions<
| 'hours'
| 'minutes'
Expand Down Expand Up @@ -524,7 +524,7 @@ export namespace Temporal {
add(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.Date;
subtract(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.Date;
difference(
other: Temporal.Date,
other: Temporal.Date | DateLike | string,
options?: DifferenceOptions<
| 'years'
| 'months'
Expand Down Expand Up @@ -639,7 +639,7 @@ export namespace Temporal {
add(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.DateTime;
subtract(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.DateTime;
difference(
other: Temporal.DateTime,
other: Temporal.DateTime | DateTimeLike | string,
options?: DifferenceOptions<
| 'years'
| 'months'
Expand Down Expand Up @@ -785,7 +785,7 @@ export namespace Temporal {
options?: ArithmeticOptions
): Temporal.Time;
difference(
other: Temporal.Time,
other: Temporal.Time | TimeLike | string,
options?: DifferenceOptions<
| 'hours'
| 'minutes'
Expand Down Expand Up @@ -910,7 +910,7 @@ export namespace Temporal {
add(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.YearMonth;
subtract(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.YearMonth;
difference(
other: Temporal.YearMonth,
other: Temporal.YearMonth | YearMonthLike | string,
options?: DifferenceOptions<'years' | 'months' | /** @deprecated */ 'year' | /** @deprecated */ 'month'>
): Temporal.Duration;
toDateOnDay(day: number): Temporal.Date;
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/date.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export class Date {
}
difference(other, options = undefined) {
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
if (!ES.IsTemporalDate(other)) throw new TypeError('invalid Date object');
other = ES.ToTemporalDate(other, Date);
const calendar = GetSlot(this, CALENDAR);
const otherCalendar = GetSlot(other, CALENDAR);
const calendarId = ES.CalendarToString(calendar);
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/datetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ export class DateTime {
}
difference(other, options = undefined) {
if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
if (!ES.IsTemporalDateTime(other)) throw new TypeError('invalid DateTime object');
other = ES.ToTemporalDateTime(other, DateTime);
const calendar = GetSlot(this, CALENDAR);
const otherCalendar = GetSlot(other, CALENDAR);
const calendarId = ES.CalendarToString(calendar);
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/instant.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class Instant {
}
difference(other, options = undefined) {
if (!ES.IsTemporalInstant(this)) throw new TypeError('invalid receiver');
if (!ES.IsTemporalInstant(other)) throw new TypeError('invalid Instant object');
other = ES.ToTemporalInstant(other, Instant);
const disallowedUnits = ['years', 'months', 'weeks', 'days'];
options = ES.NormalizeOptionsObject(options);
const smallestUnit = ES.ToSmallestTemporalDurationUnit(options, 'nanoseconds', disallowedUnits);
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/time.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ export class Time {
}
difference(other, options = undefined) {
if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver');
if (!ES.IsTemporalTime(other)) throw new TypeError('invalid Time object');
other = ES.ToTemporalTime(other, Time);
options = ES.NormalizeOptionsObject(options);
const largestUnit = ES.ToLargestTemporalUnit(options, 'hours', ['years', 'months', 'weeks', 'days']);
const smallestUnit = ES.ToSmallestTemporalDurationUnit(options, 'nanoseconds');
Expand Down
2 changes: 1 addition & 1 deletion polyfill/lib/yearmonth.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export class YearMonth {
}
difference(other, options = undefined) {
if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
if (!ES.IsTemporalYearMonth(other)) throw new TypeError('invalid YearMonth object');
other = ES.ToTemporalYearMonth(other, YearMonth);
const calendar = GetSlot(this, CALENDAR);
const otherCalendar = GetSlot(other, CALENDAR);
if (calendar.id !== otherCalendar.id) {
Expand Down
6 changes: 3 additions & 3 deletions polyfill/test/date.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ describe('Date', () => {
equal(duration.microseconds, 0);
equal(duration.nanoseconds, 0);
});
it("doesn't cast argument", () => {
throws(() => date.difference({ year: 2019, month: 11, day: 5 }), TypeError);
throws(() => date.difference('2019-11-05'), TypeError);
it('casts argument', () => {
equal(`${date.difference({ year: 2019, month: 11, day: 5 })}`, '-P15692D');
equal(`${date.difference('2019-11-05')}`, '-P15692D');
});
it('takes days per month into account', () => {
const date1 = Date.from('2019-01-01');
Expand Down
6 changes: 3 additions & 3 deletions polyfill/test/datetime.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,9 @@ describe('DateTime', () => {
});
describe('DateTime.difference()', () => {
const dt = DateTime.from('1976-11-18T15:23:30.123456789');
it("doesn't cast argument", () => {
throws(() => dt.difference({ year: 2019, month: 10, day: 29, hour: 10 }), TypeError);
throws(() => dt.difference('2019-10-29T10:46:38.271986102'), TypeError);
it('casts argument', () => {
equal(`${dt.difference({ year: 2019, month: 10, day: 29, hour: 10 })}`, '-P15684DT18H36M29.876543211S');
equal(`${dt.difference('2019-10-29T10:46:38.271986102')}`, '-P15684DT19H23M8.148529313S');
});
const feb20 = DateTime.from('2020-02-01T00:00');
const feb21 = DateTime.from('2021-02-01T00:00');
Expand Down
9 changes: 6 additions & 3 deletions polyfill/test/instant.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,12 @@ describe('Instant', () => {
equal(`${earlier.difference(later)}`, `${diff.negated()}`));
it(`(${earlier}).add(${diff}) == (${later})`, () => assert(earlier.add(diff).equals(later)));
it(`(${later}).subtract(${diff}) == (${earlier})`, () => assert(later.subtract(diff).equals(earlier)));
it("doesn't cast argument", () => {
throws(() => earlier.difference(later.toString()), TypeError);
throws(() => earlier.difference({}), TypeError);
it('casts argument from string', () => {
equal(`${later.difference(earlier.toString())}`, `${diff}`);
});
it('only casts from a string', () => {
throws(() => later.difference(earlier.epochNanoseconds), RangeError);
throws(() => earlier.difference({}), RangeError);
});
const feb20 = Instant.from('2020-02-01T00:00Z');
const feb21 = Instant.from('2021-02-01T00:00Z');
Expand Down
10 changes: 7 additions & 3 deletions polyfill/test/time.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,13 @@ describe('Time', () => {
equal(`${duration}`, 'PT1H53M');
});
it(`(${two}).difference(${time}) => -PT1H53M`, () => equal(`${two.difference(time)}`, '-PT1H53M'));
it("doesn't cast argument", () => {
throws(() => time.difference({ hour: 16, minute: 34 }), TypeError);
throws(() => time.difference('16:34'), TypeError);
it('casts argument', () => {
equal(`${time.difference({ hour: 16, minute: 34 })}`, '-PT1H10M29.876543211S');
equal(`${time.difference('16:34')}`, '-PT1H10M29.876543211S');
});
it('object must contain at least one correctly-spelled property', () => {
throws(() => time.difference({}), TypeError);
throws(() => time.difference({ minutes: 30 }), TypeError);
});
const time1 = Time.from('10:23:15');
const time2 = Time.from('17:15:57');
Expand Down
9 changes: 6 additions & 3 deletions polyfill/test/yearmonth.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,12 @@ describe('YearMonth', () => {
equal(`${nov94.difference(jun13)}`, `${diff.negated()}`));
it(`${nov94}.add(${diff}) == ${jun13}`, () => nov94.add(diff).equals(jun13));
it(`${jun13}.subtract(${diff}) == ${nov94}`, () => jun13.subtract(diff).equals(nov94));
it("doesn't cast argument", () => {
throws(() => nov94.difference({ year: 2013, month: 6 }), TypeError);
throws(() => nov94.difference('2013-06'), TypeError);
it('casts argument', () => {
equal(`${jun13.difference({ year: 1994, month: 11 })}`, `${diff}`);
equal(`${jun13.difference('1994-11')}`, `${diff}`);
});
it('object must contain at least the required properties', () => {
throws(() => jun13.difference({ year: 1994 }), TypeError);
});
const feb20 = YearMonth.from('2020-02');
const feb21 = YearMonth.from('2021-02');
Expand Down
2 changes: 1 addition & 1 deletion spec/date.html
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ <h1>Temporal.Date.prototype.difference ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _temporalDate_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalDate]]).
1. Set _other_ to ? ToTemporalDate(_other_).
1. Let _calendar_ be _temporalDate_.[[Calendar]].
1. Let _calendarID_ be ? CalendarToString(_calendar_).
1. Let _otherCalendar_ be _other_.[[Calendar]].
Expand Down
2 changes: 1 addition & 1 deletion spec/datetime.html
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ <h1>Temporal.DateTime.prototype.difference ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _dateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalDateTime]]).
1. Set _other_ to ? ToTemporalDateTime(_other_).
1. Let _calendar_ be _temporalDate_.[[Calendar]].
1. Let _calendarID_ be ? CalendarToString(_calendar_).
1. Let _otherCalendar_ be _other_.[[Calendar]].
Expand Down
2 changes: 1 addition & 1 deletion spec/instant.html
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ <h1>Temporal.Instant.prototype.difference ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _instant_ be the *this* value.
1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]).
1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalInstant]]).
1. Set _other_ to ? ToTemporalInstant(_other_).
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _smallestUnit_ be ? ToSmallestTemporalDurationUnit(_options_, « *"years"*, *"months"*, *"weeks"*, *"days"* », *"nanoseconds"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalDurationUnits(*"seconds"*, _smallestUnit_).
Expand Down
2 changes: 1 addition & 1 deletion spec/time.html
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ <h1>Temporal.Time.prototype.difference ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _temporalTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalTime_, [[InitializedTemporalTime]]).
1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalTime]]).
1. Set _other_ to ? ToTemporalTime(_other_).
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _smallestUnit_ be ? ToSmallestTemporalDurationUnit(_options_, « *"years"*, *"months"*, *"weeks"*, *"days"* », *"nanoseconds"*).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"years"*, *"months"*, *"weeks"*, *"days"* », *"hours"*).
Expand Down
2 changes: 1 addition & 1 deletion spec/yearmonth.html
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ <h1>Temporal.YearMonth.prototype.difference ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _yearMonth_ be the *this* value.
1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalYearMonth]]).
1. Set _other_ to ? ToTemporalYearMonth(_other_).
1. Set _options_ to ? NormalizeOptionsObject(_options_).
1. Let _disallowedUnits_ be « *"weeks"*, *"days"*, *"hours"*, *"minutes"*, *"seconds"*, *"milliseconds"*, *"microseconds"*, *"nanoseconds"* ».
1. Let _smallestUnit_ be ? ToSmallestTemporalDurationUnit(_options_, *"months"*, _disallowedUnits_).
Expand Down

0 comments on commit 245e266

Please sign in to comment.