Temporal: Add tests for new yearOfWeek API

To be presented for consensus in the November/December TC39 meeting. This
adds tests for a 'yearOfWeek' getter to PlainDate, PlainDateTime, and
ZonedDateTime, for use alongside 'weekOfYear', and tests for a
corresponding method to Calendar.

The tests are basically the existing tests of 'weekOfYear' adapted.

Temporal issue: https://github.com/tc39/proposal-temporal/issues/2405
This commit is contained in:
Philip Chimento 2022-10-20 17:50:49 -07:00 committed by Philip Chimento
parent 338063f80f
commit 3775b4774b
58 changed files with 1509 additions and 0 deletions

View File

@ -0,0 +1,16 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Calendar.dateFromFields method is called with a null-prototype fields object
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
const instance = new Temporal.Calendar("iso8601");
const arg = { year: 2000, month: 5, day: 2, calendar };
instance.yearOfWeek(arg);
assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar");

View File

@ -0,0 +1,27 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
When calendar.fields is undefined, yearOfWeek() doesn't perform an
observable array iteration to convert the property bag to PlainDate
features: [Temporal]
---*/
const calendar = new Temporal.Calendar("iso8601");
calendar.fields = undefined;
const instance = new Temporal.Calendar("iso8601");
// Detect observable array iteration:
const oldIterator = Array.prototype[Symbol.iterator];
Array.prototype[Symbol.iterator] = function () {
throw new Test262Error(`array shouldn't be iterated: ${new Error().stack}`);
};
const arg = { year: 1981, month: 12, day: 15, calendar };
instance.yearOfWeek(arg);
Array.prototype[Symbol.iterator] = oldIterator;

View File

@ -0,0 +1,26 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Leap second is a valid ISO string for PlainDate
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
let arg = "2016-12-31T23:59:60";
const result1 = instance.yearOfWeek(arg);
assert.sameValue(
result1,
2016,
"leap second is a valid ISO string for PlainDate"
);
arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
const result2 = instance.yearOfWeek(arg);
assert.sameValue(
result2,
2016,
"second: 60 is ignored in property bag for PlainDate"
);

View File

@ -0,0 +1,29 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: A number is converted to a string, then to Temporal.PlainDate
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const arg = 19761118;
const result = instance.yearOfWeek(arg);
assert.sameValue(result, 1976, "19761118 is a valid ISO string for PlainDate");
const numbers = [
1,
-19761118,
1234567890,
];
for (const arg of numbers) {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
`Number ${arg} does not convert to a valid ISO string for PlainDate`
);
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
A Temporal.Calendar instance passed to yearOfWeek() in a property bag does
not have its 'calendar' property observably checked
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const calendar = new Temporal.Calendar("iso8601");
Object.defineProperty(calendar, "calendar", {
get() {
throw new Test262Error("calendar.calendar should not be accessed");
},
});
let arg = { year: 1976, monthCode: "M11", day: 18, calendar };
instance.yearOfWeek(arg);
arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } };
instance.yearOfWeek(arg);

View File

@ -0,0 +1,28 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Leap second is a valid ISO string for a calendar in a property bag
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const calendar = "2016-12-31T23:59:60";
let arg = { year: 1976, monthCode: "M11", day: 18, calendar };
const result1 = instance.yearOfWeek(arg);
assert.sameValue(
result1,
1976,
"leap second is a valid ISO string for calendar"
);
arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } };
const result2 = instance.yearOfWeek(arg);
assert.sameValue(
result2,
1976,
"leap second is a valid ISO string for calendar (nested property)"
);

View File

@ -0,0 +1,41 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: A number as calendar in a property bag is converted to a string, then to a calendar
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const calendar = 19970327;
let arg = { year: 1976, monthCode: "M11", day: 18, calendar };
const result1 = instance.yearOfWeek(arg);
assert.sameValue(result1, 1976, "19970327 is a valid ISO string for calendar");
arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } };
const result2 = instance.yearOfWeek(arg);
assert.sameValue(result2, 1976, "19970327 is a valid ISO string for calendar (nested property)");
const numbers = [
1,
-19970327,
1234567890,
];
for (const calendar of numbers) {
let arg = { year: 1976, monthCode: "M11", day: 18, calendar };
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
`Number ${calendar} does not convert to a valid ISO string for calendar`
);
arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } };
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
`Number ${calendar} does not convert to a valid ISO string for calendar (nested property)`
);
}

View File

@ -0,0 +1,16 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: A calendar ID is valid input for Calendar
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const calendar = "iso8601";
const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
const result = instance.yearOfWeek(arg);
assert.sameValue(result, 1976, `Calendar created from string "${calendar}"`);

View File

@ -0,0 +1,47 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Appropriate error thrown when a calendar property from a property bag cannot
be converted to a calendar object or string
features: [BigInt, Symbol, Temporal]
---*/
const timeZone = new Temporal.TimeZone("UTC");
const instance = new Temporal.Calendar("iso8601");
const rangeErrorTests = [
[null, "null"],
[true, "boolean"],
["", "empty string"],
[1, "number that doesn't convert to a valid ISO string"],
[1n, "bigint"],
];
for (const [calendar, description] of rangeErrorTests) {
let arg = { year: 2019, monthCode: "M11", day: 1, calendar };
assert.throws(RangeError, () => instance.yearOfWeek(arg), `${description} does not convert to a valid ISO string`);
arg = { year: 2019, monthCode: "M11", day: 1, calendar: { calendar } };
assert.throws(RangeError, () => instance.yearOfWeek(arg), `${description} does not convert to a valid ISO string (nested property)`);
}
const typeErrorTests = [
[Symbol(), "symbol"],
[{}, "plain object"], // TypeError due to missing dateFromFields()
[Temporal.Calendar, "Temporal.Calendar, object"], // ditto
[Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields()
];
for (const [calendar, description] of typeErrorTests) {
let arg = { year: 2019, monthCode: "M11", day: 1, calendar };
assert.throws(TypeError, () => instance.yearOfWeek(arg), `${description} is not a valid property bag and does not convert to a string`);
arg = { year: 2019, monthCode: "M11", day: 1, calendar: { calendar } };
assert.throws(TypeError, () => instance.yearOfWeek(arg), `${description} is not a valid property bag and does not convert to a string (nested property)`);
}
const arg = { year: 2019, monthCode: "M11", day: 1, calendar: { calendar: undefined } };
assert.throws(RangeError, () => instance.yearOfWeek(arg), `nested undefined calendar property is always a RangeError`);

View File

@ -0,0 +1,24 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Negative zero, as an extended year, is rejected
features: [Temporal, arrow-function]
---*/
const invalidStrings = [
"-000000-10-31",
"-000000-10-31T17:45",
"-000000-10-31T17:45Z",
"-000000-10-31T17:45+01:00",
"-000000-10-31T17:45+00:00[UTC]",
];
const instance = new Temporal.Calendar("iso8601");
invalidStrings.forEach((arg) => {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
"reject minus zero as extended year"
);
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Various forms of calendar annotation; critical flag has no effect
features: [Temporal]
---*/
const tests = [
["2000-05-02[u-ca=iso8601]", "without time or time zone"],
["2000-05-02[UTC][u-ca=iso8601]", "with time zone and no time"],
["2000-05-02T15:23[u-ca=iso8601]", "without time zone"],
["2000-05-02T15:23[UTC][u-ca=iso8601]", "with time zone"],
["2000-05-02T15:23[!u-ca=iso8601]", "with ! and no time zone"],
["2000-05-02T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"],
["2000-05-02T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"],
["2000-05-02T15:23[u-ca=iso8601][!u-ca=discord]", "second annotation ignored even with !"],
];
const instance = new Temporal.Calendar("iso8601");
tests.forEach(([arg, description]) => {
const result = instance.yearOfWeek(arg);
assert.sameValue(
result,
2000,
`calendar annotation (${description})`
);
});

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Unknown annotations with critical flag are rejected
features: [Temporal]
---*/
const invalidStrings = [
"1970-01-01[!foo=bar]",
"1970-01-01T00:00[!foo=bar]",
"1970-01-01T00:00[UTC][!foo=bar]",
"1970-01-01T00:00[u-ca=iso8601][!foo=bar]",
"1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]",
"1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
];
const instance = new Temporal.Calendar("iso8601");
invalidStrings.forEach((arg) => {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
`reject unknown annotation with critical flag: ${arg}`
);
});

View File

@ -0,0 +1,61 @@
// Copyright (C) 2022 Igalia S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
RangeError thrown if an invalid ISO string (or syntactically valid ISO string
that is not supported) is used as a PlainDate
features: [Temporal, arrow-function]
---*/
const invalidStrings = [
// invalid ISO strings:
"",
"invalid iso8601",
"2020-01-00",
"2020-01-32",
"2020-02-30",
"2021-02-29",
"2020-00-01",
"2020-13-01",
"2020-01-01T",
"2020-01-01T25:00:00",
"2020-01-01T01:60:00",
"2020-01-01T01:60:61",
"2020-01-01junk",
"2020-01-01T00:00:00junk",
"2020-01-01T00:00:00+00:00junk",
"2020-01-01T00:00:00+00:00[UTC]junk",
"2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk",
"02020-01-01",
"2020-001-01",
"2020-01-001",
"2020-01-01T001",
"2020-01-01T01:001",
"2020-01-01T01:01:001",
// valid, but forms not supported in Temporal:
"2020-W01-1",
"2020-001",
"+0002020-01-01",
// valid, but this calendar must not exist:
"2020-01-01[u-ca=notexist]",
// may be valid in other contexts, but insufficient information for PlainDate:
"2020-01",
"+002020-01",
"01-01",
"2020-W01",
"P1Y",
"-P12Y",
// valid, but outside the supported range:
"-999999-01-01",
"+999999-01-01",
];
const instance = new Temporal.Calendar("iso8601");
for (const arg of invalidStrings) {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
`"${arg}" should not be a valid ISO string for a PlainDate`
);
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: More than one time zone annotation is not syntactical
features: [Temporal]
---*/
const invalidStrings = [
"1970-01-01[UTC][UTC]",
"1970-01-01T00:00[UTC][UTC]",
"1970-01-01T00:00[!UTC][UTC]",
"1970-01-01T00:00[UTC][!UTC]",
"1970-01-01T00:00[UTC][u-ca=iso8601][UTC]",
"1970-01-01T00:00[UTC][foo=bar][UTC]",
];
const instance = new Temporal.Calendar("iso8601");
invalidStrings.forEach((arg) => {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
`reject more than one time zone annotation: ${arg}`
);
});

View File

@ -0,0 +1,26 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Time separator in string argument can vary
features: [Temporal]
---*/
const tests = [
["2000-05-02T15:23", "uppercase T"],
["2000-05-02t15:23", "lowercase T"],
["2000-05-02 15:23", "space between date and time"],
];
const instance = new Temporal.Calendar("iso8601");
tests.forEach(([arg, description]) => {
const result = instance.yearOfWeek(arg);
assert.sameValue(
result,
2000,
`variant time separators (${description})`
);
});

View File

@ -0,0 +1,39 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Various forms of time zone annotation; critical flag has no effect
features: [Temporal]
---*/
const tests = [
["2000-05-02[Asia/Kolkata]", "named, with no time and no offset"],
["2000-05-02[!Europe/Vienna]", "named, with !, no time, and no offset"],
["2000-05-02[+00:00]", "numeric, with no time and no offset"],
["2000-05-02[!-02:30]", "numeric, with !, no time, and no offset"],
["2000-05-02+00:00[UTC]", "named, with offset and no time"],
["2000-05-02+00:00[!Africa/Abidjan]", "named, with offset, !, and no time"],
["2000-05-02+00:00[-08:00]", "numeric, with offset and no time"],
["2000-05-02+00:00[!+01:00]", "numeric, with offset, !, and no time"],
["2000-05-02T15:23[America/Sao_Paulo]", "named, with no offset"],
["2000-05-02T15:23[!Asia/Tokyo]", "named, with ! and no offset"],
["2000-05-02T15:23[-02:30]", "numeric, with no offset"],
["2000-05-02T15:23[!+00:00]", "numeric, with ! and no offset"],
["2000-05-02T15:23+00:00[America/New_York]", "named, with offset"],
["2000-05-02T15:23+00:00[!UTC]", "named, with offset and !"],
["2000-05-02T15:23+00:00[+01:00]", "numeric, with offset"],
["2000-05-02T15:23+00:00[!-08:00]", "numeric, with offset and !"],
];
const instance = new Temporal.Calendar("iso8601");
tests.forEach(([arg, description]) => {
const result = instance.yearOfWeek(arg);
assert.sameValue(
result,
2000,
`time zone annotation (${description})`
);
});

View File

@ -0,0 +1,29 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Various forms of unknown annotation
features: [Temporal]
---*/
const tests = [
["2000-05-02[foo=bar]", "without time"],
["2000-05-02T15:23[foo=bar]", "alone"],
["2000-05-02T15:23[UTC][foo=bar]", "with time zone"],
["2000-05-02T15:23[u-ca=iso8601][foo=bar]", "with calendar"],
["2000-05-02T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
["2000-05-02T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
];
const instance = new Temporal.Calendar("iso8601");
tests.forEach(([arg, description]) => {
const result = instance.yearOfWeek(arg);
assert.sameValue(
result,
2000,
`unknown annotation (${description})`
);
});

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: RangeError thrown if a string with UTC designator is used as a PlainDate
features: [Temporal, arrow-function]
---*/
const invalidStrings = [
"2019-10-01T09:00:00Z",
"2019-10-01T09:00:00Z[UTC]",
];
const instance = new Temporal.Calendar("iso8601");
invalidStrings.forEach((arg) => {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
"String with UTC designator should not be valid as a PlainDate"
);
});

View File

@ -0,0 +1,36 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Temporal.Calendar.prototype.yearOfWeek will take an ISO 8601 date string and
return the ISO week calendar year of that date.
features: [Temporal]
---*/
const cal = new Temporal.Calendar("iso8601");
// The following week calendar years are taken from the table "Examples of
// contemporary dates around New Year's Day" from
// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar
assert.sameValue(cal.yearOfWeek("1977-01-01"), 1976, "1977-01-01 is in yearOfWeek 1976");
assert.sameValue(cal.yearOfWeek("1977-01-02"), 1976, "1977-01-02 is in yearOfWeek 1976");
assert.sameValue(cal.yearOfWeek("1977-12-31"), 1977, "1977-12-31 is in yearOfWeek 1977");
assert.sameValue(cal.yearOfWeek("1978-01-01"), 1977, "1978-01-01 is in yearOfWeek 1977");
assert.sameValue(cal.yearOfWeek("1978-01-02"), 1978, "1978-01-02 is in yearOfWeek 1978");
assert.sameValue(cal.yearOfWeek("1978-12-31"), 1978, "1978-12-31 is in yearOfWeek 1978");
assert.sameValue(cal.yearOfWeek("1979-01-01"), 1979, "1979-01-01 is in yearOfWeek 1979");
assert.sameValue(cal.yearOfWeek("1979-12-30"), 1979, "1979-12-30 is in yearOfWeek 1979");
assert.sameValue(cal.yearOfWeek("1979-12-31"), 1980, "1979-12-31 is in yearOfWeek 1980");
assert.sameValue(cal.yearOfWeek("1980-01-01"), 1980, "1980-01-01 is in yearOfWeek 1980");
assert.sameValue(cal.yearOfWeek("1980-12-28"), 1980, "1980-12-28 is in yearOfWeek 1980");
assert.sameValue(cal.yearOfWeek("1980-12-29"), 1981, "1980-12-29 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1980-12-30"), 1981, "1980-12-30 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1980-12-31"), 1981, "1980-12-31 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1981-01-01"), 1981, "1981-01-01 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1981-12-31"), 1981, "1981-12-31 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1982-01-01"), 1981, "1982-01-01 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1982-01-02"), 1981, "1982-01-02 is in yearOfWeek 1981");
assert.sameValue(cal.yearOfWeek("1982-01-03"), 1981, "1982-01-03 is in yearOfWeek 1981");

View File

@ -0,0 +1,36 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Appropriate error thrown when argument cannot be converted to a valid string
or property bag for PlainDate
features: [BigInt, Symbol, Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const rangeErrorTests = [
[undefined, "undefined"],
[null, "null"],
[true, "boolean"],
["", "empty string"],
[1, "number that doesn't convert to a valid ISO string"],
[1n, "bigint"],
];
for (const [arg, description] of rangeErrorTests) {
assert.throws(RangeError, () => instance.yearOfWeek(arg), `${description} does not convert to a valid ISO string`);
}
const typeErrorTests = [
[Symbol(), "symbol"],
[{}, "plain object"],
[Temporal.PlainDate, "Temporal.PlainDate, object"],
[Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"],
];
for (const [arg, description] of typeErrorTests) {
assert.throws(TypeError, () => instance.yearOfWeek(arg), `${description} is not a valid property bag and does not convert to a string`);
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: An exception from TimeZone#getOffsetNanosecondsFor() is propagated.
features: [Temporal]
---*/
class TZ extends Temporal.TimeZone {
constructor() { super("UTC") }
getOffsetNanosecondsFor() { throw new Test262Error() }
}
const tz = new TZ();
const arg = new Temporal.ZonedDateTime(0n, tz);
const instance = new Temporal.Calendar("iso8601");
assert.throws(Test262Error, () => instance.yearOfWeek(arg));

View File

@ -0,0 +1,37 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Getters are not called when converting a ZonedDateTime to a PlainDate.
includes: [compareArray.js]
features: [Temporal]
---*/
const actual = [];
const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.ZonedDateTime.prototype);
const getters = ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "calendar"];
for (const property of getters) {
Object.defineProperty(Temporal.ZonedDateTime.prototype, property, {
get() {
actual.push(`get ${property}`);
const value = prototypeDescrs[property].get.call(this);
return {
toString() {
actual.push(`toString ${property}`);
return value.toString();
},
valueOf() {
actual.push(`valueOf ${property}`);
return value;
},
};
},
});
}
const arg = new Temporal.ZonedDateTime(0n, "UTC");
const instance = new Temporal.Calendar("iso8601");
instance.yearOfWeek(arg);
assert.compareArray(actual, []);

View File

@ -0,0 +1,16 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds
features: [Temporal]
includes: [temporalHelpers.js]
---*/
[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => {
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
const calendar = new Temporal.Calendar("iso8601");
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
assert.throws(RangeError, () => calendar.yearOfWeek(datetime));
});

View File

@ -0,0 +1,20 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable
features: [BigInt, Symbol, Temporal, arrow-function]
---*/
[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => {
const timeZone = new Temporal.TimeZone("UTC");
const calendar = new Temporal.Calendar("iso8601");
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
timeZone.getOffsetNanosecondsFor = notCallable;
assert.throws(
TypeError,
() => calendar.yearOfWeek(datetime),
`Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
);
});

View File

@ -0,0 +1,16 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: RangeError thrown if time zone reports an offset that is out of range
features: [Temporal]
includes: [temporalHelpers.js]
---*/
[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => {
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
const calendar = new Temporal.Calendar("iso8601");
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
assert.throws(RangeError, () => calendar.yearOfWeek(datetime));
});

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: TypeError thrown if time zone reports an offset that is not a Number
features: [Temporal]
includes: [temporalHelpers.js]
---*/
[
undefined,
null,
true,
"+01:00",
Symbol(),
3600_000_000_000n,
{},
{ valueOf() { return 3600_000_000_000; } },
].forEach((wrongOffset) => {
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
const calendar = new Temporal.Calendar("iso8601");
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
assert.throws(TypeError, () => calendar.yearOfWeek(datetime));
});

View File

@ -0,0 +1,16 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Basic tests for yearOfWeek().
features: [Temporal]
---*/
const iso = Temporal.Calendar.from("iso8601");
const res = 1994;
assert.sameValue(iso.yearOfWeek(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate");
assert.sameValue(iso.yearOfWeek(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime");
assert.sameValue(iso.yearOfWeek({ year: 1994, month: 11, day: 5 }), res, "property bag");
assert.sameValue(iso.yearOfWeek("1994-11-05"), res, "string");
assert.throws(TypeError, () => iso.yearOfWeek({ year: 2000 }), "property bag with missing properties");

View File

@ -0,0 +1,24 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Throw a TypeError if the receiver is invalid
features: [Symbol, Temporal]
---*/
const yearOfWeek = Temporal.Calendar.prototype.yearOfWeek;
assert.sameValue(typeof yearOfWeek, "function");
const args = [new Temporal.PlainDate(2021, 7, 20)];
assert.throws(TypeError, () => yearOfWeek.apply(undefined, args), "undefined");
assert.throws(TypeError, () => yearOfWeek.apply(null, args), "null");
assert.throws(TypeError, () => yearOfWeek.apply(true, args), "true");
assert.throws(TypeError, () => yearOfWeek.apply("", args), "empty string");
assert.throws(TypeError, () => yearOfWeek.apply(Symbol(), args), "symbol");
assert.throws(TypeError, () => yearOfWeek.apply(1, args), "1");
assert.throws(TypeError, () => yearOfWeek.apply({}, args), "plain object");
assert.throws(TypeError, () => yearOfWeek.apply(Temporal.Calendar, args), "Temporal.Calendar");
assert.throws(TypeError, () => yearOfWeek.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype");

View File

@ -0,0 +1,33 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Tests that Temporal.Calendar.prototype.yearOfWeek
meets the requirements for built-in objects defined by the
introduction of chapter 17 of the ECMAScript Language Specification.
info: |
Built-in functions that are not constructors do not have a "prototype" property unless
otherwise specified in the description of a particular function.
Unless specified otherwise, a built-in object that is callable as a function is a built-in
function object with the characteristics described in 10.3. Unless specified otherwise, the
[[Extensible]] internal slot of a built-in object initially has the value true.
Unless otherwise specified every built-in function and every built-in constructor has the
Function prototype object [...] as the value of its [[Prototype]] internal slot.
features: [Temporal]
---*/
assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.yearOfWeek),
true, "Built-in objects must be extensible.");
assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.yearOfWeek),
"[object Function]", "Object.prototype.toString");
assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.yearOfWeek),
Function.prototype, "prototype");
assert.sameValue(Temporal.Calendar.prototype.yearOfWeek.hasOwnProperty("prototype"),
false, "prototype property");

View File

@ -0,0 +1,15 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Calendar.dateFromFields method is called with undefined as the options value
when call originates internally
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions();
calendar.yearOfWeek({ year: 2000, month: 5, day: 3, calendar });
assert.sameValue(calendar.dateFromFieldsCallCount, 1);

View File

@ -0,0 +1,32 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Verify the result of calendar.fields() is treated correctly.
info: |
sec-temporal.calendar.prototype.yearofweek step 4:
4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_).
sec-temporal-totemporaldate step 2.c:
c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
sec-temporal-calendarfields step 4:
4. Let _result_ be ? IterableToListOfType(_fieldsArray_, « String »).
includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/
const expected = [
"day",
"month",
"monthCode",
"year",
];
const calendar1 = TemporalHelpers.calendarFieldsIterable();
const calendar2 = TemporalHelpers.calendarFieldsIterable();
calendar1.yearOfWeek({ year: 2000, month: 5, day: 2, calendar: calendar2 });
assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called");
assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once");
assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args");
assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable");

View File

@ -0,0 +1,26 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
info: |
sec-temporal.calendar.prototype.yearofweek step 4:
4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_).
sec-temporal-totemporaldate step 2.c:
c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
sec-temporal-gettemporalcalendarwithisodefault step 2:
2. Return ? ToTemporalCalendarWithISODefault(_calendar_).
sec-temporal-totemporalcalendarwithisodefault step 2:
3. Return ? ToTemporalCalendar(_temporalCalendarLike_).
sec-temporal-totemporalcalendar step 1.a:
a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
i. Return _temporalCalendarLike_.[[Calendar]].
includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/
TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => {
const calendar = new Temporal.Calendar("iso8601");
calendar.yearOfWeek({ year: 2000, month: 5, day: 2, calendar: temporalObject });
});

View File

@ -0,0 +1,12 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearOfWeek
description: yearOfWeek() where the result is different from the calendar year
features: [Temporal]
---*/
const iso = Temporal.Calendar.from("iso8601");
assert.sameValue(iso.yearOfWeek(Temporal.PlainDate.from("2019-12-31")), 2020, "next year");
assert.sameValue(iso.yearOfWeek(Temporal.PlainDate.from("2021-01-01")), 2020, "previous year");

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Throws if any value in the property bag is Infinity or -Infinity
esid: sec-temporal.calendar.prototype.yearofweek
includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/
const instance = new Temporal.Calendar("iso8601");
const base = { year: 2000, month: 5, day: 2 };
[Infinity, -Infinity].forEach((inf) => {
["year", "month", "day"].forEach((prop) => {
assert.throws(RangeError, () => instance.yearOfWeek({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`);
const calls = [];
const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
assert.throws(RangeError, () => instance.yearOfWeek({ ...base, [prop]: obj }));
assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value");
});
});

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Temporal.Calendar.prototype.yearOfWeek.length is 1
info: |
Every built-in function object, including constructors, has a "length" property whose value is
an integer. Unless otherwise specified, this value is equal to the largest number of named
arguments shown in the subclause headings for the function description. Optional parameters
(which are indicated with brackets: [ ]) or rest parameters (which are shown using the form
«...name») are not included in the default argument count.
Unless otherwise specified, the "length" property of a built-in function object has the
attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
includes: [propertyHelper.js]
features: [Temporal]
---*/
verifyProperty(Temporal.Calendar.prototype.yearOfWeek, "length", {
value: 1,
writable: false,
enumerable: false,
configurable: true,
});

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Temporal.Calendar.prototype.yearOfWeek.name is "yearOfWeek".
info: |
Every built-in function object, including constructors, that is not identified as an anonymous
function has a "name" property whose value is a String. Unless otherwise specified, this value
is the name that is given to the function in this specification.
Unless otherwise specified, the "name" property of a built-in function object, if it exists,
has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
includes: [propertyHelper.js]
features: [Temporal]
---*/
verifyProperty(Temporal.Calendar.prototype.yearOfWeek, "name", {
value: "yearOfWeek",
writable: false,
enumerable: false,
configurable: true,
});

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: >
Temporal.Calendar.prototype.yearOfWeek does not implement [[Construct]], is not new-able
info: |
Built-in function objects that are not identified as constructors do not implement the
[[Construct]] internal method unless otherwise specified in the description of a particular
function.
includes: [isConstructor.js]
features: [Reflect.construct, Temporal]
---*/
assert.throws(TypeError, () => {
new Temporal.Calendar.prototype.yearOfWeek();
}, "Calling as constructor");
assert.sameValue(isConstructor(Temporal.Calendar.prototype.yearOfWeek), false,
"isConstructor(Temporal.Calendar.prototype.yearOfWeek)");

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: The "yearOfWeek" property of Temporal.Calendar.prototype
includes: [propertyHelper.js]
features: [Temporal]
---*/
assert.sameValue(
typeof Temporal.Calendar.prototype.yearOfWeek,
"function",
"`typeof Calendar.prototype.yearOfWeek` is `function`"
);
verifyProperty(Temporal.Calendar.prototype, "yearOfWeek", {
writable: true,
enumerable: false,
configurable: true,
});

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.calendar.prototype.yearofweek
description: Negative zero, as an extended year, is rejected
features: [Temporal, arrow-function]
---*/
const invalidStrings = [
"-000000-10-31",
"-000000-10-31T00:45",
"-000000-10-31T00:45+01:00",
"-000000-10-31T00:45+00:00[UTC]",
];
const instance = new Temporal.Calendar("iso8601");
invalidStrings.forEach((arg) => {
assert.throws(
RangeError,
() => instance.yearOfWeek(arg),
"reject minus zero as extended year"
);
});

View File

@ -0,0 +1,26 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindate.prototype.yearofweek
description: Basic tests for yearOfWeek().
features: [Temporal]
---*/
for (let i = 29; i <= 31; ++i) {
const plainDate = new Temporal.PlainDate(1975, 12, i);
assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`);
}
for (let i = 1; i <= 11; ++i) {
const plainDate = new Temporal.PlainDate(1976, 1, i);
assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`);
}
for (let i = 20; i <= 31; ++i) {
const plainDate = new Temporal.PlainDate(1976, 12, i);
assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`);
}
for (let i = 1; i <= 2; ++i) {
const plainDate = new Temporal.PlainDate(1977, 1, i);
assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`);
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindate.prototype.yearofweek
description: Throw a TypeError if the receiver is invalid
features: [Symbol, Temporal]
---*/
const yearOfWeek = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "yearOfWeek").get;
assert.sameValue(typeof yearOfWeek, "function");
assert.throws(TypeError, () => yearOfWeek.call(undefined), "undefined");
assert.throws(TypeError, () => yearOfWeek.call(null), "null");
assert.throws(TypeError, () => yearOfWeek.call(true), "true");
assert.throws(TypeError, () => yearOfWeek.call(""), "empty string");
assert.throws(TypeError, () => yearOfWeek.call(Symbol()), "symbol");
assert.throws(TypeError, () => yearOfWeek.call(1), "1");
assert.throws(TypeError, () => yearOfWeek.call({}), "plain object");
assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDate), "Temporal.PlainDate");
assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDate.prototype), "Temporal.PlainDate.prototype");

View File

@ -0,0 +1,27 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindate.prototype.yearofweek
description: Custom calendar tests for yearOfWeek().
includes: [compareArray.js]
features: [Temporal]
---*/
let calls = 0;
class CustomCalendar extends Temporal.Calendar {
constructor() {
super("iso8601");
}
yearOfWeek(...args) {
++calls;
assert.compareArray(args, [pd], "yearOfWeek arguments");
return 7;
}
}
const calendar = new CustomCalendar();
const pd = new Temporal.PlainDate(1830, 8, 25, calendar);
const result = pd.yearOfWeek;
assert.sameValue(result, 7, "result");
assert.sameValue(calls, 1, "calls");

View File

@ -0,0 +1,14 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindate.prototype.yearofweek
description: The "yearOfWeek" property of Temporal.PlainDate.prototype
features: [Temporal]
---*/
const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "yearOfWeek");
assert.sameValue(typeof descriptor.get, "function");
assert.sameValue(descriptor.set, undefined);
assert.sameValue(descriptor.enumerable, false);
assert.sameValue(descriptor.configurable, true);

View File

@ -0,0 +1,51 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindate.prototype.yearofweek
description: Validate result returned from calendar yearOfWeek() method
features: [Temporal]
---*/
const badResults = [
[undefined, RangeError],
[Infinity, RangeError],
[-Infinity, RangeError],
[Symbol("foo"), TypeError],
[7n, TypeError],
];
badResults.forEach(([result, error]) => {
const calendar = new class extends Temporal.Calendar {
yearOfWeek() {
return result;
}
}("iso8601");
const instance = new Temporal.PlainDate(1981, 12, 15, calendar);
assert.throws(error, () => instance.yearOfWeek, `${typeof result} not converted to integer`);
});
const convertedResults = [
[null, 0],
[true, 1],
[false, 0],
[7.1, 7],
[-7, -7],
[-0.1, 0],
[NaN, 0],
["string", 0],
["7", 7],
["7.5", 7],
[{}, 0],
[{valueOf() { return 7; }}, 7],
];
convertedResults.forEach(([result, convertedResult]) => {
const calendar = new class extends Temporal.Calendar {
yearOfWeek() {
return result;
}
}("iso8601");
const instance = new Temporal.PlainDate(1981, 12, 15, calendar);
assert.sameValue(instance.yearOfWeek, convertedResult, `${typeof result} converted to integer ${convertedResult}`);
});

View File

@ -0,0 +1,12 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindatetime.prototype.yearofweek
description: Checking yearOfWeek for a "normal" case (non-undefined, non-boundary case, etc.)
features: [Temporal]
---*/
const calendar = Temporal.Calendar.from("iso8601");
const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
assert.sameValue(datetime.yearOfWeek, 1976, "check yearOfWeek information");

View File

@ -0,0 +1,22 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindatetime.prototype.yearofweek
description: Throw a TypeError if the receiver is invalid
features: [Symbol, Temporal]
---*/
const yearOfWeek = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "yearOfWeek").get;
assert.sameValue(typeof yearOfWeek, "function");
assert.throws(TypeError, () => yearOfWeek.call(undefined), "undefined");
assert.throws(TypeError, () => yearOfWeek.call(null), "null");
assert.throws(TypeError, () => yearOfWeek.call(true), "true");
assert.throws(TypeError, () => yearOfWeek.call(""), "empty string");
assert.throws(TypeError, () => yearOfWeek.call(Symbol()), "symbol");
assert.throws(TypeError, () => yearOfWeek.call(1), "1");
assert.throws(TypeError, () => yearOfWeek.call({}), "plain object");
assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDateTime), "Temporal.PlainDateTime");
assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDateTime.prototype), "Temporal.PlainDateTime.prototype");

View File

@ -0,0 +1,27 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindatetime.prototype.yearofweek
description: Custom calendar tests for yearOfWeek().
includes: [compareArray.js]
features: [Temporal]
---*/
let calls = 0;
class CustomCalendar extends Temporal.Calendar {
constructor() {
super("iso8601");
}
yearOfWeek(...args) {
++calls;
assert.compareArray(args, [pdt], "yearOfWeek arguments");
return 7;
}
}
const calendar = new CustomCalendar();
const pdt = new Temporal.PlainDateTime(1830, 8, 25, 20, 0, 0, 0, 0, 0, calendar);
const result = pdt.yearOfWeek;
assert.sameValue(result, 7, "result");
assert.sameValue(calls, 1, "calls");

View File

@ -0,0 +1,14 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindatetime.prototype.yearofweek
description: The "yearOfWeek" property of Temporal.PlainDateTime.prototype
features: [Temporal]
---*/
const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "yearOfWeek");
assert.sameValue(typeof descriptor.get, "function");
assert.sameValue(descriptor.set, undefined);
assert.sameValue(descriptor.enumerable, false);
assert.sameValue(descriptor.configurable, true);

View File

@ -0,0 +1,51 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.plaindatetime.prototype.yearofweek
description: Validate result returned from calendar yearOfWeek() method
features: [Temporal]
---*/
const badResults = [
[undefined, RangeError],
[Infinity, RangeError],
[-Infinity, RangeError],
[Symbol("foo"), TypeError],
[7n, TypeError],
];
badResults.forEach(([result, error]) => {
const calendar = new class extends Temporal.Calendar {
yearOfWeek() {
return result;
}
}("iso8601");
const instance = new Temporal.PlainDateTime(1981, 12, 15, 14, 15, 45, 987, 654, 321, calendar);
assert.throws(error, () => instance.yearOfWeek, `${typeof result} not converted to integer`);
});
const convertedResults = [
[null, 0],
[true, 1],
[false, 0],
[7.1, 7],
[-7, -7],
[-0.1, 0],
[NaN, 0],
["string", 0],
["7", 7],
["7.5", 7],
[{}, 0],
[{valueOf() { return 7; }}, 7],
];
convertedResults.forEach(([result, convertedResult]) => {
const calendar = new class extends Temporal.Calendar {
yearOfWeek() {
return result;
}
}("iso8601");
const instance = new Temporal.PlainDateTime(1981, 12, 15, 14, 15, 45, 987, 654, 321, calendar);
assert.sameValue(instance.yearOfWeek, convertedResult, `${typeof result} converted to integer ${convertedResult}`);
});

View File

@ -0,0 +1,22 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: Throw a TypeError if the receiver is invalid
features: [Symbol, Temporal]
---*/
const yearOfWeek = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "yearOfWeek").get;
assert.sameValue(typeof yearOfWeek, "function");
assert.throws(TypeError, () => yearOfWeek.call(undefined), "undefined");
assert.throws(TypeError, () => yearOfWeek.call(null), "null");
assert.throws(TypeError, () => yearOfWeek.call(true), "true");
assert.throws(TypeError, () => yearOfWeek.call(""), "empty string");
assert.throws(TypeError, () => yearOfWeek.call(Symbol()), "symbol");
assert.throws(TypeError, () => yearOfWeek.call(1), "1");
assert.throws(TypeError, () => yearOfWeek.call({}), "plain object");
assert.throws(TypeError, () => yearOfWeek.call(Temporal.ZonedDateTime), "Temporal.ZonedDateTime");
assert.throws(TypeError, () => yearOfWeek.call(Temporal.ZonedDateTime.prototype), "Temporal.ZonedDateTime.prototype");

View File

@ -0,0 +1,27 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: Custom calendar tests for yearOfWeek().
includes: [compareArray.js]
features: [Temporal]
---*/
let calls = 0;
class CustomCalendar extends Temporal.Calendar {
constructor() {
super("iso8601");
}
yearOfWeek(...args) {
++calls;
assert.compareArray(args.map(String), [instance].map((arg) => arg.toPlainDateTime().toString()), "yearOfWeek arguments");
return 7;
}
}
const calendar = new CustomCalendar();
const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
const result = instance.yearOfWeek;
assert.sameValue(result, 7, "result");
assert.sameValue(calls, 1, "calls");

View File

@ -0,0 +1,14 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: The "yearOfWeek" property of Temporal.ZonedDateTime.prototype
features: [Temporal]
---*/
const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "yearOfWeek");
assert.sameValue(typeof descriptor.get, "function");
assert.sameValue(descriptor.set, undefined);
assert.sameValue(descriptor.enumerable, false);
assert.sameValue(descriptor.configurable, true);

View File

@ -0,0 +1,15 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds
features: [Temporal]
includes: [temporalHelpers.js]
---*/
[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => {
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
assert.throws(RangeError, () => datetime.yearOfWeek);
});

View File

@ -0,0 +1,19 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable
features: [BigInt, Symbol, Temporal, arrow-function]
---*/
[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => {
const timeZone = new Temporal.TimeZone("UTC");
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
timeZone.getOffsetNanosecondsFor = notCallable;
assert.throws(
TypeError,
() => datetime.yearOfWeek,
`Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
);
});

View File

@ -0,0 +1,15 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: RangeError thrown if time zone reports an offset that is out of range
features: [Temporal]
includes: [temporalHelpers.js]
---*/
[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => {
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
assert.throws(RangeError, () => datetime.yearOfWeek);
});

View File

@ -0,0 +1,24 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: TypeError thrown if time zone reports an offset that is not a Number
features: [Temporal]
includes: [temporalHelpers.js]
---*/
[
undefined,
null,
true,
"+01:00",
Symbol(),
3600_000_000_000n,
{},
{ valueOf() { return 3600_000_000_000; } },
].forEach((wrongOffset) => {
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
assert.throws(TypeError, () => datetime.yearOfWeek);
});

View File

@ -0,0 +1,51 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-temporal.zoneddatetime.prototype.yearofweek
description: Validate result returned from calendar yearOfWeek() method
features: [Temporal]
---*/
const badResults = [
[undefined, RangeError],
[Infinity, RangeError],
[-Infinity, RangeError],
[Symbol("foo"), TypeError],
[7n, TypeError],
];
badResults.forEach(([result, error]) => {
const calendar = new class extends Temporal.Calendar {
yearOfWeek() {
return result;
}
}("iso8601");
const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
assert.throws(error, () => instance.yearOfWeek, `${typeof result} not converted to integer`);
});
const convertedResults = [
[null, 0],
[true, 1],
[false, 0],
[7.1, 7],
[-7, -7],
[-0.1, 0],
[NaN, 0],
["string", 0],
["7", 7],
["7.5", 7],
[{}, 0],
[{valueOf() { return 7; }}, 7],
];
convertedResults.forEach(([result, convertedResult]) => {
const calendar = new class extends Temporal.Calendar {
yearOfWeek() {
return result;
}
}("iso8601");
const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
assert.sameValue(instance.yearOfWeek, convertedResult, `${typeof result} converted to integer ${convertedResult}`);
});

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Throws if eraYear in the property bag is Infinity or -Infinity
esid: sec-temporal.calendar.prototype.yearofweek
includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/
const instance = new Temporal.Calendar("gregory");
const base = { era: "ad", month: 5, day: 2, calendar: "gregory" };
[Infinity, -Infinity].forEach((inf) => {
assert.throws(RangeError, () => instance.yearOfWeek({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`);
const calls = [];
const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear");
assert.throws(RangeError, () => instance.yearOfWeek({ ...base, eraYear: obj }));
assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value");
});