mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-11 20:16:02 +00:00
LibJS: Remove our existing Temporal implementation
Our Temporal implementation is woefully out of date. The spec has been so vastly rewritten that it is unfortunately not practical to update our implementation in-place. Even just removing Temporal objects that were removed from the spec, or updating any of the simpler remaining objects, has proven to be a mess in previous attempts. So, this removes our Temporal implementation. AOs used by other specs are left intact.
This commit is contained in:
parent
b94307583b
commit
f7517c5b8d
Notes:
github-actions[bot]
2024-11-21 00:06:58 +00:00
Author: https://github.com/trflynn89
Commit: f7517c5b8d
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2431
Reviewed-by: https://github.com/alimpfard
Reviewed-by: https://github.com/shannonbooth ✅
386 changed files with 8 additions and 33007 deletions
|
@ -1,15 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const date = new Date("2021-07-09T01:36:00Z");
|
||||
const instant = date.toTemporalInstant();
|
||||
expect(instant.epochSeconds).toBe(1625794560);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Date object", () => {
|
||||
expect(() => {
|
||||
Date.prototype.toTemporalInstant.call(123);
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Date");
|
||||
});
|
||||
});
|
|
@ -1,73 +0,0 @@
|
|||
describe("normal behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.from).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const plainTime = new Temporal.PlainTime();
|
||||
const plainDateTime = new Temporal.PlainDateTime(1970, 1, 1);
|
||||
const plainMonthDay = new Temporal.PlainMonthDay(1, 1);
|
||||
const plainYearMonth = new Temporal.PlainYearMonth(1970, 1);
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone);
|
||||
const calendarLike = {};
|
||||
const withCalendarLike = { calendar: {} };
|
||||
expect(Temporal.Calendar.from(plainDate)).toBe(plainDate.calendar);
|
||||
expect(Temporal.Calendar.from(plainTime)).toBe(plainTime.calendar);
|
||||
expect(Temporal.Calendar.from(plainDateTime)).toBe(plainDateTime.calendar);
|
||||
expect(Temporal.Calendar.from(plainMonthDay)).toBe(plainMonthDay.calendar);
|
||||
expect(Temporal.Calendar.from(plainYearMonth)).toBe(plainYearMonth.calendar);
|
||||
expect(Temporal.Calendar.from(zonedDateTime)).toBe(zonedDateTime.calendar);
|
||||
expect(Temporal.Calendar.from(calendarLike)).toBe(calendarLike);
|
||||
expect(Temporal.Calendar.from(withCalendarLike)).toBe(withCalendarLike.calendar);
|
||||
expect(Temporal.Calendar.from("iso8601").id).toBe("iso8601");
|
||||
expect(Temporal.Calendar.from("2021-07-06[u-ca=iso8601]").id).toBe("iso8601");
|
||||
});
|
||||
|
||||
test("ToTemporalCalendar fast path returns if it is passed a Temporal.Calendar instance", () => {
|
||||
// This is obseravble via there being no property lookups (avoiding a "calendar" property lookup in this case)
|
||||
let madeObservableHasPropertyLookup = false;
|
||||
class Calendar extends Temporal.Calendar {
|
||||
constructor() {
|
||||
super("iso8601");
|
||||
}
|
||||
|
||||
get calendar() {
|
||||
madeObservableHasPropertyLookup = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
const calendar = new Calendar();
|
||||
Temporal.Calendar.from(calendar);
|
||||
expect(madeObservableHasPropertyLookup).toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("Calendar from TimeZone", () => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
expect(() => {
|
||||
Temporal.Calendar.from(timeZone);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Got unexpected TimeZone object in conversion to Calendar"
|
||||
);
|
||||
});
|
||||
|
||||
test("yyyy-mm and mm-dd strings can only use the iso8601 calendar", () => {
|
||||
// FIXME: The error message doesn't really indicate this is the case.
|
||||
const values = [
|
||||
"02-10[u-ca=iso8602]",
|
||||
"02-10[u-ca=SerenityOS]",
|
||||
"2023-02[u-ca=iso8602]",
|
||||
"2023-02[u-ca=SerenityOS]",
|
||||
];
|
||||
|
||||
for (const value of values) {
|
||||
expect(() => {
|
||||
Temporal.Calendar.from(value);
|
||||
}).toThrowWithMessage(RangeError, `Invalid calendar string '${value}'`);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,37 +0,0 @@
|
|||
describe("errors", () => {
|
||||
test("called without new", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar();
|
||||
}).toThrowWithMessage(TypeError, "Temporal.Calendar constructor must be called with 'new'");
|
||||
});
|
||||
|
||||
test("argument must be coercible to string", () => {
|
||||
expect(() => {
|
||||
new Temporal.Calendar({
|
||||
toString() {
|
||||
throw new Error();
|
||||
},
|
||||
});
|
||||
}).toThrow(Error);
|
||||
});
|
||||
|
||||
test("invalid calendar identifier", () => {
|
||||
expect(() => {
|
||||
new Temporal.Calendar("foo");
|
||||
}).toThrowWithMessage(RangeError, "Invalid calendar identifier 'foo'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("normal behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.id).toBe("iso8601");
|
||||
expect(typeof calendar).toBe("object");
|
||||
expect(calendar).toBeInstanceOf(Temporal.Calendar);
|
||||
expect(Object.getPrototypeOf(calendar)).toBe(Temporal.Calendar.prototype);
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
test("basic functionality", () => {
|
||||
expect(Temporal.Calendar.prototype[Symbol.toStringTag]).toBe("Temporal.Calendar");
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 2", () => {
|
||||
expect(Temporal.Calendar.prototype.dateAdd).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4);
|
||||
const newPlainDate = calendar.dateAdd(plainDate, duration);
|
||||
expect(newPlainDate.year).toBe(1971);
|
||||
expect(newPlainDate.month).toBe(3);
|
||||
expect(newPlainDate.day).toBe(26);
|
||||
});
|
||||
});
|
|
@ -1,54 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.dateFromFields).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = calendar.dateFromFields({ year: 2000, month: 5, day: 2 });
|
||||
expect(date.calendar).toBe(calendar);
|
||||
});
|
||||
|
||||
test("gets overflow after temporal fields", () => {
|
||||
const operations = [];
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
|
||||
const fields = {
|
||||
get day() {
|
||||
operations.push("get day");
|
||||
return 3;
|
||||
},
|
||||
|
||||
get month() {
|
||||
operations.push("get month");
|
||||
return 10;
|
||||
},
|
||||
|
||||
get monthCode() {
|
||||
operations.push("get monthCode");
|
||||
return "M10";
|
||||
},
|
||||
|
||||
get year() {
|
||||
operations.push("get year");
|
||||
return 2022;
|
||||
},
|
||||
};
|
||||
|
||||
const options = {
|
||||
get overflow() {
|
||||
operations.push("get overflow");
|
||||
return "constrain";
|
||||
},
|
||||
};
|
||||
|
||||
expect(operations).toHaveLength(0);
|
||||
calendar.dateFromFields(fields, options);
|
||||
expect(operations).toHaveLength(5);
|
||||
expect(operations[0]).toBe("get day");
|
||||
expect(operations[1]).toBe("get month");
|
||||
expect(operations[2]).toBe("get monthCode");
|
||||
expect(operations[3]).toBe("get year");
|
||||
expect(operations[4]).toBe("get overflow");
|
||||
});
|
||||
});
|
|
@ -1,79 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 2", () => {
|
||||
expect(Temporal.Calendar.prototype.dateUntil).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const one = new Temporal.PlainDate(2021, 7, 6);
|
||||
const two = new Temporal.PlainDate(2021, 10, 10);
|
||||
|
||||
const oneToTwo = calendar.dateUntil(one, two);
|
||||
expect(oneToTwo.years).toBe(0);
|
||||
expect(oneToTwo.months).toBe(0);
|
||||
expect(oneToTwo.weeks).toBe(0);
|
||||
expect(oneToTwo.days).toBe(96);
|
||||
expect(oneToTwo.hours).toBe(0);
|
||||
expect(oneToTwo.minutes).toBe(0);
|
||||
expect(oneToTwo.seconds).toBe(0);
|
||||
expect(oneToTwo.milliseconds).toBe(0);
|
||||
expect(oneToTwo.microseconds).toBe(0);
|
||||
expect(oneToTwo.nanoseconds).toBe(0);
|
||||
|
||||
const twoToOne = calendar.dateUntil(two, one);
|
||||
expect(twoToOne.years).toBe(0);
|
||||
expect(twoToOne.months).toBe(0);
|
||||
expect(twoToOne.weeks).toBe(0);
|
||||
expect(twoToOne.days).toBe(-96);
|
||||
expect(twoToOne.hours).toBe(0);
|
||||
expect(twoToOne.minutes).toBe(0);
|
||||
expect(twoToOne.seconds).toBe(0);
|
||||
expect(twoToOne.milliseconds).toBe(0);
|
||||
expect(twoToOne.microseconds).toBe(0);
|
||||
expect(twoToOne.nanoseconds).toBe(0);
|
||||
});
|
||||
|
||||
test("largestUnit option", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const one = new Temporal.PlainDate(1970, 1, 1);
|
||||
const two = new Temporal.PlainDate(2021, 7, 6);
|
||||
|
||||
const values = [
|
||||
["years", 51, 6, 0, 5],
|
||||
["months", 0, 618, 0, 5],
|
||||
["weeks", 0, 0, 2687, 5],
|
||||
["days", 0, 0, 0, 18814],
|
||||
];
|
||||
for (const [largestUnit, years, months, weeks, days] of values) {
|
||||
const duration = calendar.dateUntil(one, two, { largestUnit });
|
||||
expect(duration.years).toBe(years);
|
||||
expect(duration.months).toBe(months);
|
||||
expect(duration.weeks).toBe(weeks);
|
||||
expect(duration.days).toBe(days);
|
||||
expect(duration.hours).toBe(0);
|
||||
expect(duration.minutes).toBe(0);
|
||||
expect(duration.seconds).toBe(0);
|
||||
expect(duration.milliseconds).toBe(0);
|
||||
expect(duration.microseconds).toBe(0);
|
||||
expect(duration.nanoseconds).toBe(0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("forbidden largestUnit option values", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const one = new Temporal.PlainDate(1970, 1, 1);
|
||||
const two = new Temporal.PlainDate(2021, 7, 6);
|
||||
|
||||
const values = ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"];
|
||||
for (const largestUnit of values) {
|
||||
expect(() => {
|
||||
calendar.dateUntil(one, two, { largestUnit });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`${largestUnit} is not a valid value for option largestUnit`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.day).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.day(date)).toBe(23);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.dayOfWeek).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.dayOfWeek(date)).toBe(5);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.dayOfYear).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.dayOfYear(date)).toBe(204);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.daysInMonth).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.daysInMonth(date)).toBe(31);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.daysInWeek).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.daysInWeek(date)).toBe(7);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.daysInYear).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.daysInYear(date)).toBe(365);
|
||||
});
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.era).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDate = new Temporal.PlainDate(2021, 7, 6);
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.era(plainDate)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.era.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
|
||||
test("argument must be date-like", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.era({});
|
||||
}).toThrowWithMessage(TypeError, "Required property day is missing or undefined");
|
||||
});
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.eraYear).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDate = new Temporal.PlainDate(2021, 7, 6);
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.eraYear(plainDate)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.eraYear.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
|
||||
test("argument must be date-like", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.eraYear({});
|
||||
}).toThrowWithMessage(TypeError, "Required property day is missing or undefined");
|
||||
});
|
||||
});
|
|
@ -1,55 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.fields).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const array = [
|
||||
"year",
|
||||
"month",
|
||||
"monthCode",
|
||||
"day",
|
||||
"hour",
|
||||
"minute",
|
||||
"second",
|
||||
"millisecond",
|
||||
"microsecond",
|
||||
"nanosecond",
|
||||
];
|
||||
const fields = calendar.fields(array);
|
||||
expect(fields).toEqual(array);
|
||||
expect(fields).not.toBe(array);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.fields.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
|
||||
test("iterator values must be strings", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
for (const value of [123, null, undefined, true, {}]) {
|
||||
expect(() => {
|
||||
calendar.fields([value]);
|
||||
}).toThrowWithMessage(TypeError, `Invalid calendar field ${value}, expected a string`);
|
||||
}
|
||||
});
|
||||
|
||||
test("iterator values must be valid field names", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.fields(["foo"]);
|
||||
}).toThrowWithMessage(RangeError, "Invalid calendar field 'foo'");
|
||||
});
|
||||
|
||||
test("iterator values must not contain duplicates", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.fields(["year", "month", "year", "month"]);
|
||||
}).toThrowWithMessage(RangeError, "Duplicate calendar field 'year'");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.id).toBe("iso8601");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Calendar.prototype, "id", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.inLeapYear).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.inLeapYear(date)).toBeFalse();
|
||||
const leapDate = new Temporal.PlainDate(2020, 7, 23);
|
||||
expect(calendar.inLeapYear(leapDate)).toBeTrue();
|
||||
});
|
||||
});
|
|
@ -1,54 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 2", () => {
|
||||
expect(Temporal.Calendar.prototype.mergeFields).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const fields = {};
|
||||
const additionalFields = {};
|
||||
const mergedFields = calendar.mergeFields(fields, additionalFields);
|
||||
expect(mergedFields).not.toBe(fields);
|
||||
expect(mergedFields).not.toBe(additionalFields);
|
||||
expect(mergedFields).toEqual({});
|
||||
expect(Object.getPrototypeOf(mergedFields)).toBe(Object.prototype);
|
||||
expect(calendar.mergeFields({ foo: 1, bar: 1 }, { foo: 2 })).toEqual({ foo: 2, bar: 1 });
|
||||
expect(calendar.mergeFields({ foo: 1 }, { foo: 2, bar: 2 })).toEqual({ foo: 2, bar: 2 });
|
||||
expect(calendar.mergeFields({ foo: 1 }, { foo: 2, bar: 2 })).toEqual({ foo: 2, bar: 2 });
|
||||
});
|
||||
|
||||
test("month and monthCode property handling", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.mergeFields({ month: 1 }, { monthCode: 2 })).toEqual({ monthCode: 2 });
|
||||
expect(calendar.mergeFields({ monthCode: 1 }, { month: 2 })).toEqual({ month: 2 });
|
||||
expect(calendar.mergeFields({ month: 1, monthCode: 1 }, {})).toEqual({
|
||||
month: 1,
|
||||
monthCode: 1,
|
||||
});
|
||||
expect(
|
||||
calendar.mergeFields({ month: 1, monthCode: 1 }, { month: 2, monthCode: 2 })
|
||||
).toEqual({ month: 2, monthCode: 2 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.mergeFields.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
|
||||
test("fields argument must be coercible to object", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.mergeFields(null, {});
|
||||
}).toThrowWithMessage(TypeError, "ToObject on null or undefined");
|
||||
});
|
||||
|
||||
test("additionalFields argument must be coercible to object", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.mergeFields({}, null);
|
||||
}).toThrowWithMessage(TypeError, "ToObject on null or undefined");
|
||||
});
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.month).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.month(date)).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("argument must not be a Temporal.PlainMonthDay object", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainMonthDay = new Temporal.PlainMonthDay(7, 6);
|
||||
expect(() => {
|
||||
calendar.month(plainMonthDay);
|
||||
}).toThrowWithMessage(
|
||||
TypeError,
|
||||
"Accessing month of PlainMonthDay is ambiguous, use monthCode instead"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.monthCode).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.monthCode(date)).toBe("M07");
|
||||
});
|
||||
});
|
|
@ -1,103 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.monthDayFromFields).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainMonthDay = calendar.monthDayFromFields({ year: 2021, month: 7, day: 6 });
|
||||
expect(plainMonthDay.calendar).toBe(calendar);
|
||||
expect(plainMonthDay.monthCode).toBe("M07");
|
||||
expect(plainMonthDay.day).toBe(6);
|
||||
|
||||
const fields = plainMonthDay.getISOFields();
|
||||
expect(fields.isoYear).toBe(1972); // No, this isn't a mistake
|
||||
});
|
||||
|
||||
test("with monthCode", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainMonthDay = calendar.monthDayFromFields({ monthCode: "M07", day: 6 });
|
||||
expect(plainMonthDay.calendar).toBe(calendar);
|
||||
expect(plainMonthDay.monthCode).toBe("M07");
|
||||
expect(plainMonthDay.day).toBe(6);
|
||||
|
||||
const fields = plainMonthDay.getISOFields();
|
||||
expect(fields.isoYear).toBe(1972);
|
||||
});
|
||||
|
||||
test("gets overflow after temporal fields", () => {
|
||||
const operations = [];
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
|
||||
const fields = {
|
||||
get day() {
|
||||
operations.push("get day");
|
||||
return 3;
|
||||
},
|
||||
|
||||
get month() {
|
||||
operations.push("get month");
|
||||
return 10;
|
||||
},
|
||||
|
||||
get monthCode() {
|
||||
operations.push("get monthCode");
|
||||
return "M10";
|
||||
},
|
||||
|
||||
get year() {
|
||||
operations.push("get year");
|
||||
return 2022;
|
||||
},
|
||||
};
|
||||
|
||||
const options = {
|
||||
get overflow() {
|
||||
operations.push("get overflow");
|
||||
return "constrain";
|
||||
},
|
||||
};
|
||||
|
||||
expect(operations).toHaveLength(0);
|
||||
calendar.monthDayFromFields(fields, options);
|
||||
expect(operations).toHaveLength(5);
|
||||
expect(operations[0]).toBe("get day");
|
||||
expect(operations[1]).toBe("get month");
|
||||
expect(operations[2]).toBe("get monthCode");
|
||||
expect(operations[3]).toBe("get year");
|
||||
expect(operations[4]).toBe("get overflow");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("first argument must be an object", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.monthDayFromFields(42);
|
||||
}).toThrowWithMessage(TypeError, "42 is not an object");
|
||||
});
|
||||
|
||||
test("month or monthCode field is required", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.monthDayFromFields({ year: 2021, day: 1 });
|
||||
}).toThrowWithMessage(TypeError, "Required property month is missing or undefined");
|
||||
});
|
||||
|
||||
test("day field is required", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.monthDayFromFields({ year: 2021, month: 7 });
|
||||
}).toThrowWithMessage(TypeError, "Required property day is missing or undefined");
|
||||
});
|
||||
|
||||
test("monthCode or year field is required when month is given", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.monthDayFromFields({ month: 7, day: 6 });
|
||||
}).toThrowWithMessage(
|
||||
TypeError,
|
||||
"Required property monthCode or year is missing or undefined"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.monthsInYear).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.monthsInYear(date)).toBe(12);
|
||||
});
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Calendar.prototype.toJSON).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.toJSON()).toBe("iso8601");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.toJSON.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Calendar.prototype.toString).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(calendar.toString()).toBe("iso8601");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.toString.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.weekOfYear).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.weekOfYear(date)).toBe(29);
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.year).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(calendar.year(date)).toBe(2021);
|
||||
});
|
||||
});
|
|
@ -1,81 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.yearMonthFromFields).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainYearMonth = calendar.yearMonthFromFields({ year: 2021, month: 7 });
|
||||
expect(plainYearMonth.calendar).toBe(calendar);
|
||||
expect(plainYearMonth.year).toBe(2021);
|
||||
expect(plainYearMonth.month).toBe(7);
|
||||
});
|
||||
|
||||
test("with monthCode", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainYearMonth = calendar.yearMonthFromFields({ year: 2021, monthCode: "M07" });
|
||||
expect(plainYearMonth.calendar).toBe(calendar);
|
||||
expect(plainYearMonth.year).toBe(2021);
|
||||
expect(plainYearMonth.month).toBe(7);
|
||||
});
|
||||
|
||||
test("gets overflow after temporal fields", () => {
|
||||
const operations = [];
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
|
||||
const fields = {
|
||||
get month() {
|
||||
operations.push("get month");
|
||||
return 10;
|
||||
},
|
||||
|
||||
get monthCode() {
|
||||
operations.push("get monthCode");
|
||||
return "M10";
|
||||
},
|
||||
|
||||
get year() {
|
||||
operations.push("get year");
|
||||
return 2022;
|
||||
},
|
||||
};
|
||||
|
||||
const options = {
|
||||
get overflow() {
|
||||
operations.push("get overflow");
|
||||
return "constrain";
|
||||
},
|
||||
};
|
||||
|
||||
expect(operations).toHaveLength(0);
|
||||
calendar.yearMonthFromFields(fields, options);
|
||||
expect(operations).toHaveLength(4);
|
||||
expect(operations[0]).toBe("get month");
|
||||
expect(operations[1]).toBe("get monthCode");
|
||||
expect(operations[2]).toBe("get year");
|
||||
expect(operations[3]).toBe("get overflow");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("first argument must be an object", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.yearMonthFromFields(42);
|
||||
}).toThrowWithMessage(TypeError, "42 is not an object");
|
||||
});
|
||||
|
||||
test("year field is required", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.yearMonthFromFields({ month: 7 });
|
||||
}).toThrowWithMessage(TypeError, "Required property year is missing or undefined");
|
||||
});
|
||||
|
||||
test("month or monthCode field is required", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
expect(() => {
|
||||
calendar.yearMonthFromFields({ year: 2021 });
|
||||
}).toThrowWithMessage(TypeError, "Required property month is missing or undefined");
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Calendar.prototype.yearOfWeek).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const date = new Temporal.PlainDate(2023, 1, 1);
|
||||
expect(calendar.yearOfWeek(date)).toBe(2022);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Calendar object", () => {
|
||||
expect(() => {
|
||||
Temporal.Calendar.prototype.yearOfWeek.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar");
|
||||
});
|
||||
});
|
|
@ -1,113 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 2", () => {
|
||||
expect(Temporal.Duration.compare).toHaveLength(2);
|
||||
});
|
||||
|
||||
function checkCommonResults(duration1, duration2) {
|
||||
expect(Temporal.Duration.compare(duration1, duration1)).toBe(0);
|
||||
expect(Temporal.Duration.compare(duration2, duration2)).toBe(0);
|
||||
expect(Temporal.Duration.compare(duration1, duration2)).toBe(-1);
|
||||
expect(Temporal.Duration.compare(duration2, duration1)).toBe(1);
|
||||
}
|
||||
|
||||
test("basic functionality", () => {
|
||||
const duration1 = new Temporal.Duration(0, 0, 0, 1);
|
||||
const duration2 = new Temporal.Duration(0, 0, 0, 2);
|
||||
checkCommonResults(duration1, duration2);
|
||||
});
|
||||
|
||||
test("duration-like objects", () => {
|
||||
const duration1 = { years: 0, months: 0, weeks: 0, days: 1 };
|
||||
const duration2 = { years: 0, months: 0, weeks: 0, days: 2 };
|
||||
checkCommonResults(duration1, duration2);
|
||||
});
|
||||
|
||||
test("duration strings", () => {
|
||||
const duration1 = "P1D";
|
||||
const duration2 = "P2D";
|
||||
checkCommonResults(duration1, duration2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("invalid duration-like object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.compare({});
|
||||
}).toThrowWithMessage(TypeError, "Invalid duration-like object");
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.compare({ years: 0, months: 0, weeks: 0, days: 1 }, {});
|
||||
}).toThrowWithMessage(TypeError, "Invalid duration-like object");
|
||||
});
|
||||
|
||||
test("relativeTo is required for comparing calendar units (year, month, week)", () => {
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(2);
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration1, duration2);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
|
||||
const duration3 = new Temporal.Duration(0, 3);
|
||||
const duration4 = new Temporal.Duration(0, 4);
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration3, duration4);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
|
||||
const duration5 = new Temporal.Duration(0, 0, 5);
|
||||
const duration6 = new Temporal.Duration(0, 0, 6);
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration5, duration6);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
|
||||
// Still throws if year/month/week of one the duration objects is non-zero.
|
||||
const duration7 = new Temporal.Duration(0, 0, 0, 7);
|
||||
const duration8 = new Temporal.Duration(0, 0, 8);
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration7, duration8);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
|
||||
const duration9 = new Temporal.Duration(0, 0, 9);
|
||||
const duration10 = new Temporal.Duration(0, 0, 0, 10);
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration9, duration10);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
});
|
||||
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(0n, {});
|
||||
const duration = new Temporal.Duration();
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration, duration, { relativeTo: zonedDateTime });
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
|
||||
test("UTC designator only allowed with bracketed time zone", () => {
|
||||
const duration = new Temporal.Duration();
|
||||
expect(() => {
|
||||
Temporal.Duration.compare(duration, duration, { relativeTo: "2022-08-18T17:01Z" });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid relativeTo string '2022-08-18T17:01Z': must not contain a UTC designator without bracketed time zone"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,133 +0,0 @@
|
|||
const expectDurationOneToTen = duration => {
|
||||
expect(duration.years).toBe(1);
|
||||
expect(duration.months).toBe(2);
|
||||
expect(duration.weeks).toBe(3);
|
||||
expect(duration.days).toBe(4);
|
||||
expect(duration.hours).toBe(5);
|
||||
expect(duration.minutes).toBe(6);
|
||||
expect(duration.seconds).toBe(7);
|
||||
expect(duration.milliseconds).toBe(8);
|
||||
expect(duration.microseconds).toBe(9);
|
||||
expect(duration.nanoseconds).toBe(10);
|
||||
};
|
||||
|
||||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Duration.from).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("Duration instance argument", () => {
|
||||
const duration = Temporal.Duration.from(
|
||||
new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
);
|
||||
expectDurationOneToTen(duration);
|
||||
});
|
||||
|
||||
test("Duration-like object argument", () => {
|
||||
const duration = Temporal.Duration.from({
|
||||
years: 1,
|
||||
months: 2,
|
||||
weeks: 3,
|
||||
days: 4,
|
||||
hours: 5,
|
||||
minutes: 6,
|
||||
seconds: 7,
|
||||
milliseconds: 8,
|
||||
microseconds: 9,
|
||||
nanoseconds: 10,
|
||||
});
|
||||
expectDurationOneToTen(duration);
|
||||
});
|
||||
|
||||
test("NaN value becomes zero", () => {
|
||||
// NOTE: NaN does *not* throw a RangeError anymore - which is questionable, IMO - as of:
|
||||
// https://github.com/tc39/proposal-temporal/commit/8c854507a52efbc6e9eb2642f0f928df38e5c021
|
||||
const duration = Temporal.Duration.from({ years: "foo" });
|
||||
expect(duration.years).toBe(0);
|
||||
});
|
||||
|
||||
test("Duration string argument", () => {
|
||||
// FIXME: yes, this needs 11 instead of 10 for nanoseconds for the test to pass.
|
||||
// See comment in parse_temporal_duration_string().
|
||||
const duration = Temporal.Duration.from("P1Y2M3W4DT5H6M7.008009011S");
|
||||
expectDurationOneToTen(duration);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("Invalid duration-like object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.from({});
|
||||
}).toThrowWithMessage(TypeError, "Invalid duration-like object");
|
||||
});
|
||||
|
||||
test("Invalid duration property value", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.from({ years: 1.23 });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid value for duration property 'years': must be an integer, got 1.2" // ...29999999999999 - let's not include that in the test :^)
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid duration string", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.from("foo");
|
||||
}).toThrowWithMessage(RangeError, "Invalid duration string 'foo'");
|
||||
});
|
||||
|
||||
test("invalid duration string: fractional hours proceeded by minutes or seconds", () => {
|
||||
const values = [
|
||||
"PT1.23H1M",
|
||||
"PT1.23H1.23M",
|
||||
"PT1.23H1S",
|
||||
"PT1.23H1.23S",
|
||||
"PT1.23H1M1S",
|
||||
"PT1.23H1M1.23S",
|
||||
"PT1.23H1.23M1S",
|
||||
"PT1.23H1.23M1.23S",
|
||||
];
|
||||
for (const value of values) {
|
||||
expect(() => {
|
||||
Temporal.Duration.from(value);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`Invalid duration string '${value}': fractional hours must not be proceeded by minutes or seconds`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid duration string: fractional minutes proceeded by seconds", () => {
|
||||
const values = ["PT1.23M1S", "PT1.23M1.23S"];
|
||||
for (const value of values) {
|
||||
expect(() => {
|
||||
Temporal.Duration.from(value);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`Invalid duration string '${value}': fractional minutes must not be proceeded by seconds`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid duration string: exceed duration limits", () => {
|
||||
const values = [
|
||||
"P4294967296Y", // abs(years) >= 2**32
|
||||
"P4294967296M", // abs(months) >= 2**32
|
||||
"P4294967296W", // abs(weeks) >= 2**32
|
||||
"P104249991375D", // days >= 2*53 seconds
|
||||
"PT2501999792984H", // hours >= 2*53 seconds
|
||||
"PT150119987579017M", // minutes >= 2*53 seconds
|
||||
"PT9007199254740992S", // seconds >= 2*53 seconds
|
||||
];
|
||||
|
||||
for (const value of values) {
|
||||
expect(() => {
|
||||
Temporal.Duration.from(value);
|
||||
}).toThrowWithMessage(RangeError, `Invalid duration`);
|
||||
|
||||
expect(() => {
|
||||
Temporal.Duration.from("-" + value);
|
||||
}).toThrowWithMessage(RangeError, `Invalid duration`);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
describe("errors", () => {
|
||||
test("called without new", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration();
|
||||
}).toThrowWithMessage(TypeError, "Temporal.Duration constructor must be called with 'new'");
|
||||
});
|
||||
|
||||
test("cannot mix arguments with different signs", () => {
|
||||
expect(() => {
|
||||
new Temporal.Duration(-1, 1);
|
||||
}).toThrowWithMessage(RangeError, "Invalid duration");
|
||||
expect(() => {
|
||||
new Temporal.Duration(1, -1);
|
||||
}).toThrowWithMessage(RangeError, "Invalid duration");
|
||||
});
|
||||
|
||||
test("cannot pass Infinity", () => {
|
||||
expect(() => {
|
||||
new Temporal.Duration(Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid duration");
|
||||
});
|
||||
});
|
||||
|
||||
describe("normal behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Duration).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration();
|
||||
expect(typeof duration).toBe("object");
|
||||
expect(duration).toBeInstanceOf(Temporal.Duration);
|
||||
expect(Object.getPrototypeOf(duration)).toBe(Temporal.Duration.prototype);
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
test("basic functionality", () => {
|
||||
expect(Temporal.Duration.prototype[Symbol.toStringTag]).toBe("Temporal.Duration");
|
||||
});
|
|
@ -1,53 +0,0 @@
|
|||
const DURATION_PROPERTIES = [
|
||||
"years",
|
||||
"months",
|
||||
"weeks",
|
||||
"days",
|
||||
"hours",
|
||||
"minutes",
|
||||
"seconds",
|
||||
"milliseconds",
|
||||
"microseconds",
|
||||
"nanoseconds",
|
||||
];
|
||||
|
||||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Duration.prototype.abs).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
let absoluteDuration;
|
||||
|
||||
absoluteDuration = new Temporal.Duration(123).abs();
|
||||
expect(absoluteDuration.years).toBe(123);
|
||||
|
||||
absoluteDuration = new Temporal.Duration(-123).abs();
|
||||
expect(absoluteDuration.years).toBe(123);
|
||||
});
|
||||
|
||||
test("each property is made absolute", () => {
|
||||
let values;
|
||||
let duration;
|
||||
|
||||
values = Array(DURATION_PROPERTIES.length).fill(-1);
|
||||
duration = new Temporal.Duration(...values).abs();
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
expect(duration[property]).toBe(1);
|
||||
}
|
||||
|
||||
values = Array(DURATION_PROPERTIES.length).fill(1);
|
||||
duration = new Temporal.Duration(...values).abs();
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
expect(duration[property]).toBe(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.abs.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Duration.prototype.add).toHaveLength(1);
|
||||
});
|
||||
|
||||
function checkCommonResults(durationResult) {
|
||||
expect(durationResult.years).toBe(0);
|
||||
expect(durationResult.months).toBe(0);
|
||||
expect(durationResult.weeks).toBe(0);
|
||||
expect(durationResult.days).toBe(3);
|
||||
expect(durationResult.hours).toBe(3);
|
||||
expect(durationResult.minutes).toBe(3);
|
||||
expect(durationResult.seconds).toBe(3);
|
||||
expect(durationResult.milliseconds).toBe(3);
|
||||
expect(durationResult.microseconds).toBe(3);
|
||||
expect(durationResult.nanoseconds).toBe(3);
|
||||
}
|
||||
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2);
|
||||
const oneDuration = new Temporal.Duration(0, 0, 0, 1, 1, 1, 1, 1, 1, 1);
|
||||
const durationResult = duration.add(oneDuration);
|
||||
|
||||
checkCommonResults(durationResult);
|
||||
});
|
||||
|
||||
test("from duration-like", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2);
|
||||
const oneDuration = {
|
||||
days: 1,
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
};
|
||||
const durationResult = duration.add(oneDuration);
|
||||
|
||||
checkCommonResults(durationResult);
|
||||
});
|
||||
|
||||
test("from string", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2);
|
||||
const oneDuration = "P1DT1H1M1.001001001S";
|
||||
const durationResult = duration.add(oneDuration);
|
||||
|
||||
checkCommonResults(durationResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.add.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
|
||||
test("relativeTo is required when duration has calendar units", () => {
|
||||
const yearDuration = new Temporal.Duration(1);
|
||||
const monthDuration = new Temporal.Duration(0, 1);
|
||||
const weekDuration = new Temporal.Duration(0, 0, 1);
|
||||
const durationToAdd = { seconds: 1 };
|
||||
|
||||
expect(() => {
|
||||
yearDuration.add(durationToAdd);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing year, month or week"
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
monthDuration.add(durationToAdd);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing year, month or week"
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
weekDuration.add(durationToAdd);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing year, month or week"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const nonBlankDuration = new Temporal.Duration(123);
|
||||
expect(nonBlankDuration.blank).toBeFalse();
|
||||
|
||||
const blankDuration = new Temporal.Duration(0);
|
||||
expect(blankDuration.blank).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "blank", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 123);
|
||||
expect(duration.days).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "days", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 123);
|
||||
expect(duration.hours).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "hours", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 123);
|
||||
expect(duration.microseconds).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "microseconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 123);
|
||||
expect(duration.milliseconds).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "milliseconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 123);
|
||||
expect(duration.minutes).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "minutes", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 123);
|
||||
expect(duration.months).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "months", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123);
|
||||
expect(duration.nanoseconds).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "nanoseconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,42 +0,0 @@
|
|||
const DURATION_PROPERTIES = [
|
||||
"years",
|
||||
"months",
|
||||
"weeks",
|
||||
"days",
|
||||
"hours",
|
||||
"minutes",
|
||||
"seconds",
|
||||
"milliseconds",
|
||||
"microseconds",
|
||||
"nanoseconds",
|
||||
];
|
||||
|
||||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Duration.prototype.negated).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const negativeDuration = new Temporal.Duration(123).negated();
|
||||
expect(negativeDuration.years).toBe(-123);
|
||||
|
||||
const positiveDuration = new Temporal.Duration(-123).negated();
|
||||
expect(positiveDuration.years).toBe(123);
|
||||
});
|
||||
|
||||
test("each property is negated", () => {
|
||||
const values = Array(DURATION_PROPERTIES.length).fill(1);
|
||||
const duration = new Temporal.Duration(...values).negated();
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
expect(duration[property]).toBe(-1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.negated.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,196 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Duration.prototype.round).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 21, 7, 10, 100, 200, 300, 400);
|
||||
const values = [
|
||||
["nanosecond", "P21DT7H11M40.2003004S"],
|
||||
["microsecond", "P21DT7H11M40.2003S"],
|
||||
["millisecond", "P21DT7H11M40.2S"],
|
||||
["second", "P21DT7H11M40S"],
|
||||
["minute", "P21DT7H12M"],
|
||||
["hour", "P21DT7H"],
|
||||
["day", "P21D"],
|
||||
];
|
||||
|
||||
for (const [smallestUnit, durationString] of values) {
|
||||
const singularRoundedDuration = duration.round({ smallestUnit });
|
||||
const pluralRoundedDuration = duration.round({ smallestUnit: `${smallestUnit}s` });
|
||||
|
||||
// Passing in a string is treated as though { smallestUnit: "<string value>" } was passed in.
|
||||
const singularRoundedDurationWithString = duration.round(smallestUnit);
|
||||
const pluralRoundedDurationWithString = duration.round(`${smallestUnit}s`);
|
||||
|
||||
expect(singularRoundedDuration.toString()).toBe(durationString);
|
||||
expect(singularRoundedDurationWithString.toString()).toBe(durationString);
|
||||
expect(pluralRoundedDuration.toString()).toBe(durationString);
|
||||
expect(pluralRoundedDurationWithString.toString()).toBe(durationString);
|
||||
}
|
||||
});
|
||||
|
||||
test("largestUnit option", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 21, 7, 10, 100, 200, 300, 400);
|
||||
|
||||
// Using strings is not sufficient here, for example, the nanosecond case will produce "PT1840300.2003004S" which is 1840300 s, 200 ms, 300 us, 400 ns
|
||||
const values = [
|
||||
["nanosecond", { nanoseconds: 1840300200300400 }],
|
||||
["microsecond", { microseconds: 1840300200300, nanoseconds: 400 }],
|
||||
["millisecond", { milliseconds: 1840300200, microseconds: 300, nanoseconds: 400 }],
|
||||
[
|
||||
"second",
|
||||
{ seconds: 1840300, milliseconds: 200, microseconds: 300, nanoseconds: 400 },
|
||||
],
|
||||
[
|
||||
"minute",
|
||||
{
|
||||
minutes: 30671,
|
||||
seconds: 40,
|
||||
milliseconds: 200,
|
||||
microseconds: 300,
|
||||
nanoseconds: 400,
|
||||
},
|
||||
],
|
||||
[
|
||||
"hour",
|
||||
{
|
||||
hours: 511,
|
||||
minutes: 11,
|
||||
seconds: 40,
|
||||
milliseconds: 200,
|
||||
microseconds: 300,
|
||||
nanoseconds: 400,
|
||||
},
|
||||
],
|
||||
[
|
||||
"day",
|
||||
{
|
||||
days: 21,
|
||||
hours: 7,
|
||||
minutes: 11,
|
||||
seconds: 40,
|
||||
milliseconds: 200,
|
||||
microseconds: 300,
|
||||
nanoseconds: 400,
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
for (const [largestUnit, durationLike] of values) {
|
||||
const singularRoundedDuration = duration.round({ largestUnit });
|
||||
const pluralRoundedDuration = duration.round({ largestUnit: `${largestUnit}s` });
|
||||
|
||||
const propertiesToCheck = Object.keys(durationLike);
|
||||
|
||||
for (const property of propertiesToCheck) {
|
||||
expect(singularRoundedDuration[property]).toBe(durationLike[property]);
|
||||
expect(pluralRoundedDuration[property]).toBe(durationLike[property]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.round.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
|
||||
test("missing options object", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round();
|
||||
}).toThrowWithMessage(TypeError, "Required options object is missing or undefined");
|
||||
});
|
||||
|
||||
test("invalid rounding mode", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({ smallestUnit: "second", roundingMode: "serenityOS" });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"serenityOS is not a valid value for option roundingMode"
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid smallest unit", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({ smallestUnit: "serenityOS" });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"serenityOS is not a valid value for option smallestUnit"
|
||||
);
|
||||
});
|
||||
|
||||
test("increment may not be NaN", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({ smallestUnit: "second", roundingIncrement: NaN });
|
||||
}).toThrowWithMessage(RangeError, "NaN is not a valid value for option roundingIncrement");
|
||||
});
|
||||
|
||||
test("increment may smaller than 1 or larger than maximum", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({ smallestUnit: "second", roundingIncrement: -1 });
|
||||
}).toThrowWithMessage(RangeError, "-1 is not a valid value for option roundingIncrement");
|
||||
expect(() => {
|
||||
duration.round({ smallestUnit: "second", roundingIncrement: 0 });
|
||||
}).toThrowWithMessage(RangeError, "0 is not a valid value for option roundingIncrement");
|
||||
expect(() => {
|
||||
duration.round({ smallestUnit: "second", roundingIncrement: Infinity });
|
||||
}).toThrowWithMessage(RangeError, "inf is not a valid value for option roundingIncrement");
|
||||
});
|
||||
|
||||
test("must provide one or both of smallestUnit or largestUnit", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({});
|
||||
}).toThrowWithMessage(RangeError, "One or both of smallestUnit or largestUnit is required");
|
||||
});
|
||||
|
||||
test("relativeTo is required when duration has calendar units", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({ largestUnit: "second" });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
});
|
||||
|
||||
// Spec Issue: https://github.com/tc39/proposal-temporal/issues/2124
|
||||
// Spec Fix: https://github.com/tc39/proposal-temporal/commit/66f7464aaec64d3cd21fb2ec37f6502743b9a730
|
||||
test("balancing calendar units with largestUnit set to 'year' and relativeTo unset throws instead of crashing", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.round({ largestUnit: "year" });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid calendar throws range exception when performing round", () => {
|
||||
const duration = Temporal.Duration.from({ nanoseconds: 0 });
|
||||
|
||||
const calendar = new (class extends Temporal.Calendar {
|
||||
dateAdd(date, duration, options) {
|
||||
return date;
|
||||
}
|
||||
})("iso8601");
|
||||
|
||||
expect(() => {
|
||||
duration.round({
|
||||
relativeTo: new Temporal.PlainDate(1997, 5, 10, calendar),
|
||||
smallestUnit: "years",
|
||||
});
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid calendar, dateAdd() function returned result implying a year is zero days long"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 123);
|
||||
expect(duration.seconds).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "seconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const positiveDuration = new Temporal.Duration(123);
|
||||
expect(positiveDuration.sign).toBe(1);
|
||||
|
||||
const negativeDuration = new Temporal.Duration(-123);
|
||||
expect(negativeDuration.sign).toBe(-1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "sign", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Duration.prototype.subtract).toHaveLength(1);
|
||||
});
|
||||
|
||||
function checkCommonResults(durationResult) {
|
||||
expect(durationResult.years).toBe(0);
|
||||
expect(durationResult.months).toBe(0);
|
||||
expect(durationResult.weeks).toBe(0);
|
||||
expect(durationResult.days).toBe(1);
|
||||
expect(durationResult.hours).toBe(1);
|
||||
expect(durationResult.minutes).toBe(1);
|
||||
expect(durationResult.seconds).toBe(1);
|
||||
expect(durationResult.milliseconds).toBe(1);
|
||||
expect(durationResult.microseconds).toBe(1);
|
||||
expect(durationResult.nanoseconds).toBe(1);
|
||||
}
|
||||
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2);
|
||||
const oneDuration = new Temporal.Duration(0, 0, 0, 1, 1, 1, 1, 1, 1, 1);
|
||||
const durationResult = duration.subtract(oneDuration);
|
||||
|
||||
checkCommonResults(durationResult);
|
||||
});
|
||||
|
||||
test("from duration-like", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2);
|
||||
const oneDuration = {
|
||||
days: 1,
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
};
|
||||
const durationResult = duration.subtract(oneDuration);
|
||||
|
||||
checkCommonResults(durationResult);
|
||||
});
|
||||
|
||||
test("from string", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2);
|
||||
const oneDuration = "P1DT1H1M1.001001001S";
|
||||
const durationResult = duration.subtract(oneDuration);
|
||||
|
||||
checkCommonResults(durationResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.subtract.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
|
||||
test("relativeTo is required when duration has calendar units", () => {
|
||||
const yearDuration = new Temporal.Duration(1);
|
||||
const monthDuration = new Temporal.Duration(0, 1);
|
||||
const weekDuration = new Temporal.Duration(0, 0, 1);
|
||||
const durationToSubtract = { seconds: 1 };
|
||||
|
||||
expect(() => {
|
||||
yearDuration.subtract(durationToSubtract);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing year, month or week"
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
monthDuration.subtract(durationToSubtract);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing year, month or week"
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
weekDuration.subtract(durationToSubtract);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing year, month or week"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Duration.prototype.toJSON).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
expect(new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).toJSON()).toBe(
|
||||
"P1Y2M3W4DT5H6M7.00800901S"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.toJSON.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Duration.prototype.toLocaleString).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
expect(new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).toLocaleString()).toBe(
|
||||
"P1Y2M3W4DT5H6M7.00800901S"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.toLocaleString.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,94 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Duration.prototype.toString).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const values = [
|
||||
[[0], "PT0S"],
|
||||
[[1], "P1Y"],
|
||||
[[0, 1], "P1M"],
|
||||
[[0, 0, 1], "P1W"],
|
||||
[[0, 0, 0, 1], "P1D"],
|
||||
[[0, 0, 0, 0, 1], "PT1H"],
|
||||
[[0, 0, 0, 0, 0, 1], "PT1M"],
|
||||
[[0, 0, 0, 0, 0, 0, 1], "PT1S"],
|
||||
[[0, 0, 0, 0, 0, 0, 0, 1], "PT0.001S"],
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 1], "PT0.000001S"],
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1], "PT0.000000001S"],
|
||||
[[1, 2], "P1Y2M"],
|
||||
[[1, 2, 3], "P1Y2M3W"],
|
||||
[[1, 2, 3, 4], "P1Y2M3W4D"],
|
||||
[[1, 2, 3, 4, 5], "P1Y2M3W4DT5H"],
|
||||
[[1, 2, 3, 4, 5, 6], "P1Y2M3W4DT5H6M"],
|
||||
[[1, 2, 3, 4, 5, 6, 7], "P1Y2M3W4DT5H6M7S"],
|
||||
[[1, 2, 3, 4, 5, 6, 7, 8], "P1Y2M3W4DT5H6M7.008S"],
|
||||
[[1, 2, 3, 4, 5, 6, 7, 8, 9], "P1Y2M3W4DT5H6M7.008009S"],
|
||||
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "P1Y2M3W4DT5H6M7.00800901S"],
|
||||
[
|
||||
[100, 200, 300, 400, 500, 600, 700, 800, 900, 1000],
|
||||
"P100Y200M300W400DT500H600M700.800901S",
|
||||
],
|
||||
[[-1], "-P1Y"],
|
||||
];
|
||||
for (const [args, expected] of values) {
|
||||
expect(new Temporal.Duration(...args).toString()).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
test("smallestUnit option", () => {
|
||||
const values = [
|
||||
["second", "P1Y2M3W4DT5H6M7S"],
|
||||
["millisecond", "P1Y2M3W4DT5H6M7.008S"],
|
||||
["microsecond", "P1Y2M3W4DT5H6M7.008010S"],
|
||||
["nanosecond", "P1Y2M3W4DT5H6M7.008010000S"],
|
||||
];
|
||||
for (const [smallestUnit, expected] of values) {
|
||||
expect(
|
||||
new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 10).toString({ smallestUnit })
|
||||
).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
test("fractionalSecondDigits option", () => {
|
||||
const values = [
|
||||
[0, "P1Y2M3W4DT5H6M7S"],
|
||||
[1, "P1Y2M3W4DT5H6M7.0S"],
|
||||
[2, "P1Y2M3W4DT5H6M7.00S"],
|
||||
[3, "P1Y2M3W4DT5H6M7.008S"],
|
||||
[4, "P1Y2M3W4DT5H6M7.0080S"],
|
||||
[5, "P1Y2M3W4DT5H6M7.00801S"],
|
||||
[6, "P1Y2M3W4DT5H6M7.008010S"],
|
||||
[7, "P1Y2M3W4DT5H6M7.0080100S"],
|
||||
[8, "P1Y2M3W4DT5H6M7.00801000S"],
|
||||
[9, "P1Y2M3W4DT5H6M7.008010000S"],
|
||||
];
|
||||
for (const [fractionalSecondDigits, expected] of values) {
|
||||
expect(
|
||||
new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 10).toString({
|
||||
fractionalSecondDigits,
|
||||
})
|
||||
).toBe(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.toString.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
|
||||
test("disallowed smallestUnit option values", () => {
|
||||
const values = ["year", "month", "week", "day", "hour", "minute"];
|
||||
for (const smallestUnit of values) {
|
||||
expect(() => {
|
||||
new Temporal.Duration(0).toString({ smallestUnit });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`${smallestUnit} is not a valid value for option smallestUnit`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,107 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
{
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 4, 5, 6);
|
||||
const relativeTo = new Temporal.PlainDate(1970, 1, 1);
|
||||
const values = [
|
||||
[{ unit: "year", relativeTo }, 0.0001180556825534627],
|
||||
[{ unit: "month", relativeTo }, 0.0013900104558714158],
|
||||
[{ unit: "week", relativeTo }, 0.006155760590287699],
|
||||
[{ unit: "day", relativeTo }, 0.04309032413201389],
|
||||
[{ unit: "hour" }, 1.034167779168333],
|
||||
[{ unit: "minute" }, 62.0500667501],
|
||||
[{ unit: "second" }, 3723.00400500600017],
|
||||
[{ unit: "millisecond" }, 3723004.005005999933928],
|
||||
[{ unit: "microsecond" }, 3723004005.006000041961669],
|
||||
[{ unit: "nanosecond" }, 3723004005006],
|
||||
];
|
||||
for (const [arg, expected] of values) {
|
||||
const matcher = Number.isInteger(expected) ? "toBe" : "toBeCloseTo";
|
||||
expect(duration.total(arg))[matcher](expected);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||
const relativeTo = new Temporal.PlainDate(1970, 1, 1);
|
||||
const values = [
|
||||
[{ unit: "year", relativeTo }, 1.2307194003046997],
|
||||
[{ unit: "month", relativeTo }, 14.813309068103722],
|
||||
[{ unit: "week", relativeTo }, 64.17322587303077],
|
||||
[{ unit: "day", relativeTo }, 449.21258111121534],
|
||||
[{ unit: "hour", relativeTo }, 10781.101946669169],
|
||||
[{ unit: "minute", relativeTo }, 646866.1168001501],
|
||||
[{ unit: "second", relativeTo }, 38811967.00800901],
|
||||
[{ unit: "millisecond", relativeTo }, 38811967008.00901],
|
||||
[{ unit: "microsecond", relativeTo }, 38811967008009.01],
|
||||
[{ unit: "nanosecond", relativeTo }, 38811967008009010],
|
||||
];
|
||||
for (const [arg, expected] of values) {
|
||||
const matcher = Number.isInteger(expected) ? "toBe" : "toBeCloseTo";
|
||||
expect(duration.total(arg))[matcher](expected);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const relativeTo = new Temporal.PlainDate(1970, 1, 1);
|
||||
const units = [
|
||||
"year",
|
||||
"month",
|
||||
"week",
|
||||
"day",
|
||||
"hour",
|
||||
"minute",
|
||||
"second",
|
||||
"millisecond",
|
||||
"microsecond",
|
||||
"nanosecond",
|
||||
];
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
const args = [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
args[i] = 123;
|
||||
const unit = units[i];
|
||||
const duration = new Temporal.Duration(...args);
|
||||
expect(duration.total({ unit, relativeTo })).toBe(123);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.total.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
|
||||
test("missing options object", () => {
|
||||
const duration = new Temporal.Duration();
|
||||
expect(() => {
|
||||
duration.total();
|
||||
}).toThrowWithMessage(TypeError, "Required options object is missing or undefined");
|
||||
});
|
||||
|
||||
test("missing unit option", () => {
|
||||
const duration = new Temporal.Duration();
|
||||
expect(() => {
|
||||
duration.total({});
|
||||
}).toThrowWithMessage(RangeError, "unit option value is undefined");
|
||||
});
|
||||
|
||||
test("invalid unit option", () => {
|
||||
const duration = new Temporal.Duration();
|
||||
expect(() => {
|
||||
duration.total({ unit: "foo" });
|
||||
}).toThrowWithMessage(RangeError, "foo is not a valid value for option unit");
|
||||
});
|
||||
|
||||
test("relativeTo is required when duration has calendar units", () => {
|
||||
const duration = new Temporal.Duration(1);
|
||||
expect(() => {
|
||||
duration.total({ unit: "second" });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"A starting point is required for balancing calendar units"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
describe("errors", () => {
|
||||
test("throws TypeError", () => {
|
||||
expect(() => {
|
||||
new Temporal.Duration().valueOf();
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert Temporal.Duration to a primitive value");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(0, 0, 123);
|
||||
expect(duration.weeks).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "weeks", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,94 +0,0 @@
|
|||
const DURATION_PROPERTIES = [
|
||||
"years",
|
||||
"months",
|
||||
"weeks",
|
||||
"days",
|
||||
"hours",
|
||||
"minutes",
|
||||
"seconds",
|
||||
"milliseconds",
|
||||
"microseconds",
|
||||
"nanoseconds",
|
||||
];
|
||||
|
||||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Duration.prototype.with).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(1, 2, 3).with({ years: 4, foo: 5, weeks: 6 });
|
||||
expect(duration.years).toBe(4);
|
||||
expect(duration.months).toBe(2);
|
||||
expect(duration.weeks).toBe(6);
|
||||
});
|
||||
|
||||
test("each property is looked up from the object", () => {
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
const duration = new Temporal.Duration().with({ [property]: 1 });
|
||||
expect(duration[property]).toBe(1);
|
||||
}
|
||||
});
|
||||
|
||||
test("each property is coerced to number", () => {
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
const duration = new Temporal.Duration().with({ [property]: "1" });
|
||||
expect(duration[property]).toBe(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Temporal.Duration.prototype.with.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
|
||||
test("argument is not an object", () => {
|
||||
expect(() => {
|
||||
new Temporal.Duration().with("foo");
|
||||
}).toThrowWithMessage(TypeError, "foo is not an object");
|
||||
expect(() => {
|
||||
new Temporal.Duration().with(42);
|
||||
}).toThrowWithMessage(TypeError, "42 is not an object");
|
||||
});
|
||||
|
||||
test("argument is an invalid duration-like object", () => {
|
||||
expect(() => {
|
||||
new Temporal.Duration().with({});
|
||||
}).toThrowWithMessage(TypeError, "Invalid duration-like object");
|
||||
expect(() => {
|
||||
new Temporal.Duration().with({ foo: 1, bar: 2 });
|
||||
}).toThrowWithMessage(TypeError, "Invalid duration-like object");
|
||||
});
|
||||
|
||||
test("error when coercing property to number", () => {
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
expect(() => {
|
||||
new Temporal.Duration().with({
|
||||
[property]: {
|
||||
valueOf() {
|
||||
throw new Error();
|
||||
},
|
||||
},
|
||||
});
|
||||
}).toThrow(Error);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid duration value", () => {
|
||||
for (const property of DURATION_PROPERTIES) {
|
||||
// NOTE: NaN does *not* throw a RangeError anymore - which is questionable, IMO - as of:
|
||||
// https://github.com/tc39/proposal-temporal/commit/8c854507a52efbc6e9eb2642f0f928df38e5c021
|
||||
for (const value of [1.23, Infinity]) {
|
||||
expect(() => {
|
||||
new Temporal.Duration().with({ [property]: value });
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`Invalid value for duration property '${property}': must be an integer, got ${value}`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const duration = new Temporal.Duration(123);
|
||||
expect(duration.years).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Duration object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Duration.prototype, "years", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration");
|
||||
});
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 2", () => {
|
||||
expect(Temporal.Instant.compare).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant1 = new Temporal.Instant(111n);
|
||||
expect(Temporal.Instant.compare(instant1, instant1)).toBe(0);
|
||||
const instant2 = new Temporal.Instant(999n);
|
||||
expect(Temporal.Instant.compare(instant1, instant2)).toBe(-1);
|
||||
expect(Temporal.Instant.compare(instant2, instant1)).toBe(1);
|
||||
});
|
||||
});
|
|
@ -1,76 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.from).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("Instant instance argument", () => {
|
||||
const instant = new Temporal.Instant(123n);
|
||||
expect(Temporal.Instant.from(instant).epochNanoseconds).toBe(123n);
|
||||
});
|
||||
|
||||
test("ZonedDateTime instance argument", () => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(123n, timeZone);
|
||||
expect(Temporal.Instant.from(zonedDateTime).epochNanoseconds).toBe(123n);
|
||||
});
|
||||
|
||||
test("Instant string argument", () => {
|
||||
expect(Temporal.Instant.from("1975-02-02T14:25:36.123456789Z").epochNanoseconds).toBe(
|
||||
160583136123456789n
|
||||
);
|
||||
// Time zone is not validated
|
||||
expect(
|
||||
Temporal.Instant.from("1975-02-02T14:25:36.123456789Z[Custom/TimeZone]")
|
||||
.epochNanoseconds
|
||||
).toBe(160583136123456789n);
|
||||
|
||||
// Accepts but ignores the calendar.
|
||||
let result = null;
|
||||
expect(() => {
|
||||
result = Temporal.Instant.from("1970-01-01T00:00Z[u-ca=UTC]");
|
||||
}).not.toThrow();
|
||||
expect(result).toBeInstanceOf(Temporal.Instant);
|
||||
expect(result.epochNanoseconds).toBe(0n);
|
||||
|
||||
// Does not validate calendar name, it only checks that the calendar name matches the grammar.
|
||||
result = null;
|
||||
expect(() => {
|
||||
result = Temporal.Instant.from("1970-01-01T00:00Z[u-ca=aAaAaAaA-bBbBbBb]");
|
||||
}).not.toThrow();
|
||||
expect(result).toBeInstanceOf(Temporal.Instant);
|
||||
expect(result.epochNanoseconds).toBe(0n);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("invalid instant string", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.from("foo");
|
||||
}).toThrowWithMessage(RangeError, "Invalid instant string 'foo'");
|
||||
});
|
||||
|
||||
test("invalid epoch nanoseconds", () => {
|
||||
// Test cases from https://github.com/tc39/proposal-temporal/commit/baead4d85bc3e9ecab1e9824c3d3fe4fdd77fc3a
|
||||
expect(() => {
|
||||
Temporal.Instant.from("-271821-04-20T00:00:00+00:01");
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
expect(() => {
|
||||
Temporal.Instant.from("+275760-09-13T00:00:00-00:01");
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
|
||||
test("annotations must match annotation grammar even though they're ignored", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.from("1970-01-01T00:00Z[SerenityOS=cool]");
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid instant string '1970-01-01T00:00Z[SerenityOS=cool]'"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,51 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.fromEpochMicroseconds).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
expect(Temporal.Instant.fromEpochMicroseconds(0n).epochMicroseconds).toBe(0n);
|
||||
expect(Temporal.Instant.fromEpochMicroseconds(1n).epochMicroseconds).toBe(1n);
|
||||
expect(Temporal.Instant.fromEpochMicroseconds(999_999_999n).epochMicroseconds).toBe(
|
||||
999_999_999n
|
||||
);
|
||||
expect(
|
||||
Temporal.Instant.fromEpochMicroseconds(8_640_000_000_000_000_000n).epochMicroseconds
|
||||
).toBe(8_640_000_000_000_000_000n);
|
||||
|
||||
expect(Temporal.Instant.fromEpochMicroseconds(-0n).epochMicroseconds).toBe(0n);
|
||||
expect(Temporal.Instant.fromEpochMicroseconds(-1n).epochMicroseconds).toBe(-1n);
|
||||
expect(Temporal.Instant.fromEpochMicroseconds(-999_999_999n).epochMicroseconds).toBe(
|
||||
-999_999_999n
|
||||
);
|
||||
expect(
|
||||
Temporal.Instant.fromEpochMicroseconds(-8_640_000_000_000_000_000n).epochMicroseconds
|
||||
).toBe(-8_640_000_000_000_000_000n);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("argument must be coercible to BigInt", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMicroseconds(123);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert number to BigInt");
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMicroseconds("foo");
|
||||
}).toThrowWithMessage(SyntaxError, "Invalid value for BigInt: foo");
|
||||
});
|
||||
|
||||
test("out-of-range epoch microseconds value", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMicroseconds(8_640_000_000_000_000_001n);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMicroseconds(-8_640_000_000_000_000_001n);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,52 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.fromEpochMilliseconds).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
expect(Temporal.Instant.fromEpochMilliseconds(0).epochMilliseconds).toBe(0);
|
||||
expect(Temporal.Instant.fromEpochMilliseconds(1).epochMilliseconds).toBe(1);
|
||||
expect(Temporal.Instant.fromEpochMilliseconds(999_999_999).epochMilliseconds).toBe(
|
||||
999_999_999
|
||||
);
|
||||
expect(
|
||||
Temporal.Instant.fromEpochMilliseconds(8_640_000_000_000_000).epochMilliseconds
|
||||
).toBe(8_640_000_000_000_000);
|
||||
|
||||
expect(Temporal.Instant.fromEpochMilliseconds(-0).epochMilliseconds).toBe(0);
|
||||
expect(Temporal.Instant.fromEpochMilliseconds(-1).epochMilliseconds).toBe(-1);
|
||||
expect(Temporal.Instant.fromEpochMilliseconds(-999_999_999).epochMilliseconds).toBe(
|
||||
-999_999_999
|
||||
);
|
||||
expect(
|
||||
Temporal.Instant.fromEpochMilliseconds(-8_640_000_000_000_000).epochMilliseconds
|
||||
).toBe(-8_640_000_000_000_000);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("argument must be coercible to BigInt", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMilliseconds(1.23);
|
||||
}).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt");
|
||||
// NOTE: ToNumber is called on the argument first, so this is effectively NaN.
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMilliseconds("foo");
|
||||
}).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt");
|
||||
});
|
||||
|
||||
test("out-of-range epoch milliseconds value", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMilliseconds(8_640_000_000_000_001);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochMilliseconds(-8_640_000_000_000_001);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,51 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.fromEpochNanoseconds).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
expect(Temporal.Instant.fromEpochNanoseconds(0n).epochNanoseconds).toBe(0n);
|
||||
expect(Temporal.Instant.fromEpochNanoseconds(1n).epochNanoseconds).toBe(1n);
|
||||
expect(Temporal.Instant.fromEpochNanoseconds(999_999_999n).epochNanoseconds).toBe(
|
||||
999_999_999n
|
||||
);
|
||||
expect(
|
||||
Temporal.Instant.fromEpochNanoseconds(8_640_000_000_000_000_000_000n).epochNanoseconds
|
||||
).toBe(8_640_000_000_000_000_000_000n);
|
||||
|
||||
expect(Temporal.Instant.fromEpochNanoseconds(-0n).epochNanoseconds).toBe(0n);
|
||||
expect(Temporal.Instant.fromEpochNanoseconds(-1n).epochNanoseconds).toBe(-1n);
|
||||
expect(Temporal.Instant.fromEpochNanoseconds(-999_999_999n).epochNanoseconds).toBe(
|
||||
-999_999_999n
|
||||
);
|
||||
expect(
|
||||
Temporal.Instant.fromEpochNanoseconds(-8_640_000_000_000_000_000_000n).epochNanoseconds
|
||||
).toBe(-8_640_000_000_000_000_000_000n);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("argument must be coercible to BigInt", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochNanoseconds(123);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert number to BigInt");
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochNanoseconds("foo");
|
||||
}).toThrowWithMessage(SyntaxError, "Invalid value for BigInt: foo");
|
||||
});
|
||||
|
||||
test("out-of-range epoch nanoseconds value", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochNanoseconds(8_640_000_000_000_000_000_001n);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochNanoseconds(-8_640_000_000_000_000_000_001n);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.fromEpochSeconds).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
expect(Temporal.Instant.fromEpochSeconds(0).epochSeconds).toBe(0);
|
||||
expect(Temporal.Instant.fromEpochSeconds(1).epochSeconds).toBe(1);
|
||||
expect(Temporal.Instant.fromEpochSeconds(999_999_999).epochSeconds).toBe(999_999_999);
|
||||
expect(Temporal.Instant.fromEpochSeconds(8_640_000_000_000).epochSeconds).toBe(
|
||||
8_640_000_000_000
|
||||
);
|
||||
|
||||
expect(Temporal.Instant.fromEpochSeconds(-0).epochSeconds).toBe(0);
|
||||
expect(Temporal.Instant.fromEpochSeconds(-1).epochSeconds).toBe(-1);
|
||||
expect(Temporal.Instant.fromEpochSeconds(-999_999_999).epochSeconds).toBe(-999_999_999);
|
||||
expect(Temporal.Instant.fromEpochSeconds(-8_640_000_000_000).epochSeconds).toBe(
|
||||
-8_640_000_000_000
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("argument must be coercible to BigInt", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochSeconds(1.23);
|
||||
}).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt");
|
||||
// NOTE: ToNumber is called on the argument first, so this is effectively NaN.
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochSeconds("foo");
|
||||
}).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt");
|
||||
});
|
||||
|
||||
test("out-of-range epoch seconds value", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochSeconds(8_640_000_000_001);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
expect(() => {
|
||||
Temporal.Instant.fromEpochSeconds(-8_640_000_000_001);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,30 +0,0 @@
|
|||
describe("errors", () => {
|
||||
test("called without new", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant();
|
||||
}).toThrowWithMessage(TypeError, "Temporal.Instant constructor must be called with 'new'");
|
||||
});
|
||||
|
||||
test("argument must be coercible to bigint", () => {
|
||||
expect(() => {
|
||||
new Temporal.Instant(123);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert number to BigInt");
|
||||
expect(() => {
|
||||
new Temporal.Instant("foo");
|
||||
}).toThrowWithMessage(SyntaxError, "Invalid value for BigInt: foo");
|
||||
});
|
||||
});
|
||||
|
||||
describe("normal behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(123n);
|
||||
expect(instant.epochNanoseconds).toBe(123n);
|
||||
expect(typeof instant).toBe("object");
|
||||
expect(instant).toBeInstanceOf(Temporal.Instant);
|
||||
expect(Object.getPrototypeOf(instant)).toBe(Temporal.Instant.prototype);
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
test("basic functionality", () => {
|
||||
expect(Temporal.Instant.prototype[Symbol.toStringTag]).toBe("Temporal.Instant");
|
||||
});
|
|
@ -1,59 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.add).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921000000000n);
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 4, 5, 6);
|
||||
expect(instant.add(duration).epochNanoseconds).toBe(1625618644004005006n);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.add.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
|
||||
test("invalid nanoseconds value, positive", () => {
|
||||
const instant = new Temporal.Instant(8_640_000_000_000_000_000_000n);
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||
expect(() => {
|
||||
instant.add(duration);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid nanoseconds value, negative", () => {
|
||||
const instant = new Temporal.Instant(-8_640_000_000_000_000_000_000n);
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1);
|
||||
expect(() => {
|
||||
instant.add(duration);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
|
||||
test("disallowed fields", () => {
|
||||
const instant = new Temporal.Instant(1625614921000000000n);
|
||||
for (const [args, property] of [
|
||||
[[123, 0, 0, 0], "years"],
|
||||
[[0, 123, 0, 0], "months"],
|
||||
[[0, 0, 123, 0], "weeks"],
|
||||
[[0, 0, 0, 123], "days"],
|
||||
]) {
|
||||
const duration = new Temporal.Duration(...args);
|
||||
expect(() => {
|
||||
instant.add(duration);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`Invalid value for duration property '${property}': must be zero, got 123`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
expect(new Temporal.Instant(0n).epochMicroseconds).toBe(0n);
|
||||
expect(new Temporal.Instant(1n).epochMicroseconds).toBe(0n);
|
||||
expect(new Temporal.Instant(999n).epochMicroseconds).toBe(0n);
|
||||
expect(new Temporal.Instant(1_000n).epochMicroseconds).toBe(1n);
|
||||
expect(new Temporal.Instant(1_500n).epochMicroseconds).toBe(1n);
|
||||
expect(new Temporal.Instant(1_999n).epochMicroseconds).toBe(1n);
|
||||
expect(new Temporal.Instant(2_000n).epochMicroseconds).toBe(2n);
|
||||
expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochMicroseconds).toBe(
|
||||
8_640_000_000_000_000_000n
|
||||
);
|
||||
|
||||
expect(new Temporal.Instant(-0n).epochMicroseconds).toBe(-0n);
|
||||
expect(new Temporal.Instant(-1n).epochMicroseconds).toBe(-0n);
|
||||
expect(new Temporal.Instant(-999n).epochMicroseconds).toBe(-0n);
|
||||
expect(new Temporal.Instant(-1_000n).epochMicroseconds).toBe(-1n);
|
||||
expect(new Temporal.Instant(-1_500n).epochMicroseconds).toBe(-1n);
|
||||
expect(new Temporal.Instant(-1_999n).epochMicroseconds).toBe(-1n);
|
||||
expect(new Temporal.Instant(-2_000n).epochMicroseconds).toBe(-2n);
|
||||
expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochMicroseconds).toBe(
|
||||
-8_640_000_000_000_000_000n
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Instant.prototype, "epochMicroseconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
expect(new Temporal.Instant(0n).epochMilliseconds).toBe(0);
|
||||
expect(new Temporal.Instant(1n).epochMilliseconds).toBe(0);
|
||||
expect(new Temporal.Instant(999_999n).epochMilliseconds).toBe(0);
|
||||
expect(new Temporal.Instant(1_000_000n).epochMilliseconds).toBe(1);
|
||||
expect(new Temporal.Instant(1_500_000n).epochMilliseconds).toBe(1);
|
||||
expect(new Temporal.Instant(1_999_999n).epochMilliseconds).toBe(1);
|
||||
expect(new Temporal.Instant(2_000_000n).epochMilliseconds).toBe(2);
|
||||
expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochMilliseconds).toBe(
|
||||
8_640_000_000_000_000
|
||||
);
|
||||
|
||||
expect(new Temporal.Instant(-0n).epochMilliseconds).toBe(0);
|
||||
expect(new Temporal.Instant(-1n).epochMilliseconds).toBe(0);
|
||||
expect(new Temporal.Instant(-999_999n).epochMilliseconds).toBe(0);
|
||||
expect(new Temporal.Instant(-1_000_000n).epochMilliseconds).toBe(-1);
|
||||
expect(new Temporal.Instant(-1_500_000n).epochMilliseconds).toBe(-1);
|
||||
expect(new Temporal.Instant(-1_999_999n).epochMilliseconds).toBe(-1);
|
||||
expect(new Temporal.Instant(-2_000_000n).epochMilliseconds).toBe(-2);
|
||||
expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochMilliseconds).toBe(
|
||||
-8_640_000_000_000_000
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Instant.prototype, "epochMilliseconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
expect(new Temporal.Instant(0n).epochNanoseconds).toBe(0n);
|
||||
expect(new Temporal.Instant(1n).epochNanoseconds).toBe(1n);
|
||||
expect(new Temporal.Instant(999n).epochNanoseconds).toBe(999n);
|
||||
expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochNanoseconds).toBe(
|
||||
8_640_000_000_000_000_000_000n
|
||||
);
|
||||
|
||||
expect(new Temporal.Instant(-0n).epochNanoseconds).toBe(-0n);
|
||||
expect(new Temporal.Instant(-1n).epochNanoseconds).toBe(-1n);
|
||||
expect(new Temporal.Instant(-999n).epochNanoseconds).toBe(-999n);
|
||||
expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochNanoseconds).toBe(
|
||||
-8_640_000_000_000_000_000_000n
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Instant.prototype, "epochNanoseconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
expect(new Temporal.Instant(0n).epochSeconds).toBe(0);
|
||||
expect(new Temporal.Instant(1n).epochSeconds).toBe(0);
|
||||
expect(new Temporal.Instant(999_999_999n).epochSeconds).toBe(0);
|
||||
expect(new Temporal.Instant(1_000_000_000n).epochSeconds).toBe(1);
|
||||
expect(new Temporal.Instant(1_500_000_000n).epochSeconds).toBe(1);
|
||||
expect(new Temporal.Instant(1_999_999_999n).epochSeconds).toBe(1);
|
||||
expect(new Temporal.Instant(2_000_000_000n).epochSeconds).toBe(2);
|
||||
expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochSeconds).toBe(
|
||||
8_640_000_000_000
|
||||
);
|
||||
|
||||
expect(new Temporal.Instant(-0n).epochSeconds).toBe(0);
|
||||
expect(new Temporal.Instant(-1n).epochSeconds).toBe(0);
|
||||
expect(new Temporal.Instant(-999_999_999n).epochSeconds).toBe(0);
|
||||
expect(new Temporal.Instant(-1_000_000_000n).epochSeconds).toBe(-1);
|
||||
expect(new Temporal.Instant(-1_500_000_000n).epochSeconds).toBe(-1);
|
||||
expect(new Temporal.Instant(-1_999_999_999n).epochSeconds).toBe(-1);
|
||||
expect(new Temporal.Instant(-2_000_000_000n).epochSeconds).toBe(-2);
|
||||
expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochSeconds).toBe(
|
||||
-8_640_000_000_000
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.Instant.prototype, "epochSeconds", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,20 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.equals).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant1 = new Temporal.Instant(111n);
|
||||
expect(instant1.equals(instant1));
|
||||
const instant2 = new Temporal.Instant(999n);
|
||||
expect(!instant1.equals(instant2));
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.equals.call("foo", 1, 2);
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,80 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.round).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1111111111111n);
|
||||
expect(instant.round({ smallestUnit: "second" }).epochNanoseconds).toBe(1111000000000n);
|
||||
expect(
|
||||
instant.round({ smallestUnit: "second", roundingMode: "ceil" }).epochNanoseconds
|
||||
).toBe(1112000000000n);
|
||||
expect(
|
||||
instant.round({ smallestUnit: "minute", roundingIncrement: 30, roundingMode: "floor" })
|
||||
.epochNanoseconds
|
||||
).toBe(0n);
|
||||
expect(
|
||||
instant.round({
|
||||
smallestUnit: "minute",
|
||||
roundingIncrement: 30,
|
||||
roundingMode: "halfExpand",
|
||||
}).epochNanoseconds
|
||||
).toBe(1800000000000n);
|
||||
});
|
||||
|
||||
test("string argument is implicitly converted to options object", () => {
|
||||
const instant = new Temporal.Instant(1111111111111n);
|
||||
expect(
|
||||
instant.round("second").equals(instant.round({ smallestUnit: "second" }))
|
||||
).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.round.call("foo", {});
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
|
||||
test("missing options object", () => {
|
||||
expect(() => {
|
||||
const instant = new Temporal.Instant(1n);
|
||||
instant.round();
|
||||
}).toThrowWithMessage(TypeError, "Required options object is missing or undefined");
|
||||
});
|
||||
|
||||
test("invalid rounding mode", () => {
|
||||
expect(() => {
|
||||
const instant = new Temporal.Instant(1n);
|
||||
instant.round({ smallestUnit: "second", roundingMode: "serenityOS" });
|
||||
}).toThrowWithMessage(RangeError, "is not a valid value for option roundingMode");
|
||||
});
|
||||
|
||||
test("invalid smallest unit", () => {
|
||||
expect(() => {
|
||||
const instant = new Temporal.Instant(1n);
|
||||
instant.round({ smallestUnit: "serenityOS" });
|
||||
}).toThrowWithMessage(RangeError, "is not a valid value for option smallestUnit");
|
||||
});
|
||||
|
||||
test("increment may not be NaN", () => {
|
||||
expect(() => {
|
||||
const instant = new Temporal.Instant(1n);
|
||||
instant.round({ smallestUnit: "second", roundingIncrement: NaN });
|
||||
}).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement");
|
||||
});
|
||||
|
||||
test("increment may smaller than 1 or larger than maximum", () => {
|
||||
const instant = new Temporal.Instant(1n);
|
||||
expect(() => {
|
||||
instant.round({ smallestUnit: "second", roundingIncrement: -1 });
|
||||
}).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement");
|
||||
expect(() => {
|
||||
instant.round({ smallestUnit: "second", roundingIncrement: 0 });
|
||||
}).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement");
|
||||
expect(() => {
|
||||
instant.round({ smallestUnit: "second", roundingIncrement: Infinity });
|
||||
}).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement");
|
||||
});
|
||||
});
|
|
@ -1,190 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.since).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant1 = new Temporal.Instant(1625614920000000000n);
|
||||
const instant2 = new Temporal.Instant(0n);
|
||||
expect(instant1.since(instant2).seconds).toBe(1625614920);
|
||||
expect(instant1.since(instant2, { largestUnit: "hour" }).hours).toBe(451559);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.since.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
||||
|
||||
describe("rounding modes", () => {
|
||||
const earlier = new Temporal.Instant(
|
||||
217178610_123_456_789n /* 1976-11-18T15:23:30.123456789Z */
|
||||
);
|
||||
const later = new Temporal.Instant(
|
||||
1572345998_271_986_289n /* 2019-10-29T10:46:38.271986289Z */
|
||||
);
|
||||
const largestUnit = "hours";
|
||||
|
||||
test("'ceil' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376436H", "-PT376435H"],
|
||||
["minutes", "PT376435H24M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M9S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.148S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "ceil";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'expand' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376436H", "-PT376436H"],
|
||||
["minutes", "PT376435H24M", "-PT376435H24M"],
|
||||
["seconds", "PT376435H23M9S", "-PT376435H23M9S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "expand";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'floor' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376436H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H24M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M9S"],
|
||||
["milliseconds", "PT376435H23M8.148S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "floor";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfCeil' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfCeil";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfEven' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfEven";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfExpand' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfExpand";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfFloor' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfFloor";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfTrunc' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.148529S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfTrunc";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sincePositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(sinceNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,59 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.subtract).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921000000000n);
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 4, 5, 6);
|
||||
expect(instant.subtract(duration).epochNanoseconds).toBe(1625611197995994994n);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.subtract.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
|
||||
test("invalid nanoseconds value, positive", () => {
|
||||
const instant = new Temporal.Instant(8_640_000_000_000_000_000_000n);
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1);
|
||||
expect(() => {
|
||||
instant.subtract(duration);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid nanoseconds value, negative", () => {
|
||||
const instant = new Temporal.Instant(-8_640_000_000_000_000_000_000n);
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||
expect(() => {
|
||||
instant.subtract(duration);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
|
||||
);
|
||||
});
|
||||
|
||||
test("disallowed fields", () => {
|
||||
const instant = new Temporal.Instant(1625614921000000000n);
|
||||
for (const [args, property] of [
|
||||
[[123, 0, 0, 0], "years"],
|
||||
[[0, 123, 0, 0], "months"],
|
||||
[[0, 0, 123, 0], "weeks"],
|
||||
[[0, 0, 0, 123], "days"],
|
||||
]) {
|
||||
const duration = new Temporal.Duration(...args);
|
||||
expect(() => {
|
||||
instant.subtract(duration);
|
||||
}).toThrowWithMessage(
|
||||
RangeError,
|
||||
`Invalid value for duration property '${property}': must be zero, got 123`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Instant.prototype.toJSON).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
expect(instant.toJSON()).toBe("2021-07-06T23:42:01.123456789Z");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.toJSON.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Instant.prototype.toLocaleString).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
expect(instant.toLocaleString()).toBe("2021-07-06T23:42:01.123456789Z");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.toLocaleString.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,72 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Instant.prototype.toString).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
expect(instant.toString()).toBe("2021-07-06T23:42:01.123456789Z");
|
||||
});
|
||||
|
||||
test("timeZone option", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
const options = { timeZone: new Temporal.TimeZone("+01:30") };
|
||||
expect(instant.toString(options)).toBe("2021-07-07T01:12:01.123456789+01:30");
|
||||
});
|
||||
|
||||
test("fractionalSecondDigits option", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456000n);
|
||||
const values = [
|
||||
["auto", "2021-07-06T23:42:01.123456Z"],
|
||||
[0, "2021-07-06T23:42:01Z"],
|
||||
[1, "2021-07-06T23:42:01.1Z"],
|
||||
[2, "2021-07-06T23:42:01.12Z"],
|
||||
[3, "2021-07-06T23:42:01.123Z"],
|
||||
[4, "2021-07-06T23:42:01.1234Z"],
|
||||
[5, "2021-07-06T23:42:01.12345Z"],
|
||||
[6, "2021-07-06T23:42:01.123456Z"],
|
||||
[7, "2021-07-06T23:42:01.1234560Z"],
|
||||
[8, "2021-07-06T23:42:01.12345600Z"],
|
||||
[9, "2021-07-06T23:42:01.123456000Z"],
|
||||
];
|
||||
for (const [fractionalSecondDigits, expected] of values) {
|
||||
const options = { fractionalSecondDigits };
|
||||
expect(instant.toString(options)).toBe(expected);
|
||||
}
|
||||
|
||||
// Ignored when smallestUnit is given
|
||||
expect(instant.toString({ smallestUnit: "minute", fractionalSecondDigits: 9 })).toBe(
|
||||
"2021-07-06T23:42Z"
|
||||
);
|
||||
});
|
||||
|
||||
test("smallestUnit option", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
const values = [
|
||||
["minute", "2021-07-06T23:42Z"],
|
||||
["second", "2021-07-06T23:42:01Z"],
|
||||
["millisecond", "2021-07-06T23:42:01.123Z"],
|
||||
["microsecond", "2021-07-06T23:42:01.123456Z"],
|
||||
["nanosecond", "2021-07-06T23:42:01.123456789Z"],
|
||||
];
|
||||
for (const [smallestUnit, expected] of values) {
|
||||
const options = { smallestUnit };
|
||||
expect(instant.toString(options)).toBe(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.toString.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
const instant = new Temporal.Instant(0n);
|
||||
expect(() => {
|
||||
instant.toString({ timeZone: {} });
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
});
|
|
@ -1,54 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.toZonedDateTime).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = instant.toZonedDateTime({ calendar, timeZone });
|
||||
expect(zonedDateTime.year).toBe(2021);
|
||||
expect(zonedDateTime.month).toBe(7);
|
||||
expect(zonedDateTime.day).toBe(6);
|
||||
expect(zonedDateTime.hour).toBe(23);
|
||||
expect(zonedDateTime.minute).toBe(42);
|
||||
expect(zonedDateTime.second).toBe(1);
|
||||
expect(zonedDateTime.millisecond).toBe(123);
|
||||
expect(zonedDateTime.microsecond).toBe(456);
|
||||
expect(zonedDateTime.nanosecond).toBe(789);
|
||||
expect(zonedDateTime.calendar).toBe(calendar);
|
||||
expect(zonedDateTime.timeZone).toBe(timeZone);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.toZonedDateTime.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
|
||||
test("item argument must be an object", () => {
|
||||
const instant = new Temporal.Instant(0n);
|
||||
for (const value of [123, NaN, Infinity, true, false, null, undefined]) {
|
||||
expect(() => {
|
||||
instant.toZonedDateTime(value);
|
||||
}).toThrowWithMessage(TypeError, `${value} is not an object`);
|
||||
}
|
||||
});
|
||||
|
||||
test("item argument must have a 'calendar' property", () => {
|
||||
const instant = new Temporal.Instant(0n);
|
||||
expect(() => {
|
||||
instant.toZonedDateTime({});
|
||||
}).toThrowWithMessage(TypeError, "Required property calendar is missing or undefined");
|
||||
});
|
||||
|
||||
test("item argument must have a 'timeZone' property", () => {
|
||||
const instant = new Temporal.Instant(0n);
|
||||
expect(() => {
|
||||
instant.toZonedDateTime({ calendar: {} });
|
||||
}).toThrowWithMessage(TypeError, "Required property timeZone is missing or undefined");
|
||||
});
|
||||
});
|
|
@ -1,55 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.toZonedDateTimeISO).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
const zonedDateTime = instant.toZonedDateTimeISO("UTC");
|
||||
expect(zonedDateTime.year).toBe(2021);
|
||||
expect(zonedDateTime.month).toBe(7);
|
||||
expect(zonedDateTime.day).toBe(6);
|
||||
expect(zonedDateTime.hour).toBe(23);
|
||||
expect(zonedDateTime.minute).toBe(42);
|
||||
expect(zonedDateTime.second).toBe(1);
|
||||
expect(zonedDateTime.millisecond).toBe(123);
|
||||
expect(zonedDateTime.microsecond).toBe(456);
|
||||
expect(zonedDateTime.nanosecond).toBe(789);
|
||||
expect(zonedDateTime.calendar.id).toBe("iso8601");
|
||||
expect(zonedDateTime.timeZone.id).toBe("UTC");
|
||||
});
|
||||
|
||||
test("custom time zone object", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = instant.toZonedDateTimeISO({ timeZone });
|
||||
expect(zonedDateTime.timeZone).toBe(timeZone);
|
||||
});
|
||||
|
||||
test("avoids extra timeZone property lookup", () => {
|
||||
const instant = new Temporal.Instant(1625614921123456789n);
|
||||
|
||||
let timesGetterCalled = 0;
|
||||
const timeZoneObject = {
|
||||
get timeZone() {
|
||||
timesGetterCalled++;
|
||||
return "UTC";
|
||||
},
|
||||
|
||||
toString() {
|
||||
return "UTC";
|
||||
},
|
||||
};
|
||||
|
||||
instant.toZonedDateTimeISO({ timeZone: timeZoneObject });
|
||||
expect(timesGetterCalled).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.toZonedDateTimeISO.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
|
@ -1,190 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Instant.prototype.until).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const instant1 = new Temporal.Instant(0n);
|
||||
const instant2 = new Temporal.Instant(1625614920000000000n);
|
||||
expect(instant1.until(instant2).seconds).toBe(1625614920);
|
||||
expect(instant1.until(instant2, { largestUnit: "hour" }).hours).toBe(451559);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.Instant object", () => {
|
||||
expect(() => {
|
||||
Temporal.Instant.prototype.until.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant");
|
||||
});
|
||||
});
|
||||
|
||||
describe("rounding modes", () => {
|
||||
const earlier = new Temporal.Instant(
|
||||
217178610_123_456_789n /* 1976-11-18T15:23:30.123456789Z */
|
||||
);
|
||||
const later = new Temporal.Instant(
|
||||
1572345998_271_986_289n /* 2019-10-29T10:46:38.271986289Z */
|
||||
);
|
||||
const largestUnit = "hours";
|
||||
|
||||
test("'ceil' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376436H", "-PT376435H"],
|
||||
["minutes", "PT376435H24M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M9S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.148S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "ceil";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'expand' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376436H", "-PT376436H"],
|
||||
["minutes", "PT376435H24M", "-PT376435H24M"],
|
||||
["seconds", "PT376435H23M9S", "-PT376435H23M9S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "expand";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'floor' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376436H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H24M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M9S"],
|
||||
["milliseconds", "PT376435H23M8.148S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "floor";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfCeil' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfCeil";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfEven' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfEven";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfExpand' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfExpand";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfFloor' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfFloor";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
|
||||
test("'halfTrunc' rounding mode", () => {
|
||||
const expected = [
|
||||
["hours", "PT376435H", "-PT376435H"],
|
||||
["minutes", "PT376435H23M", "-PT376435H23M"],
|
||||
["seconds", "PT376435H23M8S", "-PT376435H23M8S"],
|
||||
["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"],
|
||||
["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.148529S"],
|
||||
["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"],
|
||||
];
|
||||
|
||||
const roundingMode = "halfTrunc";
|
||||
expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => {
|
||||
const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilPositive.toString()).toBe(expectedPositive);
|
||||
|
||||
const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode });
|
||||
expect(untilNegative.toString()).toBe(expectedNegative);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
describe("errors", () => {
|
||||
test("throws TypeError", () => {
|
||||
expect(() => {
|
||||
new Temporal.Instant(0n).valueOf();
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert Temporal.Instant to a primitive value");
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
test("basic functionality", () => {
|
||||
expect(Temporal.Now[Symbol.toStringTag]).toBe("Temporal.Now");
|
||||
});
|
|
@ -1,60 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Now.plainDate).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainDate = Temporal.Now.plainDate(calendar);
|
||||
expect(plainDate).toBeInstanceOf(Temporal.PlainDate);
|
||||
expect(plainDate.calendar).toBe(calendar);
|
||||
});
|
||||
|
||||
test("custom time zone", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return 86399999999999;
|
||||
},
|
||||
};
|
||||
const plainDate = Temporal.Now.plainDate(calendar, "UTC");
|
||||
const plainDateWithOffset = Temporal.Now.plainDate(calendar, timeZone);
|
||||
if (plainDate.dayOfYear === plainDate.daysInYear) {
|
||||
expect(plainDateWithOffset.year).toBe(plainDate.year + 1);
|
||||
expect(plainDateWithOffset.month).toBe(1);
|
||||
expect(plainDateWithOffset.day).toBe(1);
|
||||
} else {
|
||||
expect(plainDateWithOffset.year).toBe(plainDate.year);
|
||||
if (plainDate.day === plainDate.daysInMonth) {
|
||||
expect(plainDateWithOffset.month).toBe(plainDate.month + 1);
|
||||
expect(plainDateWithOffset.day).toBe(1);
|
||||
} else {
|
||||
expect(plainDateWithOffset.month).toBe(plainDate.month);
|
||||
expect(plainDateWithOffset.day).toBe(plainDate.day + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("cannot have a time zone with more than a day", () => {
|
||||
[86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return offset;
|
||||
},
|
||||
};
|
||||
expect(() => Temporal.Now.plainDate(calendar, timeZone)).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
expect(() => {
|
||||
Temporal.Now.plainDate({}, {});
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
});
|
|
@ -1,57 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Now.plainDateISO).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDate = Temporal.Now.plainDateISO();
|
||||
expect(plainDate).toBeInstanceOf(Temporal.PlainDate);
|
||||
expect(plainDate.calendar.id).toBe("iso8601");
|
||||
});
|
||||
|
||||
test("custom time zone", () => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return 86399999999999;
|
||||
},
|
||||
};
|
||||
const plainDate = Temporal.Now.plainDateISO("UTC");
|
||||
const plainDateWithOffset = Temporal.Now.plainDateISO(timeZone);
|
||||
if (plainDate.dayOfYear === plainDate.daysInYear) {
|
||||
expect(plainDateWithOffset.year).toBe(plainDate.year + 1);
|
||||
expect(plainDateWithOffset.month).toBe(1);
|
||||
expect(plainDateWithOffset.day).toBe(1);
|
||||
} else {
|
||||
expect(plainDateWithOffset.year).toBe(plainDate.year);
|
||||
if (plainDate.day === plainDate.daysInMonth) {
|
||||
expect(plainDateWithOffset.month).toBe(plainDate.month + 1);
|
||||
expect(plainDateWithOffset.day).toBe(1);
|
||||
} else {
|
||||
expect(plainDateWithOffset.month).toBe(plainDate.month);
|
||||
expect(plainDateWithOffset.day).toBe(plainDate.day + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("cannot have a time zone with more than a day", () => {
|
||||
[86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return offset;
|
||||
},
|
||||
};
|
||||
expect(() => Temporal.Now.plainDateISO(timeZone)).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
expect(() => {
|
||||
Temporal.Now.plainDateISO({});
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
});
|
|
@ -1,109 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Now.plainDateTime).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const plainDateTime = Temporal.Now.plainDateTime(calendar);
|
||||
expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime);
|
||||
expect(plainDateTime.calendar).toBe(calendar);
|
||||
});
|
||||
|
||||
const plainDateTimeToEpochSeconds = plainDateTime =>
|
||||
(plainDateTime.year - 1970) * 31_556_952 +
|
||||
plainDateTime.dayOfYear * 86_400 +
|
||||
plainDateTime.hour * 3_600 +
|
||||
plainDateTime.minute * 60 +
|
||||
plainDateTime.second +
|
||||
plainDateTime.millisecond / 1_000 +
|
||||
plainDateTime.microsecond / 1_000_000 +
|
||||
plainDateTime.nanosecond / 1_000_000_000;
|
||||
|
||||
let timeZoneTested = false;
|
||||
|
||||
// Note: We test both positive and negative timezones because one might cross a year boundary.
|
||||
// Since a year does not have a fixed amount of seconds because it can be a leap year,
|
||||
// we cannot have a correct constant for seconds per year which is always correct.
|
||||
// However, by assuming years are at least 2 days long we can simply try the positive
|
||||
// and negative timezones and skip one if we jump the year. To ensure at least one is
|
||||
// tested we have the timeZoneTested which is only set to true if one of the tests passed.
|
||||
|
||||
// FIXME: The custom time zone tests are disabled due to being flaky. See:
|
||||
// https://github.com/SerenityOS/serenity/issues/20806
|
||||
|
||||
test.skip("custom time zone positive", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return 86399999999999;
|
||||
},
|
||||
};
|
||||
|
||||
const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => {
|
||||
return [
|
||||
Temporal.Now.plainDateTime(calendar, "UTC"),
|
||||
Temporal.Now.plainDateTime(calendar, timeZone),
|
||||
];
|
||||
});
|
||||
|
||||
if (plainDateTime.year !== plainDateTimeWithOffset.year) return;
|
||||
|
||||
const differenceSeconds =
|
||||
plainDateTimeToEpochSeconds(plainDateTimeWithOffset) -
|
||||
plainDateTimeToEpochSeconds(plainDateTime);
|
||||
expect(Math.floor(differenceSeconds)).toBe(86400);
|
||||
timeZoneTested = true;
|
||||
});
|
||||
|
||||
test.skip("custom time zone negative", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return -86399999999999;
|
||||
},
|
||||
};
|
||||
|
||||
const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => {
|
||||
return [
|
||||
Temporal.Now.plainDateTime(calendar, "UTC"),
|
||||
Temporal.Now.plainDateTime(calendar, timeZone),
|
||||
];
|
||||
});
|
||||
|
||||
if (plainDateTime.year !== plainDateTimeWithOffset.year) return;
|
||||
|
||||
const differenceSeconds =
|
||||
plainDateTimeToEpochSeconds(plainDateTimeWithOffset) -
|
||||
plainDateTimeToEpochSeconds(plainDateTime);
|
||||
expect(Math.floor(differenceSeconds)).toBe(-86400);
|
||||
timeZoneTested = true;
|
||||
});
|
||||
|
||||
test.skip("custom time zone test was executed", () => {
|
||||
expect(timeZoneTested).toBeTrue();
|
||||
});
|
||||
|
||||
test("cannot have a time zone with more than a day", () => {
|
||||
[86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return offset;
|
||||
},
|
||||
};
|
||||
expect(() => Temporal.Now.plainDateTime(calendar, timeZone)).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
expect(() => {
|
||||
Temporal.Now.plainDateTime({}, {});
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
});
|
|
@ -1,99 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Now.plainDateTimeISO).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDateTime = Temporal.Now.plainDateTimeISO();
|
||||
expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime);
|
||||
expect(plainDateTime.calendar.id).toBe("iso8601");
|
||||
});
|
||||
|
||||
const plainDateTimeToEpochSeconds = plainDateTime =>
|
||||
(plainDateTime.year - 1970) * 31_556_952 +
|
||||
plainDateTime.dayOfYear * 86_400 +
|
||||
plainDateTime.hour * 3_600 +
|
||||
plainDateTime.minute * 60 +
|
||||
plainDateTime.second +
|
||||
plainDateTime.millisecond / 1_000 +
|
||||
plainDateTime.microsecond / 1_000_000 +
|
||||
plainDateTime.nanosecond / 1_000_000_000;
|
||||
|
||||
let timeZoneTested = false;
|
||||
|
||||
// Note: We test both positive and negative timezones because one might cross a year boundary.
|
||||
// Since a year does not have a fixed amount of seconds because it can be a leap year,
|
||||
// we cannot have a correct constant for seconds per year which is always correct.
|
||||
// However, by assuming years are at least 2 days long we can simply try the positive
|
||||
// and negative timezones and skip one if we jump the year. To ensure at least one is
|
||||
// tested we have the timeZoneTested which is only set to true if one of the tests passed.
|
||||
|
||||
// FIXME: The custom time zone tests are disabled due to being flaky. See:
|
||||
// https://github.com/SerenityOS/serenity/issues/20806
|
||||
|
||||
test.skip("custom time zone (positive)", () => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return 86399999999999;
|
||||
},
|
||||
};
|
||||
|
||||
const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => {
|
||||
return [Temporal.Now.plainDateTimeISO("UTC"), Temporal.Now.plainDateTimeISO(timeZone)];
|
||||
});
|
||||
|
||||
if (plainDateTime.year !== plainDateTimeWithOffset.year) return;
|
||||
|
||||
const differenceSeconds =
|
||||
plainDateTimeToEpochSeconds(plainDateTimeWithOffset) -
|
||||
plainDateTimeToEpochSeconds(plainDateTime);
|
||||
expect(Math.floor(differenceSeconds)).toBe(86400);
|
||||
timeZoneTested = true;
|
||||
});
|
||||
|
||||
test.skip("custom time zone (negative)", () => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return -86399999999999;
|
||||
},
|
||||
};
|
||||
|
||||
const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => {
|
||||
return [Temporal.Now.plainDateTimeISO("UTC"), Temporal.Now.plainDateTimeISO(timeZone)];
|
||||
});
|
||||
|
||||
if (plainDateTime.year !== plainDateTimeWithOffset.year) return;
|
||||
|
||||
const differenceSeconds =
|
||||
plainDateTimeToEpochSeconds(plainDateTimeWithOffset) -
|
||||
plainDateTimeToEpochSeconds(plainDateTime);
|
||||
expect(Math.floor(differenceSeconds)).toBe(-86400);
|
||||
timeZoneTested = true;
|
||||
});
|
||||
|
||||
test.skip("custom time zone test was executed", () => {
|
||||
expect(timeZoneTested).toBeTrue();
|
||||
});
|
||||
|
||||
test("cannot have a time zone with more than a day", () => {
|
||||
[86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return offset;
|
||||
},
|
||||
};
|
||||
expect(() => Temporal.Now.plainDateTimeISO(timeZone)).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
expect(() => {
|
||||
Temporal.Now.plainDateTimeISO({});
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
});
|
|
@ -1,44 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Now.plainTimeISO).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainTime = Temporal.Now.plainTimeISO();
|
||||
expect(plainTime).toBeInstanceOf(Temporal.PlainTime);
|
||||
expect(plainTime.calendar.id).toBe("iso8601");
|
||||
});
|
||||
|
||||
test("custom time zone", () => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return 86399999999999;
|
||||
},
|
||||
};
|
||||
const plainTime = Temporal.Now.plainTimeISO("UTC");
|
||||
const plainTimeWithOffset = Temporal.Now.plainTimeISO(timeZone);
|
||||
// FIXME: Compare these in a sensible way
|
||||
});
|
||||
|
||||
test("cannot have a time zone with more than a day", () => {
|
||||
[86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => {
|
||||
const timeZone = {
|
||||
getOffsetNanosecondsFor() {
|
||||
return offset;
|
||||
},
|
||||
};
|
||||
expect(() => Temporal.Now.plainTimeISO(timeZone)).toThrowWithMessage(
|
||||
RangeError,
|
||||
"Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
expect(() => {
|
||||
Temporal.Now.plainTimeISO({});
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.Now.zonedDateTime).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const zonedDateTime = Temporal.Now.zonedDateTime(calendar);
|
||||
expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime);
|
||||
expect(zonedDateTime.calendar).toBe(calendar);
|
||||
});
|
||||
|
||||
test("with time zone", () => {
|
||||
const calendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = Temporal.Now.zonedDateTime(calendar, timeZone);
|
||||
expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime);
|
||||
expect(zonedDateTime.calendar).toBe(calendar);
|
||||
expect(zonedDateTime.timeZone).toBe(timeZone);
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Temporal.Now.zonedDateTimeISO).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const zonedDateTime = Temporal.Now.zonedDateTimeISO();
|
||||
expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime);
|
||||
expect(zonedDateTime.calendar.id).toBe("iso8601");
|
||||
});
|
||||
|
||||
test("with time zone", () => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = Temporal.Now.zonedDateTimeISO(timeZone);
|
||||
expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime);
|
||||
expect(zonedDateTime.calendar.id).toBe("iso8601");
|
||||
expect(zonedDateTime.timeZone).toBe(timeZone);
|
||||
});
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 2", () => {
|
||||
expect(Temporal.PlainDate.compare).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDate1 = new Temporal.PlainDate(2021, 7, 26);
|
||||
expect(Temporal.PlainDate.compare(plainDate1, plainDate1)).toBe(0);
|
||||
const plainDate2 = new Temporal.PlainDate(2021, 7, 27);
|
||||
expect(Temporal.PlainDate.compare(plainDate1, plainDate2)).toBe(-1);
|
||||
expect(Temporal.PlainDate.compare(plainDate2, plainDate1)).toBe(1);
|
||||
});
|
||||
});
|
|
@ -1,61 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.PlainDate.from).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("PlainDate instance argument", () => {
|
||||
const plainDate = new Temporal.PlainDate(2021, 7, 26);
|
||||
const createdPlainDate = Temporal.PlainDate.from(plainDate);
|
||||
expect(createdPlainDate.year).toBe(2021);
|
||||
expect(createdPlainDate.month).toBe(7);
|
||||
expect(createdPlainDate.day).toBe(26);
|
||||
});
|
||||
|
||||
test("PlainDateTime instance argument", () => {
|
||||
const plainDateTime = new Temporal.PlainDateTime(2021, 7, 26, 1, 2, 3);
|
||||
const createdPlainDate = Temporal.PlainDate.from(plainDateTime);
|
||||
expect(createdPlainDate.year).toBe(2021);
|
||||
expect(createdPlainDate.month).toBe(7);
|
||||
expect(createdPlainDate.day).toBe(26);
|
||||
});
|
||||
|
||||
test("ZonedDateTime instance argument", () => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, timeZone);
|
||||
const createdPlainDate = Temporal.PlainDate.from(zonedDateTime);
|
||||
expect(createdPlainDate.year).toBe(2021);
|
||||
expect(createdPlainDate.month).toBe(7);
|
||||
expect(createdPlainDate.day).toBe(26);
|
||||
});
|
||||
|
||||
test("PlainDate string argument", () => {
|
||||
const createdPlainDate = Temporal.PlainDate.from("2021-07-26");
|
||||
expect(createdPlainDate.year).toBe(2021);
|
||||
expect(createdPlainDate.month).toBe(7);
|
||||
expect(createdPlainDate.day).toBe(26);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => {
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(0n, {});
|
||||
expect(() => {
|
||||
Temporal.PlainDate.from(zonedDateTime);
|
||||
}).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined");
|
||||
});
|
||||
|
||||
test("invalid date time string", () => {
|
||||
expect(() => {
|
||||
Temporal.PlainDate.from("foo");
|
||||
}).toThrowWithMessage(RangeError, "Invalid date time string 'foo'");
|
||||
});
|
||||
|
||||
test("extended year must not be negative zero", () => {
|
||||
expect(() => {
|
||||
Temporal.PlainDate.from("-000000-01-01");
|
||||
}).toThrowWithMessage(RangeError, "Invalid date time string '-000000-01-01'");
|
||||
expect(() => {
|
||||
Temporal.PlainDate.from("−000000-01-01"); // U+2212
|
||||
}).toThrowWithMessage(RangeError, "Invalid date time string '−000000-01-01'");
|
||||
});
|
||||
});
|
|
@ -1,53 +0,0 @@
|
|||
describe("errors", () => {
|
||||
test("called without new", () => {
|
||||
expect(() => {
|
||||
Temporal.PlainDate();
|
||||
}).toThrowWithMessage(
|
||||
TypeError,
|
||||
"Temporal.PlainDate constructor must be called with 'new'"
|
||||
);
|
||||
});
|
||||
|
||||
test("cannot pass Infinity", () => {
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(0, Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(0, 0, Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(-Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(0, -Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(0, 0, -Infinity);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
});
|
||||
|
||||
test("cannot pass invalid ISO month/day", () => {
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(0, 0, 1);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
expect(() => {
|
||||
new Temporal.PlainDate(0, 1, 0);
|
||||
}).toThrowWithMessage(RangeError, "Invalid plain date");
|
||||
});
|
||||
});
|
||||
|
||||
describe("normal behavior", () => {
|
||||
test("length is 3", () => {
|
||||
expect(Temporal.PlainDate).toHaveLength(3);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDate = new Temporal.PlainDate(2021, 7, 19);
|
||||
expect(typeof plainDate).toBe("object");
|
||||
expect(plainDate).toBeInstanceOf(Temporal.PlainDate);
|
||||
expect(Object.getPrototypeOf(plainDate)).toBe(Temporal.PlainDate.prototype);
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
test("basic functionality", () => {
|
||||
expect(Temporal.PlainDate.prototype[Symbol.toStringTag]).toBe("Temporal.PlainDate");
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.PlainDate.prototype.add).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const result = plainDate.add(new Temporal.Duration(51, 6, 0, 5));
|
||||
expect(result.equals(new Temporal.PlainDate(2021, 7, 6))).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Temporal.PlainDate.prototype.add.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const calendar = { hello: "friends" };
|
||||
const plainDate = new Temporal.PlainDate(1, 1, 1, calendar);
|
||||
expect(plainDate.calendar).toBe(calendar);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "calendar", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("calendarId basic functionality", () => {
|
||||
const calendar = "iso8601";
|
||||
const plainDate = new Temporal.PlainDate(2000, 5, 1, calendar);
|
||||
expect(plainDate.calendarId).toBe("iso8601");
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "calendarId", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(date.day).toBe(23);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "day", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(date.dayOfWeek).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "dayOfWeek", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(date.dayOfYear).toBe(204);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "dayOfYear", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(date.daysInMonth).toBe(31);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "daysInMonth", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
describe("correct behavior", () => {
|
||||
test("basic functionality", () => {
|
||||
const date = new Temporal.PlainDate(2021, 7, 23);
|
||||
expect(date.daysInWeek).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainDate object", () => {
|
||||
expect(() => {
|
||||
Reflect.get(Temporal.PlainDate.prototype, "daysInWeek", "foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate");
|
||||
});
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue