blob: ad5f244d91438fdef31a72efc26d433efa3ed1b9 [file] [log] [blame]
//@ requireOptions("--useTemporal=1")
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`expected ${expected} but got ${actual}`);
}
function shouldThrow(func, errorType, message) {
let error;
try {
func();
} catch (e) {
error = e;
}
if (!(error instanceof errorType))
throw new Error(`Expected ${errorType.name}!`);
if (message !== undefined)
shouldBe(String(error), message);
}
shouldBe(Temporal.PlainTime instanceof Function, true);
shouldBe(Temporal.PlainTime.length, 0);
shouldBe(Object.getOwnPropertyDescriptor(Temporal.PlainTime, 'prototype').writable, false);
shouldBe(Object.getOwnPropertyDescriptor(Temporal.PlainTime, 'prototype').enumerable, false);
shouldBe(Object.getOwnPropertyDescriptor(Temporal.PlainTime, 'prototype').configurable, false);
shouldBe(Temporal.PlainTime.prototype.constructor, Temporal.PlainTime);
{
let time = new Temporal.PlainTime(0, 1, 2, 3, 4, 5, 6, 7);
shouldBe(String(time), `00:01:02.003004005`);
shouldBe(time.hour, 0);
shouldBe(time.minute, 1);
shouldBe(time.second, 2);
shouldBe(time.millisecond, 3);
shouldBe(time.microsecond, 4);
shouldBe(time.nanosecond, 5);
}
{
let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0);
shouldBe(String(time), `00:00:00`);
shouldBe(time.hour, 0);
shouldBe(time.minute, 0);
shouldBe(time.second, 0);
shouldBe(time.millisecond, 0);
shouldBe(time.microsecond, 0);
shouldBe(time.nanosecond, 0);
}
{
let time = new Temporal.PlainTime(23, 59, 59, 999, 999, 999);
shouldBe(String(time), `23:59:59.999999999`);
shouldBe(time.hour, 23);
shouldBe(time.minute, 59);
shouldBe(time.second, 59);
shouldBe(time.millisecond, 999);
shouldBe(time.microsecond, 999);
shouldBe(time.nanosecond, 999);
}
{
let time = new Temporal.PlainTime(23, 59, 59, 999, 999, 999);
shouldBe(String(time), `23:59:59.999999999`);
shouldBe(time.hour, 23);
shouldBe(time.minute, 59);
shouldBe(time.second, 59);
shouldBe(time.millisecond, 999);
shouldBe(time.microsecond, 999);
shouldBe(time.nanosecond, 999);
}
{
// We accept 60 seconds, but interpret it as 59 seconds.
// https://tc39.es/proposal-temporal/#sec-temporal-parseisodatetime step 13
let time = Temporal.PlainTime.from("23:59:60.999999999");
shouldBe(String(time), `23:59:59.999999999`);
shouldBe(time.hour, 23);
shouldBe(time.minute, 59);
shouldBe(time.second, 59);
shouldBe(time.millisecond, 999);
shouldBe(time.microsecond, 999);
shouldBe(time.nanosecond, 999);
}
{
let time = Temporal.PlainTime.from("2021-09-04T23:14:26.100200300");
shouldBe(String(time), `23:14:26.1002003`);
shouldBe(time.hour, 23);
shouldBe(time.minute, 14);
shouldBe(time.second, 26);
shouldBe(time.millisecond, 100);
shouldBe(time.microsecond, 200);
shouldBe(time.nanosecond, 300);
}
shouldBe(String(Temporal.PlainTime.from('03')), `03:00:00`);
shouldBe(String(Temporal.PlainTime.from('0314')), `03:14:00`);
shouldBe(String(Temporal.PlainTime.from('031415')), `03:14:15`);
shouldBe(String(Temporal.PlainTime.from('03:14')), `03:14:00`);
shouldBe(String(Temporal.PlainTime.from('03:14:15')), `03:14:15`);
shouldBe(String(Temporal.PlainTime.from('03:24:30')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('2020-01')), `20:20:00`); // -01 UTC offset
shouldBe(String(Temporal.PlainTime.from('01-01')), `01:00:00`); // -01 UTC offset
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07t03:24:30')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30Z')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+20:20:59')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30-20:20:59')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30\u221220:20:59')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+10')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+1020')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+102030')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+10:20:30.05')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+10:20:30.123456789')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[Europe/Brussels]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[Europe/Brussels]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[UNKNOWN]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[.hey]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[_]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[_-]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[_/_]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[_-./_-.]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[_../_..]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[_./_.]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[Etc/GMT+20]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[Etc/GMT-20]')), `03:24:30`); // TimeZone error should be ignored.
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01:00]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01:00:00]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01:00:00.123]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01:00:00.12345]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01:00:00.12345678]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[+01:00:00.123456789]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[-01:00]')), `03:24:30`);
shouldBe(String(Temporal.PlainTime.from('1995-12-07 03:24:30+01:00[\u221201:00]')), `03:24:30`);
{
let time = Temporal.PlainTime.from('1995-12-07T03:24:30+01:00[Europe/Brussels]')
shouldBe(time === Temporal.PlainTime.from(time), false);
}
{
let time = Temporal.PlainTime.from({
hour: 19,
minute: 39,
second: 9,
millisecond: 68,
microsecond: 346,
nanosecond: 205
});
shouldBe(String(time), `19:39:09.068346205`);
// This is spec bug. Currently this throws an error. But possibly this should not throw an error.
// Tracked in https://github.com/tc39/proposal-temporal/issues/1803.
shouldThrow(() => {
Temporal.PlainTime.from({ hour: 19, minute: 39, second: 9 });
}, TypeError);
}
{
// Different overflow modes
shouldBe(String(Temporal.PlainTime.from({ hour: 15, minute: 60, second: 0, millisecond: 0, microsecond: 0, nanosecond: 0 }, { overflow: 'constrain' })), `15:59:00`);
shouldBe(String(Temporal.PlainTime.from({ hour: 15, minute: -1, second: 0, millisecond: 0, microsecond: 0, nanosecond: 0 }, { overflow: 'constrain' })), `15:00:00`);
}
shouldThrow(() => {
Temporal.PlainTime.from({ hour: 15, minute: 60, second: 0, millisecond: 0, microsecond: 0, nanosecond: 0 }, { overflow: 'reject' });
}, RangeError);
shouldThrow(() => {
Temporal.PlainTime.from({ hour: 15, minute: -1, second: 0, millisecond: 0, microsecond: 0, nanosecond: 0 }, { overflow: 'reject' });
}, RangeError);
shouldThrow(() => { new Temporal.PlainTime(-1); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(25); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(24); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(30); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(-Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, -1); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 60); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 61); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 77); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 100); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, -Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, -1); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 60); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 61); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 77); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 100); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, -Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, -1); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 1000); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 1001); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 50000); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 9999999999); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, -Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, -1); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 1000); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 1001); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 50000); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 9999999999); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, -Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, -1); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, 1000); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, 1001); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, 50000); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, 9999999999); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, Infinity); }, RangeError);
shouldThrow(() => { new Temporal.PlainTime(0, 0, 0, 0, 0, -Infinity); }, RangeError);
let failures = [
"",
"2020-01-01",
"23:59:61.999999999",
"1995-1207T03:24:30",
"199512-07T03:24:30",
"1995-12-07T03:24:30+20:20:60",
"1995-12-07T03:24:30+20:2050",
"1995-12-07T03:24:30+:",
"1995-12-07T03:24:30+2:50",
"1995-12-07T03:24:30+01:00[/]",
"1995-12-07T03:24:30+01:00[///]",
"1995-12-07T03:24:30+01:00[Hey/Hello",
"1995-12-07T03:24:30+01:00[]",
"1995-12-07T03:24:30+01:00[Hey/]",
"1995-12-07T03:24:30+01:00[..]",
"1995-12-07T03:24:30+01:00[.]",
"1995-12-07T03:24:30+01:00[./.]",
"1995-12-07T03:24:30+01:00[../..]",
"1995-12-07T03:24:30+01:00[-Hey/Hello]",
"1995-12-07T03:24:30+01:00[-]",
"1995-12-07T03:24:30+01:00[-/_]",
"1995-12-07T03:24:30+01:00[_/-]",
"1995-12-07T03:24:30+01:00[CocoaCappuccinoMatcha]",
"1995-12-07T03:24:30+01:00[Etc/GMT+50]",
"1995-12-07T03:24:30+01:00[Etc/GMT+0]",
"1995-12-07T03:24:30+01:00[Etc/GMT0]",
"1995-12-07T03:24:30+10:20:30.0123456789",
"1995-12-07 03:24:30+01:00[Etc/GMT\u221201]",
"1995-12-07 03:24:30+01:00[+02:00:00.0123456789]",
"1995-12-07 03:24:30+01:00[02:00:00.123456789]",
"1995-12-07 03:24:30+01:00[02:0000.123456789]",
"1995-12-07 03:24:30+01:00[0200:00.123456789]",
"1995-12-07 03:24:30+01:00[02:00:60.123456789]",
];
for (let text of failures) {
shouldThrow(() => {
print(String(Temporal.PlainTime.from(text)));
}, RangeError);
}
{
let one = Temporal.PlainTime.from('03:24');
let two = Temporal.PlainTime.from('01:24');
let three = Temporal.PlainTime.from('01:24:05');
let sorted = [one, two, three].sort(Temporal.PlainTime.compare);
shouldBe(sorted.join(' '), `01:24:00 01:24:05 03:24:00`);
}
shouldBe(String(Temporal.PlainTime.from("20:34").calendar), `iso8601`);
shouldBe(Temporal.PlainTime.from("20:34").calendar instanceof Temporal.Calendar, true);
{
let time = Temporal.PlainTime.from("20:34");
shouldBe(time.calendar, time.calendar);
}
{
let time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(String(time.round({ smallestUnit: 'hour' })), `20:00:00`);
shouldBe(String(time.round({ roundingIncrement: 30, smallestUnit: 'minute' })), `19:30:00`);
shouldBe(String(time.round({ roundingIncrement: 30, smallestUnit: 'minute', roundingMode: 'ceil' })), `20:00:00`);
}
{
let time = Temporal.PlainTime.from('19:39:09.068346205');
let other = Temporal.PlainTime.from('20:13:20.971398099');
shouldBe(time.equals(other), false);
shouldBe(time.equals(time), true);
}
{
let time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(time.toString(), `19:39:09.068346205`);
shouldBe(time.toString({ smallestUnit: 'minute' }), `19:39`);
shouldBe(time.toString({ fractionalSecondDigits: 0 }), `19:39:09`);
shouldBe(time.toString({ fractionalSecondDigits: 4 }), `19:39:09.0683`);
shouldBe(time.toString({ fractionalSecondDigits: 5, roundingMode: 'halfExpand' }), `19:39:09.06835`);
shouldBe(Temporal.PlainTime.from('19:39:09.000000205').toString({ fractionalSecondDigits: 4 }), `19:39:09.0000`);
}
{
const workBreak = {
type: 'mandatory',
name: 'Lunch',
startTime: new Temporal.PlainTime(12),
endTime: new Temporal.PlainTime(13)
};
const str = JSON.stringify(workBreak);
shouldBe(str, `{"type":"mandatory","name":"Lunch","startTime":"12:00:00","endTime":"13:00:00"}`);
function reviver(key, value) {
if (key.endsWith('Time')) return Temporal.PlainTime.from(value);
return value;
}
let object = JSON.parse(str, reviver);
shouldBe(object.startTime instanceof Temporal.PlainTime, true);
shouldBe(String(object.startTime), `12:00:00`);
shouldBe(object.endTime instanceof Temporal.PlainTime, true);
shouldBe(String(object.endTime), `13:00:00`);
}
shouldThrow(() => {
new Temporal.PlainTime(12).valueOf();
}, TypeError);
{
let time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(JSON.stringify(time.getISOFields()), `{"calendar":"iso8601","isoHour":19,"isoMicrosecond":346,"isoMillisecond":68,"isoMinute":39,"isoNanosecond":205,"isoSecond":9}`);
}
{
let max = 1 ** 53;
let time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(String(time.add({ minutes: 5, nanoseconds: 800 })), `19:44:09.068347005`);
time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(String(time.add({ hours: max, minutes: max, seconds: max, milliseconds: max, microseconds: max, nanoseconds: max })), `20:40:10.069347206`);
shouldBe(String(time.add(new Temporal.Duration(1, 1, 1, 1))), `19:39:09.068346205`);
shouldBe(String(time.add(new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, 1))), `20:40:10.069346205`);
shouldBe(String(time.add(new Temporal.Duration(0, 0, 0, 0, 30, 1, 1, 1))), `01:40:10.069346205`);
}
{
let max = 1 ** 53;
let time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(String(time.subtract({ minutes: 5, nanoseconds: 800 })), `19:34:09.068345405`);
time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(String(time.subtract({ hours: max, minutes: max, seconds: max, milliseconds: max, microseconds: max, nanoseconds: max })), `18:38:08.067345204`);
shouldBe(String(time.subtract(new Temporal.Duration(1, 1, 1, 1))), `19:39:09.068346205`);
shouldBe(String(time.subtract(new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, 1))), `18:38:08.067346205`);
shouldBe(String(time.subtract(new Temporal.Duration(0, 0, 0, 0, 30, 1, 1, 1))), `13:38:08.067346205`);
}
{
let time = Temporal.PlainTime.from('19:39:09.068346205');
shouldBe(String(time.add({ hours: 1 }).with({
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
nanosecond: 0
})), `20:00:00`);
}
{
let time = Temporal.PlainTime.from('20:13:20.971398099');
shouldBe(String(time.until(Temporal.PlainTime.from('22:39:09.068346205'))), `PT2H25M48.096948106S`);
shouldBe(String(time.until(Temporal.PlainTime.from('19:39:09.068346205'))), `-PT34M11.903051894S`);
shouldBe(String(time.until(Temporal.PlainTime.from('22:39:09.068346205'), { smallestUnit: 'second' })), `PT2H25M48S`);
}
{
let time = Temporal.PlainTime.from('20:13:20.971398099');
shouldBe(String(time.since(Temporal.PlainTime.from('19:39:09.068346205'))), `PT34M11.903051894S`);
shouldBe(String(time.since(Temporal.PlainTime.from('22:39:09.068346205'))), `-PT2H25M48.096948106S`);
}