From 4a7d73eb52363391a874186bd264b9c7504105e9 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Mon, 18 May 2020 17:21:57 -0700 Subject: [PATCH] Add equal() method This adds an equal() method to Absolute, Date, DateTime, MonthDay, Time, and YearMonth. Currently `a.equal(b)` is equivalent to `Temporal.X.compare(a, b) === 0`, but after calendars are added, equal() should additionally return false if the calendars in the two objects are different. Duration doesn't have an equal() method at this time because, does `{ minutes: 1, seconds: 30 }` equal `{ seconds: 90 }`? TimeZone doesn't have one either because it's simple enough to compare the .name property. --- docs/absolute.md | 21 +++++++++++++ docs/date.md | 22 ++++++++++++++ docs/datetime.md | 22 ++++++++++++++ docs/monthday.md | 21 +++++++++++++ docs/time.md | 21 +++++++++++++ docs/yearmonth.md | 22 ++++++++++++++ polyfill/lib/absolute.mjs | 7 +++++ polyfill/lib/date.mjs | 10 +++++++ polyfill/lib/datetime.mjs | 10 +++++++ polyfill/lib/monthday.mjs | 10 +++++++ polyfill/lib/time.mjs | 10 +++++++ polyfill/lib/yearmonth.mjs | 10 +++++++ .../prototype/equal/argument-wrong-type.js | 19 ++++++++++++ .../test/Absolute/prototype/equal/branding.js | 21 +++++++++++++ .../Absolute/prototype/equal/prop-desc.js | 19 ++++++++++++ .../prototype/equal/argument-wrong-type.js | 19 ++++++++++++ .../test/Date/prototype/equal/branding.js | 21 +++++++++++++ .../test/Date/prototype/equal/prop-desc.js | 18 +++++++++++ .../prototype/equal/argument-wrong-type.js | 19 ++++++++++++ .../test/DateTime/prototype/equal/branding.js | 21 +++++++++++++ .../DateTime/prototype/equal/prop-desc.js | 19 ++++++++++++ .../prototype/equal/argument-wrong-type.js | 19 ++++++++++++ .../test/MonthDay/prototype/equal/branding.js | 21 +++++++++++++ .../MonthDay/prototype/equal/prop-desc.js | 19 ++++++++++++ .../prototype/equal/argument-wrong-type.js | 19 ++++++++++++ .../test/Time/prototype/equal/branding.js | 21 +++++++++++++ .../test/Time/prototype/equal/prop-desc.js | 19 ++++++++++++ .../prototype/equal/argument-wrong-type.js | 19 ++++++++++++ .../YearMonth/prototype/equal/branding.js | 21 +++++++++++++ .../YearMonth/prototype/equal/prop-desc.js | 19 ++++++++++++ polyfill/test/absolute.mjs | 30 ++++++++++++++++--- polyfill/test/date.mjs | 17 +++++++++-- polyfill/test/datemath.mjs | 7 ++--- polyfill/test/datetime.mjs | 19 ++++++++++-- polyfill/test/monthday.mjs | 19 ++++++++++-- polyfill/test/time.mjs | 15 +++++++++- polyfill/test/yearmonth.mjs | 19 ++++++++++-- spec/absolute.html | 15 ++++++++++ spec/date.html | 17 +++++++++++ spec/datetime.html | 23 ++++++++++++++ spec/monthday.html | 16 ++++++++++ spec/time.html | 20 +++++++++++++ spec/yearmonth.html | 16 ++++++++++ 43 files changed, 751 insertions(+), 21 deletions(-) create mode 100644 polyfill/test/Absolute/prototype/equal/argument-wrong-type.js create mode 100644 polyfill/test/Absolute/prototype/equal/branding.js create mode 100644 polyfill/test/Absolute/prototype/equal/prop-desc.js create mode 100644 polyfill/test/Date/prototype/equal/argument-wrong-type.js create mode 100644 polyfill/test/Date/prototype/equal/branding.js create mode 100644 polyfill/test/Date/prototype/equal/prop-desc.js create mode 100644 polyfill/test/DateTime/prototype/equal/argument-wrong-type.js create mode 100644 polyfill/test/DateTime/prototype/equal/branding.js create mode 100644 polyfill/test/DateTime/prototype/equal/prop-desc.js create mode 100644 polyfill/test/MonthDay/prototype/equal/argument-wrong-type.js create mode 100644 polyfill/test/MonthDay/prototype/equal/branding.js create mode 100644 polyfill/test/MonthDay/prototype/equal/prop-desc.js create mode 100644 polyfill/test/Time/prototype/equal/argument-wrong-type.js create mode 100644 polyfill/test/Time/prototype/equal/branding.js create mode 100644 polyfill/test/Time/prototype/equal/prop-desc.js create mode 100644 polyfill/test/YearMonth/prototype/equal/argument-wrong-type.js create mode 100644 polyfill/test/YearMonth/prototype/equal/branding.js create mode 100644 polyfill/test/YearMonth/prototype/equal/prop-desc.js diff --git a/docs/absolute.md b/docs/absolute.md index ab73297033..0283a40301 100644 --- a/docs/absolute.md +++ b/docs/absolute.md @@ -334,6 +334,27 @@ epoch.inTimeZone(utc).difference(billion.inTimeZone(utc), { largestUnit: 'years' // => P31Y8M8DT1H46M40S ``` +### absolute.**equal**(_other_: Temporal.Absolute) : boolean + +**Parameters:** +- `other` (`Temporal.Absolute`): Another time to compare. + +**Returns:** `true` if `absolute` and `other` are equal, or `false` if not. + +Compares two `Temporal.Absolute` objects for equality. + +This function exists because it's not possible to compare using `absolute == other` or `absolute === other`, due to ambiguity in the primitive representation and between Temporal types. + +If you don't need to know the order in which the two times occur, then this function may be less typing and more efficient than `Temporal.Absolute.compare`. + +Example usage: +```javascript +one = Temporal.Absolute.fromEpochSeconds(1.0e9); +two = Temporal.Absolute.fromEpochSeconds(1.1e9); +one.equal(two) // => false +one.equal(one) // => true +``` + ### absolute.**toString**(_timeZone_?: Temporal.TimeZone | string) : string **Parameters:** diff --git a/docs/date.md b/docs/date.md index 76a16477fc..93846e8c59 100644 --- a/docs/date.md +++ b/docs/date.md @@ -371,6 +371,28 @@ date.withTime(midnight).difference(other.withTime(midnight), { largestUnit: 'hou // => PT109032H ``` +### date.**equal**(_other_: Temporal.Date) : boolean + +**Parameters:** +- `other` (`Temporal.Date`): Another date to compare. + +**Returns:** `true` if `date` and `other` are equal, or `false` if not. + +Compares two `Temporal.Date` objects for equality. + +This function exists because it's not possible to compare using `date == other` or `date === other`, due to ambiguity in the primitive representation and between Temporal types. + +The difference with `Temporal.Date.compare` is that this function will return `false` if the two dates are expressed in different calendar systems. +Even if you are using the same calendar system, if you don't need to know the order in which the two dates occur, then this function may be less typing and more efficient than `Temporal.Date.compare`. + +Example usage: +```javascript +date = Temporal.Date.from('2006-08-24'); +other = Temporal.Date.from('2019-01-31'); +date.equal(other) // => false +date.equal(date) // => true +``` + ### date.**toString**() : string **Returns:** a string in the ISO 8601 date format representing `date`. diff --git a/docs/datetime.md b/docs/datetime.md index 0e02b19de8..8f3e7eda93 100644 --- a/docs/datetime.md +++ b/docs/datetime.md @@ -429,6 +429,28 @@ feb1.difference(mar1); // => P29D feb1.difference(mar1, { largestUnit: 'months' }); // => P1M ``` +### datetime.**equal**(_other_: Temporal.DateTime) : boolean + +**Parameters:** +- `other` (`Temporal.DateTime`): Another date/time to compare. + +**Returns:** `true` if `datetime` and `other` are equal, or `false` if not. + +Compares two `Temporal.DateTime` objects for equality. + +This function exists because it's not possible to compare using `datetime == other` or `datetime === other`, due to ambiguity in the primitive representation and between Temporal types. + +The difference with `Temporal.DateTime.compare` is that this function will return `false` if the two dates/times are expressed in different calendar systems. +Even if you are using the same calendar system, if you don't need to know the order in which the two dates/times occur, then this function may be less typing and more efficient than `Temporal.DateTime.compare`. + +Example usage: +```javascript +dt1 = Temporal.DateTime.from('1995-12-07T03:24:30.000003500'); +dt2 = Temporal.DateTime.from('2019-01-31T15:30'); +dt1.equal(dt2) // => false +dt1.equal(dt1) // => true +``` + ### datetime.**toString**() : string **Returns:** a string in the ISO 8601 date format representing `datetime`. diff --git a/docs/monthday.md b/docs/monthday.md index b583a9eb60..90b054be63 100644 --- a/docs/monthday.md +++ b/docs/monthday.md @@ -150,6 +150,27 @@ md.with({ day: 31 }) // => 11-30 Temporal.MonthDay.from('02-01').with({ day: 31 }); // => 02-29 ``` +### monthDay.**equal**(_other_: Temporal.MonthDay) : boolean + +**Parameters:** +- `other` (`Temporal.MonthDay`): Another month-day to compare. + +**Returns:** `true` if `monthDay` and `other` are equal, or `false` if not. + +Compares two `Temporal.MonthDay` objects for equality. + +This function exists because it's not possible to compare using `monthDay == other` or `monthDay === other`, due to ambiguity in the primitive representation and between Temporal types. + +Note that this function will return `false` if the two inputs are expressed in different calendar systems. + +Example usage: +```javascript +dt1 = Temporal.DateTime.from('1995-12-07T03:24:30.000003500'); +dt2 = Temporal.DateTime.from('2019-01-31T15:30'); +dt1.equal(dt2) // => false +dt1.equal(dt1) // => true +``` + ### monthDay.**toString**() : string **Returns:** a string in the ISO 8601 date format representing `monthDay`. diff --git a/docs/time.md b/docs/time.md index cf0a50f18a..066d4c8107 100644 --- a/docs/time.md +++ b/docs/time.md @@ -270,6 +270,27 @@ time.difference(Temporal.Time.from('20:13:20.971398099')) // => PT34M11.9030518 Temporal.Time.from('01:00').difference(Temporal.Time.from('23:00')) // => P2H ``` +### time.**equal**(_other_: Temporal.Time) : boolean + +**Parameters:** +- `other` (`Temporal.Time`): Another time to compare. + +**Returns:** `true` if `time` and `other` are equal, or `false` if not. + +Compares two `Temporal.Time` objects for equality. + +This function exists because it's not possible to compare using `time == other` or `time === other`, due to ambiguity in the primitive representation and between Temporal types. + +If you don't need to know the order in which the two dates occur, then this function may be less typing and more efficient than `Temporal.Time.compare`. + +Example usage: +```javascript +time = Temporal.Time.from('19:39:09.068346205'); +other = Temporal.Time.from('20:13:20.971398099'); +time.equal(other) // => false +time.equal(time) // => true +``` + ### time.**toString**() : string **Returns:** a string in the ISO 8601 time format representing `time`. diff --git a/docs/yearmonth.md b/docs/yearmonth.md index 2182bbe83b..838600a97b 100644 --- a/docs/yearmonth.md +++ b/docs/yearmonth.md @@ -313,6 +313,28 @@ ym.difference(other, { largestUnit: 'months' }) // => P154M ym.withDay(1).difference(other.withDay(1), { largestUnit: 'days' }); // => P4687D ``` +### yearMonth.**equal**(_other_: Temporal.YearMonth) : boolean + +**Parameters:** +- `other` (`Temporal.YearMonth`): Another month to compare. + +**Returns:** `true` if `yearMonth` and `other` are equal, or `false` if not. + +Compares two `Temporal.YearMonth` objects for equality. + +This function exists because it's not possible to compare using `yearMonth == other` or `yearMonth === other`, due to ambiguity in the primitive representation and between Temporal types. + +Note that this function will return `false` if the two months are expressed in different calendar systems. +Even if you are using the same calendar system, if you don't need to know the order in which the two months occur, then this function may be less typing and more efficient than `Temporal.YearMonth.compare`. + +Example usage: +```javascript +ym = Temporal.YearMonth.from('2019-06'); +other = Temporal.YearMonth.from('2006-08'); +ym.equal(other) // => false +ym.equal(ym) // => true +``` + ### yearMonth.**toString**() : string **Returns:** a string in the ISO 8601 date format representing `yearMonth`. diff --git a/polyfill/lib/absolute.mjs b/polyfill/lib/absolute.mjs index 17755384df..cb8dfbd5c5 100644 --- a/polyfill/lib/absolute.mjs +++ b/polyfill/lib/absolute.mjs @@ -118,6 +118,13 @@ export class Absolute { ); return new Duration(0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } + equal(other) { + if (!ES.IsTemporalAbsolute(this)) throw new TypeError('invalid receiver'); + if (!ES.IsTemporalAbsolute(other)) throw new TypeError('invalid Absolute object'); + const one = GetSlot(this, EPOCHNANOSECONDS); + const two = GetSlot(other, EPOCHNANOSECONDS); + return bigInt(one).equals(two); + } toString(temporalTimeZoneLike = 'UTC') { if (!ES.IsTemporalAbsolute(this)) throw new TypeError('invalid receiver'); const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike); diff --git a/polyfill/lib/date.mjs b/polyfill/lib/date.mjs index 19bfaa6120..1339a947e8 100644 --- a/polyfill/lib/date.mjs +++ b/polyfill/lib/date.mjs @@ -131,6 +131,16 @@ export class Date { const Duration = GetIntrinsic('%Temporal.Duration%'); return new Duration(years, months, days, 0, 0, 0, 0, 0, 0); } + equal(other) { + if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver'); + if (!ES.IsTemporalDate(other)) throw new TypeError('invalid Date object'); + for (const slot of [YEAR, MONTH, DAY]) { + const val1 = GetSlot(this, slot); + const val2 = GetSlot(other, slot); + if (val1 !== val2) return false; + } + return true; + } toString() { if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver'); let year = ES.ISOYearString(GetSlot(this, YEAR)); diff --git a/polyfill/lib/datetime.mjs b/polyfill/lib/datetime.mjs index a285d753f8..0fee67b147 100644 --- a/polyfill/lib/datetime.mjs +++ b/polyfill/lib/datetime.mjs @@ -259,6 +259,16 @@ export class DateTime { const Duration = GetIntrinsic('%Temporal.Duration%'); return new Duration(years, months, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } + equal(other) { + if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver'); + if (!ES.IsTemporalDateTime(other)) throw new TypeError('invalid Date object'); + for (const slot of [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND, MICROSECOND, NANOSECOND]) { + const val1 = GetSlot(this, slot); + const val2 = GetSlot(other, slot); + if (val1 !== val2) return false; + } + return true; + } toString() { if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver'); let year = ES.ISOYearString(GetSlot(this, YEAR)); diff --git a/polyfill/lib/monthday.mjs b/polyfill/lib/monthday.mjs index eb4681b2a2..a9ac3127c8 100644 --- a/polyfill/lib/monthday.mjs +++ b/polyfill/lib/monthday.mjs @@ -37,6 +37,16 @@ export class MonthDay { if (!ES.IsTemporalMonthDay(result)) throw new TypeError('invalid result'); return result; } + equal(other) { + if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); + if (!ES.IsTemporalMonthDay(other)) throw new TypeError('invalid MonthDay object'); + for (const slot of [MONTH, DAY]) { + const val1 = GetSlot(this, slot); + const val2 = GetSlot(other, slot); + if (val1 !== val2) return false; + } + return true; + } toString() { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); let month = ES.ISODateTimePartString(GetSlot(this, MONTH)); diff --git a/polyfill/lib/time.mjs b/polyfill/lib/time.mjs index b211cef673..78e9a40de0 100644 --- a/polyfill/lib/time.mjs +++ b/polyfill/lib/time.mjs @@ -191,6 +191,16 @@ export class Time { const Duration = GetIntrinsic('%Temporal.Duration%'); return new Duration(0, 0, 0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } + equal(other) { + if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver'); + if (!ES.IsTemporalTime(other)) throw new TypeError('invalid Time object'); + for (const slot of [HOUR, MINUTE, SECOND, MILLISECOND, MICROSECOND, NANOSECOND]) { + const val1 = GetSlot(this, slot); + const val2 = GetSlot(other, slot); + if (val1 !== val2) return false; + } + return true; + } toString() { if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver'); diff --git a/polyfill/lib/yearmonth.mjs b/polyfill/lib/yearmonth.mjs index fd37f97804..3c1663c082 100644 --- a/polyfill/lib/yearmonth.mjs +++ b/polyfill/lib/yearmonth.mjs @@ -112,6 +112,16 @@ export class YearMonth { const Duration = GetIntrinsic('%Temporal.Duration%'); return new Duration(years, months); } + equal(other) { + if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver'); + if (!ES.IsTemporalYearMonth(other)) throw new TypeError('invalid YearMonth object'); + for (const slot of [YEAR, MONTH]) { + const val1 = GetSlot(this, slot); + const val2 = GetSlot(other, slot); + if (val1 !== val2) return false; + } + return true; + } toString() { if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver'); let year = ES.ISOYearString(GetSlot(this, YEAR)); diff --git a/polyfill/test/Absolute/prototype/equal/argument-wrong-type.js b/polyfill/test/Absolute/prototype/equal/argument-wrong-type.js new file mode 100644 index 0000000000..00d94a97e7 --- /dev/null +++ b/polyfill/test/Absolute/prototype/equal/argument-wrong-type.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.absolute.prototype.equal +features: [Symbol] +---*/ + +const instance = Temporal.Absolute.fromEpochSeconds(0); + +assert.throws(TypeError, () => instance.equal(undefined), "undefined"); +assert.throws(TypeError, () => instance.equal(null), "null"); +assert.throws(TypeError, () => instance.equal(true), "true"); +assert.throws(TypeError, () => instance.equal(""), "empty string"); +assert.throws(TypeError, () => instance.equal(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.equal(1), "1"); +assert.throws(TypeError, () => instance.equal({}), "plain object"); +assert.throws(TypeError, () => instance.equal(Temporal.Absolute), "Temporal.Absolute"); +assert.throws(TypeError, () => instance.equal(Temporal.Absolute.prototype), "Temporal.Absolute.prototype"); diff --git a/polyfill/test/Absolute/prototype/equal/branding.js b/polyfill/test/Absolute/prototype/equal/branding.js new file mode 100644 index 0000000000..b0ef4caf5b --- /dev/null +++ b/polyfill/test/Absolute/prototype/equal/branding.js @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.absolute.prototype.equal +features: [Symbol] +---*/ + +const equal = Temporal.Absolute.prototype.equal; + +assert.sameValue(typeof equal, "function"); + +assert.throws(TypeError, () => equal.call(undefined), "undefined"); +assert.throws(TypeError, () => equal.call(null), "null"); +assert.throws(TypeError, () => equal.call(true), "true"); +assert.throws(TypeError, () => equal.call(""), "empty string"); +assert.throws(TypeError, () => equal.call(Symbol()), "symbol"); +assert.throws(TypeError, () => equal.call(1), "1"); +assert.throws(TypeError, () => equal.call({}), "plain object"); +assert.throws(TypeError, () => equal.call(Temporal.Absolute), "Temporal.Absolute"); +assert.throws(TypeError, () => equal.call(Temporal.Absolute.prototype), "Temporal.Absolute.prototype"); diff --git a/polyfill/test/Absolute/prototype/equal/prop-desc.js b/polyfill/test/Absolute/prototype/equal/prop-desc.js new file mode 100644 index 0000000000..10540a2368 --- /dev/null +++ b/polyfill/test/Absolute/prototype/equal/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +includes: [propertyHelper.js] +---*/ + +const { Absolute } = Temporal; +assert.sameValue( + typeof Absolute.prototype.equal, + "function", + "`typeof Absolute.prototype.equal` is `function`" +); + +verifyProperty(Absolute.prototype, "equal", { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/polyfill/test/Date/prototype/equal/argument-wrong-type.js b/polyfill/test/Date/prototype/equal/argument-wrong-type.js new file mode 100644 index 0000000000..b768387d88 --- /dev/null +++ b/polyfill/test/Date/prototype/equal/argument-wrong-type.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.date.prototype.equal +features: [Symbol] +---*/ + +const instance = Temporal.Date.from({ year: 2000, month: 5, day: 2 }); + +assert.throws(TypeError, () => instance.equal(undefined), "undefined"); +assert.throws(TypeError, () => instance.equal(null), "null"); +assert.throws(TypeError, () => instance.equal(true), "true"); +assert.throws(TypeError, () => instance.equal(""), "empty string"); +assert.throws(TypeError, () => instance.equal(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.equal(1), "1"); +assert.throws(TypeError, () => instance.equal({}), "plain object"); +assert.throws(TypeError, () => instance.equal(Temporal.Date), "Temporal.Date"); +assert.throws(TypeError, () => instance.equal(Temporal.Date.prototype), "Temporal.Date.prototype"); diff --git a/polyfill/test/Date/prototype/equal/branding.js b/polyfill/test/Date/prototype/equal/branding.js new file mode 100644 index 0000000000..6ad088871d --- /dev/null +++ b/polyfill/test/Date/prototype/equal/branding.js @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.date.prototype.equal +features: [Symbol] +---*/ + +const equal = Temporal.Date.prototype.equal; + +assert.sameValue(typeof equal, "function"); + +assert.throws(TypeError, () => equal.call(undefined), "undefined"); +assert.throws(TypeError, () => equal.call(null), "null"); +assert.throws(TypeError, () => equal.call(true), "true"); +assert.throws(TypeError, () => equal.call(""), "empty string"); +assert.throws(TypeError, () => equal.call(Symbol()), "symbol"); +assert.throws(TypeError, () => equal.call(1), "1"); +assert.throws(TypeError, () => equal.call({}), "plain object"); +assert.throws(TypeError, () => equal.call(Temporal.Date), "Temporal.Date"); +assert.throws(TypeError, () => equal.call(Temporal.Date.prototype), "Temporal.Date.prototype"); diff --git a/polyfill/test/Date/prototype/equal/prop-desc.js b/polyfill/test/Date/prototype/equal/prop-desc.js new file mode 100644 index 0000000000..58acb8fac2 --- /dev/null +++ b/polyfill/test/Date/prototype/equal/prop-desc.js @@ -0,0 +1,18 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +includes: [propertyHelper.js] +---*/ + +assert.sameValue( + typeof Temporal.Date.prototype.equal, + "function", + "`typeof Date.prototype.equal` is `function`" +); + +verifyProperty(Temporal.Date.prototype, "equal", { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/polyfill/test/DateTime/prototype/equal/argument-wrong-type.js b/polyfill/test/DateTime/prototype/equal/argument-wrong-type.js new file mode 100644 index 0000000000..760341ff32 --- /dev/null +++ b/polyfill/test/DateTime/prototype/equal/argument-wrong-type.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.datetime.prototype.equal +features: [Symbol] +---*/ + +const instance = Temporal.DateTime.from({ year: 2000, month: 5, day: 2, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +assert.throws(TypeError, () => instance.equal(undefined), "undefined"); +assert.throws(TypeError, () => instance.equal(null), "null"); +assert.throws(TypeError, () => instance.equal(true), "true"); +assert.throws(TypeError, () => instance.equal(""), "empty string"); +assert.throws(TypeError, () => instance.equal(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.equal(1), "1"); +assert.throws(TypeError, () => instance.equal({}), "plain object"); +assert.throws(TypeError, () => instance.equal(Temporal.DateTime), "Temporal.DateTime"); +assert.throws(TypeError, () => instance.equal(Temporal.DateTime.prototype), "Temporal.DateTime.prototype"); diff --git a/polyfill/test/DateTime/prototype/equal/branding.js b/polyfill/test/DateTime/prototype/equal/branding.js new file mode 100644 index 0000000000..188ab18eb4 --- /dev/null +++ b/polyfill/test/DateTime/prototype/equal/branding.js @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.datetime.prototype.equal +features: [Symbol] +---*/ + +const equal = Temporal.DateTime.prototype.equal; + +assert.sameValue(typeof equal, "function"); + +assert.throws(TypeError, () => equal.call(undefined), "undefined"); +assert.throws(TypeError, () => equal.call(null), "null"); +assert.throws(TypeError, () => equal.call(true), "true"); +assert.throws(TypeError, () => equal.call(""), "empty string"); +assert.throws(TypeError, () => equal.call(Symbol()), "symbol"); +assert.throws(TypeError, () => equal.call(1), "1"); +assert.throws(TypeError, () => equal.call({}), "plain object"); +assert.throws(TypeError, () => equal.call(Temporal.DateTime), "Temporal.DateTime"); +assert.throws(TypeError, () => equal.call(Temporal.DateTime.prototype), "Temporal.DateTime.prototype"); diff --git a/polyfill/test/DateTime/prototype/equal/prop-desc.js b/polyfill/test/DateTime/prototype/equal/prop-desc.js new file mode 100644 index 0000000000..95d326ba4b --- /dev/null +++ b/polyfill/test/DateTime/prototype/equal/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +includes: [propertyHelper.js] +---*/ + +const { DateTime } = Temporal; +assert.sameValue( + typeof DateTime.prototype.equal, + "function", + "`typeof DateTime.prototype.equal` is `function`" +); + +verifyProperty(DateTime.prototype, "equal", { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/polyfill/test/MonthDay/prototype/equal/argument-wrong-type.js b/polyfill/test/MonthDay/prototype/equal/argument-wrong-type.js new file mode 100644 index 0000000000..f80c1a84ae --- /dev/null +++ b/polyfill/test/MonthDay/prototype/equal/argument-wrong-type.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.monthday.prototype.equal +features: [Symbol] +---*/ + +const instance = Temporal.MonthDay.from({ month: 5, day: 2 }); + +assert.throws(TypeError, () => instance.equal(undefined), "undefined"); +assert.throws(TypeError, () => instance.equal(null), "null"); +assert.throws(TypeError, () => instance.equal(true), "true"); +assert.throws(TypeError, () => instance.equal(""), "empty string"); +assert.throws(TypeError, () => instance.equal(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.equal(1), "1"); +assert.throws(TypeError, () => instance.equal({}), "plain object"); +assert.throws(TypeError, () => instance.equal(Temporal.MonthDay), "Temporal.MonthDay"); +assert.throws(TypeError, () => instance.equal(Temporal.MonthDay.prototype), "Temporal.MonthDay.prototype"); diff --git a/polyfill/test/MonthDay/prototype/equal/branding.js b/polyfill/test/MonthDay/prototype/equal/branding.js new file mode 100644 index 0000000000..81bcf745a5 --- /dev/null +++ b/polyfill/test/MonthDay/prototype/equal/branding.js @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.monthday.prototype.equal +features: [Symbol] +---*/ + +const equal = Temporal.MonthDay.prototype.equal; + +assert.sameValue(typeof equal, "function"); + +assert.throws(TypeError, () => equal.call(undefined), "undefined"); +assert.throws(TypeError, () => equal.call(null), "null"); +assert.throws(TypeError, () => equal.call(true), "true"); +assert.throws(TypeError, () => equal.call(""), "empty string"); +assert.throws(TypeError, () => equal.call(Symbol()), "symbol"); +assert.throws(TypeError, () => equal.call(1), "1"); +assert.throws(TypeError, () => equal.call({}), "plain object"); +assert.throws(TypeError, () => equal.call(Temporal.MonthDay), "Temporal.MonthDay"); +assert.throws(TypeError, () => equal.call(Temporal.MonthDay.prototype), "Temporal.MonthDay.prototype"); diff --git a/polyfill/test/MonthDay/prototype/equal/prop-desc.js b/polyfill/test/MonthDay/prototype/equal/prop-desc.js new file mode 100644 index 0000000000..699d4e6e5a --- /dev/null +++ b/polyfill/test/MonthDay/prototype/equal/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +includes: [propertyHelper.js] +---*/ + +const { MonthDay } = Temporal; +assert.sameValue( + typeof MonthDay.prototype.equal, + "function", + "`typeof MonthDay.prototype.equal` is `function`" +); + +verifyProperty(MonthDay.prototype, "equal", { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/polyfill/test/Time/prototype/equal/argument-wrong-type.js b/polyfill/test/Time/prototype/equal/argument-wrong-type.js new file mode 100644 index 0000000000..f72e491041 --- /dev/null +++ b/polyfill/test/Time/prototype/equal/argument-wrong-type.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.time.prototype.equal +features: [Symbol] +---*/ + +const instance = Temporal.Time.from({ minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +assert.throws(TypeError, () => instance.equal(undefined), "undefined"); +assert.throws(TypeError, () => instance.equal(null), "null"); +assert.throws(TypeError, () => instance.equal(true), "true"); +assert.throws(TypeError, () => instance.equal(""), "empty string"); +assert.throws(TypeError, () => instance.equal(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.equal(1), "1"); +assert.throws(TypeError, () => instance.equal({}), "plain object"); +assert.throws(TypeError, () => instance.equal(Temporal.Time), "Temporal.Time"); +assert.throws(TypeError, () => instance.equal(Temporal.Time.prototype), "Temporal.Time.prototype"); diff --git a/polyfill/test/Time/prototype/equal/branding.js b/polyfill/test/Time/prototype/equal/branding.js new file mode 100644 index 0000000000..c5a26815c8 --- /dev/null +++ b/polyfill/test/Time/prototype/equal/branding.js @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.time.prototype.equal +features: [Symbol] +---*/ + +const equal = Temporal.Time.prototype.equal; + +assert.sameValue(typeof equal, "function"); + +assert.throws(TypeError, () => equal.call(undefined), "undefined"); +assert.throws(TypeError, () => equal.call(null), "null"); +assert.throws(TypeError, () => equal.call(true), "true"); +assert.throws(TypeError, () => equal.call(""), "empty string"); +assert.throws(TypeError, () => equal.call(Symbol()), "symbol"); +assert.throws(TypeError, () => equal.call(1), "1"); +assert.throws(TypeError, () => equal.call({}), "plain object"); +assert.throws(TypeError, () => equal.call(Temporal.Time), "Temporal.Time"); +assert.throws(TypeError, () => equal.call(Temporal.Time.prototype), "Temporal.Time.prototype"); diff --git a/polyfill/test/Time/prototype/equal/prop-desc.js b/polyfill/test/Time/prototype/equal/prop-desc.js new file mode 100644 index 0000000000..a974058ca9 --- /dev/null +++ b/polyfill/test/Time/prototype/equal/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +includes: [propertyHelper.js] +---*/ + +const { Time } = Temporal; +assert.sameValue( + typeof Time.prototype.equal, + "function", + "`typeof Time.prototype.equal` is `function`" +); + +verifyProperty(Time.prototype, "equal", { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/polyfill/test/YearMonth/prototype/equal/argument-wrong-type.js b/polyfill/test/YearMonth/prototype/equal/argument-wrong-type.js new file mode 100644 index 0000000000..32874b8701 --- /dev/null +++ b/polyfill/test/YearMonth/prototype/equal/argument-wrong-type.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.yearmonth.prototype.equal +features: [Symbol] +---*/ + +const instance = Temporal.YearMonth.from({ year: 2000, month: 5, day: 2 }); + +assert.throws(TypeError, () => instance.equal(undefined), "undefined"); +assert.throws(TypeError, () => instance.equal(null), "null"); +assert.throws(TypeError, () => instance.equal(true), "true"); +assert.throws(TypeError, () => instance.equal(""), "empty string"); +assert.throws(TypeError, () => instance.equal(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.equal(1), "1"); +assert.throws(TypeError, () => instance.equal({}), "plain object"); +assert.throws(TypeError, () => instance.equal(Temporal.YearMonth), "Temporal.YearMonth"); +assert.throws(TypeError, () => instance.equal(Temporal.YearMonth.prototype), "Temporal.YearMonth.prototype"); diff --git a/polyfill/test/YearMonth/prototype/equal/branding.js b/polyfill/test/YearMonth/prototype/equal/branding.js new file mode 100644 index 0000000000..0343eabe9b --- /dev/null +++ b/polyfill/test/YearMonth/prototype/equal/branding.js @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.yearmonth.prototype.equal +features: [Symbol] +---*/ + +const equal = Temporal.YearMonth.prototype.equal; + +assert.sameValue(typeof equal, "function"); + +assert.throws(TypeError, () => equal.call(undefined), "undefined"); +assert.throws(TypeError, () => equal.call(null), "null"); +assert.throws(TypeError, () => equal.call(true), "true"); +assert.throws(TypeError, () => equal.call(""), "empty string"); +assert.throws(TypeError, () => equal.call(Symbol()), "symbol"); +assert.throws(TypeError, () => equal.call(1), "1"); +assert.throws(TypeError, () => equal.call({}), "plain object"); +assert.throws(TypeError, () => equal.call(Temporal.YearMonth), "Temporal.YearMonth"); +assert.throws(TypeError, () => equal.call(Temporal.YearMonth.prototype), "Temporal.YearMonth.prototype"); diff --git a/polyfill/test/YearMonth/prototype/equal/prop-desc.js b/polyfill/test/YearMonth/prototype/equal/prop-desc.js new file mode 100644 index 0000000000..1d6f596e94 --- /dev/null +++ b/polyfill/test/YearMonth/prototype/equal/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +includes: [propertyHelper.js] +---*/ + +const { YearMonth } = Temporal; +assert.sameValue( + typeof YearMonth.prototype.equal, + "function", + "`typeof YearMonth.prototype.equal` is `function`" +); + +verifyProperty(YearMonth.prototype, "equal", { + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/polyfill/test/absolute.mjs b/polyfill/test/absolute.mjs index d4e2871117..e6d46107c5 100644 --- a/polyfill/test/absolute.mjs +++ b/polyfill/test/absolute.mjs @@ -22,6 +22,15 @@ describe('Absolute', () => { it('Absolute is a Function', () => { equal(typeof Absolute, 'function'); }); + it('Absolute has a prototype', () => { + assert(Absolute.prototype); + equal(typeof Absolute.prototype, 'object'); + }); + describe('Absolute.prototype', () => { + it('Absolute.prototype.equal is a Function', () => { + equal(typeof Absolute.prototype.equal, 'function'); + }); + }); it('Absolute.fromEpochSeconds is a Function', () => { equal(typeof Absolute.fromEpochSeconds, 'function'); }); @@ -345,8 +354,8 @@ describe('Absolute', () => { equal(`${one}`, '1969-12-15T12:23:45.678900434Z')); it(`(${abs}).plus({ days: 10, nanoseconds: 800 }) = ${two}`, () => equal(`${two}`, '1970-01-04T12:23:45.678902034Z')); - it(`(${two}).minus({ days: 20, nanoseconds: 1600 }) = ${one}`, () => equal(`${three}`, `${one}`)); - it(`(${one}).plus( days: 20, nanoseconds: 1600 }) = ${two}`, () => equal(`${four}`, `${two}`)); + it(`(${two}).minus({ days: 20, nanoseconds: 1600 }) = ${one}`, () => assert(three.equal(one))); + it(`(${one}).plus( days: 20, nanoseconds: 1600 }) = ${two}`, () => assert(four.equal(two))); }); it('abs.plus(durationObj)', () => { const later = abs.plus(Temporal.Duration.from('P10DT0.000000800S')); @@ -387,14 +396,27 @@ describe('Absolute', () => { throws(() => Absolute.compare({}, abs2), TypeError); }); }); + describe('Absolute.equal works', () => { + const abs1 = Absolute.from('1963-02-13T09:36:29.123456789Z'); + const abs2 = Absolute.from('1976-11-18T15:23:30.123456789Z'); + const abs3 = Absolute.from('1981-12-15T14:34:31.987654321Z'); + it('pre epoch equal', () => assert(abs1.equal(abs1))); + it('epoch equal', () => assert(abs2.equal(abs2))); + it('cross epoch unequal', () => assert(!abs1.equal(abs2))); + it('epoch unequal', () => assert(!abs2.equal(abs3))); + it("doesn't cast argument", () => { + throws(() => abs1.equal(abs1.getEpochNanoseconds()), TypeError); + throws(() => abs1.equal({}), TypeError); + }); + }); 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}`)); - it(`(${earlier}).plus(${diff}) == (${later})`, () => equal(`${earlier.plus(diff)}`, `${later}`)); - it(`(${later}).minus(${diff}) == (${earlier})`, () => equal(`${later.minus(diff)}`, `${earlier}`)); + it(`(${earlier}).plus(${diff}) == (${later})`, () => assert(earlier.plus(diff).equal(later))); + it(`(${later}).minus(${diff}) == (${earlier})`, () => assert(later.minus(diff).equal(earlier))); it("doesn't cast argument", () => { throws(() => earlier.difference(later.toString()), TypeError); throws(() => earlier.difference({}), TypeError); diff --git a/polyfill/test/date.mjs b/polyfill/test/date.mjs index dffd0e5f6e..c864cf4051 100644 --- a/polyfill/test/date.mjs +++ b/polyfill/test/date.mjs @@ -57,6 +57,9 @@ describe('Date', () => { it('Date.prototype.difference is a Function', () => { equal(typeof Date.prototype.difference, 'function'); }); + it('Date.prototype.equal is a Function', () => { + equal(typeof Date.prototype.equal, 'function'); + }); it('Date.prototype.withTime is a Function', () => { equal(typeof Date.prototype.withTime, 'function'); }); @@ -107,7 +110,7 @@ describe('Date', () => { it(`Temporal.Date.from(${JSON.stringify(datetime)}) instanceof Temporal.date`, () => assert(Date.from(datetime) instanceof Date)); it(`Temporal.Date.from(${JSON.stringify(datetime)}) === (${fromed})`, () => - equal(`${Date.from(datetime)}`, `${fromed}`)); + assert(Date.from(datetime).equal(fromed))); }); describe('.with manipulation', () => { const original = new Date(1976, 11, 18); @@ -373,7 +376,7 @@ describe('Date', () => { it('Date.from({}) throws', () => throws(() => Date.from({}), TypeError)); it('Date.from(required prop undefined) throws', () => throws(() => Date.from({ year: undefined, month: 11, day: 18 }), TypeError)); - it('Date.from(number) is converted to string', () => equal(`${Date.from(19761118)}`, `${Date.from('19761118')}`)); + it('Date.from(number) is converted to string', () => Date.from(19761118).equal(Date.from('19761118'))); it('basic format', () => { equal(`${Date.from('19761118')}`, '1976-11-18'); equal(`${Date.from('+0019761118')}`, '1976-11-18'); @@ -426,6 +429,16 @@ describe('Date', () => { throws(() => Date.compare(d1, '2019-06-30'), TypeError); }); }); + describe('Date.equal works', () => { + const d1 = Date.from('1976-11-18'); + const d2 = Date.from('2019-06-30'); + it('equal', () => assert(d1.equal(d1))); + it('unequal', () => assert(!d1.equal(d2))); + it("doesn't cast argument", () => { + throws(() => d2.equal({ year: 1976, month: 11, day: 18 }), TypeError); + throws(() => d2.equal('1976-11-18'), TypeError); + }); + }); describe('Min/max range', () => { it('constructing from numbers', () => { throws(() => new Date(-271821, 4, 18), RangeError); diff --git a/polyfill/test/datemath.mjs b/polyfill/test/datemath.mjs index a2599e87b7..006b4f1870 100644 --- a/polyfill/test/datemath.mjs +++ b/polyfill/test/datemath.mjs @@ -12,7 +12,6 @@ import Pretty from '@pipobscure/demitasse-pretty'; const { reporter } = Pretty; import { strict as assert } from 'assert'; -const { equal } = assert; import * as Temporal from 'tc39-temporal'; @@ -71,10 +70,8 @@ function buildSub(one, two, largestUnits) { largestUnits.forEach((largestUnit) => { describe(`< ${one} : ${two} (${largestUnit})>`, () => { const dif = two.difference(one, { largestUnit }); - it(`(${one}).plus(${dif}) => ${two}`, () => - equal(`${one.plus(dif, { disambiguation: 'reject' })}`, `${two}`, `(${one}).plus(${dif}) => ${two}`)); - it(`(${two}).minus(${dif}) => ${one}`, () => - equal(`${two.minus(dif, { disambiguation: 'reject' })}`, `${one}`, `(${two}).minus(${dif}) => ${one}`)); + it(`(${one}).plus(${dif}) => ${two}`, () => assert(one.plus(dif, { disambiguation: 'reject' }).equal(two))); + it(`(${two}).minus(${dif}) => ${one}`, () => assert(two.minus(dif, { disambiguation: 'reject' }).equal(one))); }); }); } diff --git a/polyfill/test/datetime.mjs b/polyfill/test/datetime.mjs index 73745815e7..aa1d766f52 100644 --- a/polyfill/test/datetime.mjs +++ b/polyfill/test/datetime.mjs @@ -75,6 +75,9 @@ describe('DateTime', () => { it('DateTime.prototype.difference is a Function', () => { equal(typeof DateTime.prototype.difference, 'function'); }); + it('DateTime.prototype.equal is a Function', () => { + equal(typeof DateTime.prototype.equal, 'function'); + }); it('DateTime.prototype.inTimeZone is a Function', () => { equal(typeof DateTime.prototype.inTimeZone, 'function'); }); @@ -269,6 +272,16 @@ describe('DateTime', () => { throws(() => DateTime.compare('2019-10-29T10:46:38.271986102', dt2), TypeError); }); }); + describe('DateTime.equal() works', () => { + const dt1 = DateTime.from('1976-11-18T15:23:30.123456789'); + const dt2 = DateTime.from('2019-10-29T10:46:38.271986102'); + it('equal', () => assert(dt1.equal(dt1))); + it('unequal', () => assert(!dt1.equal(dt2))); + it("doesn't cast argument", () => { + throws(() => dt2.equal({ year: 1976, month: 11, day: 18, hour: 15 }), TypeError); + throws(() => dt2.equal('1976-11-18T15:23:30.123456789'), TypeError); + }); + }); describe('date/time maths', () => { const earlier = DateTime.from('1976-11-18T15:23:30.123456789'); const later = DateTime.from('2019-10-29T10:46:38.271986102'); @@ -276,8 +289,8 @@ describe('DateTime', () => { const diff = earlier.difference(later, { largestUnit }); it(`(${earlier}).difference(${later}, ${largestUnit}) == (${later}).difference(${earlier}, ${largestUnit})`, () => equal(`${later.difference(earlier, { largestUnit })}`, `${diff}`)); - it(`(${earlier}).plus(${diff}) == (${later})`, () => equal(`${earlier.plus(diff)}`, `${later}`)); - it(`(${later}).minus(${diff}) == (${earlier})`, () => equal(`${later.minus(diff)}`, `${earlier}`)); + it(`(${earlier}).plus(${diff}) == (${later})`, () => earlier.plus(diff).equal(later)); + it(`(${later}).minus(${diff}) == (${earlier})`, () => later.minus(diff).equal(earlier)); }); }); describe('date/time maths: hours overflow', () => { @@ -376,7 +389,7 @@ describe('DateTime', () => { equal(`${DateTime.from('2016-12-31T23:59:60')}`, '2016-12-31T23:59:59'); }); it('DateTime.from(number) is converted to string', () => - equal(`${DateTime.from(19761118)}`, `${DateTime.from('19761118')}`)); + assert(DateTime.from(19761118).equal(DateTime.from('19761118')))); describe('Disambiguation', () => { const bad = { year: 2019, month: 1, day: 32 }; it('reject', () => throws(() => DateTime.from(bad, { disambiguation: 'reject' }), RangeError)); diff --git a/polyfill/test/monthday.mjs b/polyfill/test/monthday.mjs index 2f8dc0233f..961d9b2af1 100644 --- a/polyfill/test/monthday.mjs +++ b/polyfill/test/monthday.mjs @@ -20,6 +20,9 @@ describe('MonthDay', () => { equal(typeof MonthDay.prototype, 'object'); }); describe('MonthDay.prototype', () => { + it('MonthDay.prototype.equal is a Function', () => { + equal(typeof MonthDay.prototype.equal, 'function'); + }); it('MonthDay.prototype.getFields is a Function', () => { equal(typeof MonthDay.prototype.getFields, 'function'); }); @@ -46,7 +49,7 @@ describe('MonthDay', () => { it('MonthDay.from(required prop undefined) throws', () => throws(() => MonthDay.from({ month: undefined, day: 15 }), TypeError)); it('MonthDay.from(number) is converted to string', () => - equal(`${MonthDay.from(1201)}`, `${MonthDay.from('12-01')}`)); + assert(MonthDay.from(1201).equal(MonthDay.from('12-01')))); it('basic format', () => { equal(`${MonthDay.from('1118')}`, '11-18'); }); @@ -123,6 +126,16 @@ describe('MonthDay', () => { equal(`${md.with({ month: 999999 * 12 }, { disambiguation: 'balance' })}`, '12-01'); }); }); + describe('MonthDay.equal()', () => { + const md1 = MonthDay.from('01-22'); + const md2 = MonthDay.from('12-15'); + it('equal', () => assert(md1.equal(md1))); + it('unequal', () => assert(!md1.equal(md2))); + it("doesn't cast argument", () => { + throws(() => md1.equal('01-22'), TypeError); + throws(() => md1.equal({ month: 1, day: 22 }), TypeError); + }); + }); describe('MonthDay.withYear()', () => { const md = MonthDay.from('01-22'); it('takes a number argument', () => { @@ -153,11 +166,11 @@ describe('MonthDay', () => { }); it('as input to from()', () => { const md2 = MonthDay.from(fields); - equal(`${md1}`, `${md2}`); + assert(md1.equal(md2)); }); it('as input to with()', () => { const md2 = MonthDay.from('06-30').with(fields); - equal(`${md1}`, `${md2}`); + assert(md1.equal(md2)); }); }); }); diff --git a/polyfill/test/time.mjs b/polyfill/test/time.mjs index e0b09e735a..c1861aeab9 100644 --- a/polyfill/test/time.mjs +++ b/polyfill/test/time.mjs @@ -57,6 +57,9 @@ describe('Time', () => { it('Time.prototype.difference is a Function', () => { equal(typeof Time.prototype.difference, 'function'); }); + it('Time.prototype.equal is a Function', () => { + equal(typeof Time.prototype.equal, 'function'); + }); it('Time.prototype.withDate is a Function', () => { equal(typeof Time.prototype.withDate, 'function'); }); @@ -321,6 +324,16 @@ describe('Time', () => { throws(() => Time.compare(t1, '16:34'), TypeError); }); }); + describe('time.equal() works', () => { + const t1 = Time.from('08:44:15.321'); + const t2 = Time.from('14:23:30.123'); + it('equal', () => assert(t1.equal(t1))); + it('unequal', () => assert(!t1.equal(t2))); + it("doesn't cast argument", () => { + throws(() => t1.equal('08:44:15.321'), TypeError); + throws(() => t1.equal({ hour: 8, minute: 44, second: 15, millisecond: 321 }), TypeError); + }); + }); describe('time.plus() works', () => { const time = new Time(15, 23, 30, 123, 456, 789); it(`(${time}).plus({ hours: 16 })`, () => { @@ -536,7 +549,7 @@ describe('Time', () => { it(`Temporal.Time.from(${JSON.stringify(datetime)}) instanceof Temporal.Time`, () => assert(Time.from(datetime) instanceof Time)); it(`Temporal.Time.from(${JSON.stringify(datetime)}) === ${fromed}`, () => - equal(`${Time.from(datetime)}`, `${fromed}`)); + assert(Time.from(datetime).equal(fromed))); const iso = '20:18:32'; it(`Temporal.Time.from("${iso}") === (${iso})`, () => equal(`${Time.from(iso)}`, iso)); diff --git a/polyfill/test/yearmonth.mjs b/polyfill/test/yearmonth.mjs index 8196a3b616..8abd1fdfdf 100644 --- a/polyfill/test/yearmonth.mjs +++ b/polyfill/test/yearmonth.mjs @@ -23,6 +23,9 @@ describe('YearMonth', () => { it('YearMonth.prototype.difference is a Function', () => { equal(typeof YearMonth.prototype.difference, 'function'); }); + it('YearMonth.prototype.equal is a Function', () => { + equal(typeof YearMonth.prototype.equal, 'function'); + }); it('YearMonth.prototype.getFields is a Function', () => { equal(typeof YearMonth.prototype.getFields, 'function'); }); @@ -64,7 +67,7 @@ describe('YearMonth', () => { it('YearMonth.from(required prop undefined) throws', () => throws(() => YearMonth.from({ year: undefined, month: 6 }), TypeError)); it('YearMonth.from(number) is converted to string', () => - equal(`${YearMonth.from(201906)}`, `${YearMonth.from('201906')}`)); + assert(YearMonth.from(201906).equal(YearMonth.from('201906')))); it('basic format', () => { equal(`${YearMonth.from('197611')}`, '1976-11'); equal(`${YearMonth.from('+00197611')}`, '1976-11'); @@ -128,14 +131,24 @@ describe('YearMonth', () => { throws(() => YearMonth.compare(nov94, '2013-06'), TypeError); }); }); + describe('YearMonth.equal() works', () => { + const nov94 = YearMonth.from('1994-11'); + const jun13 = YearMonth.from('2013-06'); + it('equal', () => assert(nov94.equal(nov94))); + it('unequal', () => assert(!nov94.equal(jun13))); + it("doesn't cast argument", () => { + throws(() => nov94.equal({ year: 1994, month: 11 }), TypeError); + throws(() => nov94.equal('1994-11'), TypeError); + }); + }); 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)}`)); - it(`${nov94}.plus(${diff}) == ${jun13}`, () => equal(`${nov94.plus(diff)}`, `${jun13}`)); - it(`${jun13}.minus(${diff}) == ${nov94}`, () => equal(`${jun13.minus(diff)}`, `${nov94}`)); + it(`${nov94}.plus(${diff}) == ${jun13}`, () => nov94.plus(diff).equal(jun13)); + it(`${jun13}.minus(${diff}) == ${nov94}`, () => jun13.minus(diff).equal(nov94)); it("doesn't cast argument", () => { throws(() => nov94.difference({ year: 2013, month: 6 }), TypeError); throws(() => nov94.difference('2013-06'), TypeError); diff --git a/spec/absolute.html b/spec/absolute.html index 9e2710ef15..816a69b3e5 100644 --- a/spec/absolute.html +++ b/spec/absolute.html @@ -298,6 +298,21 @@

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

+ +

Temporal.Absolute.prototype.equal ( _other_ )

+

+ The `equal` method takes one argument _other_. + The following steps are taken: +

+ + 1. Let _absolute_ be the *this* value. + 1. Perform ? RequireInternalSlot(_absolute_, [[InitializedTemporalAbsolute]]). + 1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalAbsolute]]). + 1. If _absolute_.[[Nanoseconds]] ≠ _other_.[[Nanoseconds]], return *false*. + 1. Return *true*. + +
+

Temporal.Absolute.prototype.toString ( [ _temporalTimeZoneLike_ ] )

diff --git a/spec/date.html b/spec/date.html index 3870e6a597..8e30167ec7 100644 --- a/spec/date.html +++ b/spec/date.html @@ -360,6 +360,23 @@

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

+ +

Temporal.Date.prototype.equal ( _other_ )

+

+ The `equal` method takes one argument _other_. + The following steps are taken: +

+ + 1. Let _temporalDate_ be the *this* value. + 1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]). + 1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalDate]]). + 1. If _temporalDate_.[[Year]] ≠ _other_.[[Year]], return *false*. + 1. If _temporalDate_.[[Month]] ≠ _other_.[[Month]], return *false*. + 1. If _temporalDate_.[[Day]] ≠ _other_.[[Day]], return *false*. + 1. Return *true*. + +
+

Temporal.Date.prototype.withTime ( _temporalTime_ )

diff --git a/spec/datetime.html b/spec/datetime.html index c21622e91f..3ab61a425b 100644 --- a/spec/datetime.html +++ b/spec/datetime.html @@ -447,6 +447,29 @@

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

+ +

Temporal.DateTime.prototype.equal ( _other_ )

+

+ The `equal` method takes one argument _other_. + The following steps are taken: +

+ + 1. Let _dateTime_ be the *this* value. + 1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]). + 1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalDateTime]]). + 1. If _dateTime_.[[Year]] ≠ _other_.[[Year]], return *false*. + 1. If _dateTime_.[[Month]] ≠ _other_.[[Month]], return *false*. + 1. If _dateTime_.[[Day]] ≠ _other_.[[Day]], return *false*. + 1. If _dateTime_.[[Hour]] ≠ _other_.[[Hour]], return *false*. + 1. If _dateTime_.[[Minute]] ≠ _other_.[[Minute]], return *false*. + 1. If _dateTime_.[[Second]] ≠ _other_.[[Second]], return *false*. + 1. If _dateTime_.[[Millisecond]] ≠ _other_.[[Millisecond]], return *false*. + 1. If _dateTime_.[[Microsecond]] ≠ _other_.[[Microsecond]], return *false*. + 1. If _dateTime_.[[Nanosecond]] ≠ _other_.[[Nanosecond]], return *false*. + 1. Return *true*. + +
+

Temporal.DateTime.prototype.toString ( )

diff --git a/spec/monthday.html b/spec/monthday.html index 08a473819e..4830101090 100644 --- a/spec/monthday.html +++ b/spec/monthday.html @@ -152,6 +152,22 @@

Temporal.MonthDay.prototype.with ( _temporalMonthDayLike_ [ , _options_ ] )< + +

Temporal.MonthDay.prototype.equal ( _other_ )

+

+ The `equal` method takes one argument _other_. + The following steps are taken: +

+ + 1. Let _monthDay_ be the *this* value. + 1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]). + 1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalMonthDay]]). + 1. If _monthDay_.[[Month]] ≠ _other_.[[Month]], return *false*. + 1. If _monthDay_.[[Day]] ≠ _other_.[[Day]], return *false*. + 1. Return *true*. + +
+

Temporal.MonthDay.prototype.toString ( )

diff --git a/spec/time.html b/spec/time.html index 8259ba4178..47efb79dc7 100644 --- a/spec/time.html +++ b/spec/time.html @@ -305,6 +305,26 @@

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

+ +

Temporal.Time.prototype.equal ( _other_ )

+

+ The `equal` method takes one argument _other_. + The following steps are taken: +

+ + 1. Let _temporalTime_ be the *this* value. + 1. Perform ? RequireInternalSlot(_temporalTime_, [[InitializedTemporalTime]]). + 1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalTime]]). + 1. If _temporalTime_.[[Hour]] ≠ _other_.[[Hour]], return *false*. + 1. If _temporalTime_.[[Minute]] ≠ _other_.[[Minute]], return *false*. + 1. If _temporalTime_.[[Second]] ≠ _other_.[[Second]], return *false*. + 1. If _temporalTime_.[[Millisecond]] ≠ _other_.[[Millisecond]], return *false*. + 1. If _temporalTime_.[[Microsecond]] ≠ _other_.[[Microsecond]], return *false*. + 1. If _temporalTime_.[[Nanosecond]] ≠ _other_.[[Nanosecond]], return *false*. + 1. Return *true*. + +
+

Temporal.Time.prototype.withDate ( _temporalDate_ )

diff --git a/spec/yearmonth.html b/spec/yearmonth.html index 71005141f0..77c2b3a573 100644 --- a/spec/yearmonth.html +++ b/spec/yearmonth.html @@ -271,6 +271,22 @@

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

+ +

Temporal.YearMonth.prototype.equal ( _other_ )

+

+ The `equal` method takes one argument _other_. + The following steps are taken: +

+ + 1. Let _yearMonth_ be the *this* value. + 1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]). + 1. Perform ? RequireInternalSlot(_other_, [[InitializedTemporalYearMonth]]). + 1. If _yearMonth_.[[Year]] ≠ _other_.[[Year]], return *false*. + 1. If _yearMonth_.[[Month]] ≠ _other_.[[Month]], return *false*. + 1. Return *true*. + +
+

Temporal.YearMonth.prototype.toString ( )