mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 14:17:36 +00:00
LibJS: Implement Intl.DateTimeFormat.prototype.formatRange
This commit is contained in:
parent
1f35eda37b
commit
04f8fb07e1
7 changed files with 591 additions and 28 deletions
|
@ -0,0 +1,220 @@
|
|||
describe("errors", () => {
|
||||
test("called on non-DateTimeFormat object", () => {
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat.prototype.formatRange(1, 2);
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Intl.DateTimeFormat");
|
||||
});
|
||||
|
||||
test("called with undefined values", () => {
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange();
|
||||
}).toThrowWithMessage(TypeError, "startDate is undefined");
|
||||
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange(1);
|
||||
}).toThrowWithMessage(TypeError, "endDate is undefined");
|
||||
});
|
||||
|
||||
test("called with values that cannot be converted to numbers", () => {
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange(1, Symbol.hasInstance);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert symbol to number");
|
||||
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange(1n, 1);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
|
||||
});
|
||||
|
||||
test("time value cannot be clipped", () => {
|
||||
[NaN, -8.65e15, 8.65e15].forEach(d => {
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange(d, 1);
|
||||
}).toThrowWithMessage(RangeError, "Time value must be between -8.64E15 and 8.64E15");
|
||||
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange(1, d);
|
||||
}).toThrowWithMessage(RangeError, "Time value must be between -8.64E15 and 8.64E15");
|
||||
});
|
||||
});
|
||||
|
||||
test("called with values in bad order", () => {
|
||||
expect(() => {
|
||||
Intl.DateTimeFormat().formatRange(new Date(2021), new Date(1989));
|
||||
}).toThrowWithMessage(RangeError, "Start time 2021 is after end time 1989");
|
||||
});
|
||||
});
|
||||
|
||||
const d0 = Date.UTC(1989, 0, 23, 7, 8, 9, 45);
|
||||
const d1 = Date.UTC(2021, 11, 7, 17, 40, 50, 456);
|
||||
|
||||
describe("equal dates are squashed", () => {
|
||||
test("with date fields", () => {
|
||||
const en = new Intl.DateTimeFormat("en", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "2-digit",
|
||||
});
|
||||
expect(en.formatRange(d0, d0)).toBe("January 23, 1989");
|
||||
expect(en.formatRange(d1, d1)).toBe("December 07, 2021");
|
||||
|
||||
const ja = new Intl.DateTimeFormat("ja", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "2-digit",
|
||||
});
|
||||
expect(ja.formatRange(d0, d0)).toBe("1989/1月/23");
|
||||
expect(ja.formatRange(d1, d1)).toBe("2021/12月/07");
|
||||
});
|
||||
|
||||
test("with time fields", () => {
|
||||
const en = new Intl.DateTimeFormat("en", {
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(en.formatRange(d0, d0)).toBe("7:08:09 AM");
|
||||
expect(en.formatRange(d1, d1)).toBe("5:40:50 PM");
|
||||
|
||||
const ja = new Intl.DateTimeFormat("ja", {
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(ja.formatRange(d0, d0)).toBe("7:08:09");
|
||||
expect(ja.formatRange(d1, d1)).toBe("17:40:50");
|
||||
});
|
||||
|
||||
test("with mixed fields", () => {
|
||||
const en = new Intl.DateTimeFormat("en", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "2-digit",
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(en.formatRange(d0, d0)).toBe("January 23, 1989 at 7:08:09 AM");
|
||||
expect(en.formatRange(d1, d1)).toBe("December 07, 2021 at 5:40:50 PM");
|
||||
|
||||
const ja = new Intl.DateTimeFormat("ja", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "2-digit",
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(ja.formatRange(d0, d0)).toBe("1989/1月/23 7:08:09");
|
||||
expect(ja.formatRange(d1, d1)).toBe("2021/12月/07 17:40:50");
|
||||
});
|
||||
|
||||
test("with date/time style fields", () => {
|
||||
const en = new Intl.DateTimeFormat("en", {
|
||||
dateStyle: "full",
|
||||
timeStyle: "medium",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(en.formatRange(d0, d0)).toBe("Monday, January 23, 1989 at 7:08:09 AM");
|
||||
expect(en.formatRange(d1, d1)).toBe("Tuesday, December 7, 2021 at 5:40:50 PM");
|
||||
|
||||
const ja = new Intl.DateTimeFormat("ja", {
|
||||
dateStyle: "full",
|
||||
timeStyle: "medium",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(ja.formatRange(d0, d0)).toBe("1989年1月23日月曜日 7:08:09");
|
||||
expect(ja.formatRange(d1, d1)).toBe("2021年12月7日火曜日 17:40:50");
|
||||
});
|
||||
});
|
||||
|
||||
describe("dateStyle", () => {
|
||||
// prettier-ignore
|
||||
const data = [
|
||||
{ date: "full", en: "Monday, January 23, 1989 – Tuesday, December 7, 2021", ja: "1989年1月23日月曜日~2021年12月7日火曜日" },
|
||||
{ date: "long", en: "January 23, 1989 – December 7, 2021", ja: "1989/01/23~2021/12/07" },
|
||||
{ date: "medium", en: "Jan 23, 1989 – Dec 7, 2021", ja: "1989/01/23~2021/12/07" },
|
||||
{ date: "short", en: "1/23/89 – 12/7/21", ja: "1989/01/23~2021/12/07" },
|
||||
];
|
||||
|
||||
test("all", () => {
|
||||
data.forEach(d => {
|
||||
const en = new Intl.DateTimeFormat("en", { dateStyle: d.date });
|
||||
expect(en.formatRange(d0, d1)).toBe(d.en);
|
||||
|
||||
// If this test is to be changed, take care to note the "long" style for the ja locale is an intentionally
|
||||
// chosen complex test case. The format pattern is "y年M月d日" and its skeleton is "yMd" - note that the
|
||||
// month field has a numeric style. However, the interval patterns that match the "yMd" skeleton are all
|
||||
// "y/MM/dd~y/MM/dd" - the month field there conflicts with a 2-digit style. This exercises the step in the
|
||||
// FormatDateTimePattern AO to choose the style from rangeFormatOptions instead of dateTimeFormat (step 15.f.i
|
||||
// as of when this test was written).
|
||||
const ja = new Intl.DateTimeFormat("ja", { dateStyle: d.date });
|
||||
expect(ja.formatRange(d0, d1)).toBe(d.ja);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("timeStyle", () => {
|
||||
// prettier-ignore
|
||||
const data = [
|
||||
// FIXME: These results should include the date, even though it isn't requested, because the start/end dates
|
||||
// are more than just hours apart. See the FIXME in PartitionDateTimeRangePattern.
|
||||
{ time: "full", en: "7:08:09 AM Coordinated Universal Time – 5:40:50 PM Coordinated Universal Time", ja: "7時08分09秒 協定世界時~17時40分50秒 協定世界時" },
|
||||
{ time: "long", en: "7:08:09 AM UTC – 5:40:50 PM UTC", ja: "7:08:09 UTC~17:40:50 UTC" },
|
||||
{ time: "medium", en: "7:08:09 AM – 5:40:50 PM", ja: "7:08:09~17:40:50" },
|
||||
{ time: "short", en: "7:08 AM – 5:40 PM", ja: "7:08~17:40" },
|
||||
];
|
||||
|
||||
test("all", () => {
|
||||
data.forEach(d => {
|
||||
const en = new Intl.DateTimeFormat("en", { timeStyle: d.time, timeZone: "UTC" });
|
||||
expect(en.formatRange(d0, d1)).toBe(d.en);
|
||||
|
||||
const ja = new Intl.DateTimeFormat("ja", { timeStyle: d.time, timeZone: "UTC" });
|
||||
expect(ja.formatRange(d0, d1)).toBe(d.ja);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("dateStyle + timeStyle", () => {
|
||||
// prettier-ignore
|
||||
const data = [
|
||||
{ date: "full", time: "full", en: "Monday, January 23, 1989 at 7:08:09 AM Coordinated Universal Time – Tuesday, December 7, 2021 at 5:40:50 PM Coordinated Universal Time", ja: "1989年1月23日月曜日 7時08分09秒 協定世界時~2021年12月7日火曜日 17時40分50秒 協定世界時" },
|
||||
{ date: "full", time: "long", en: "Monday, January 23, 1989 at 7:08:09 AM UTC – Tuesday, December 7, 2021 at 5:40:50 PM UTC", ja: "1989年1月23日月曜日 7:08:09 UTC~2021年12月7日火曜日 17:40:50 UTC" },
|
||||
{ date: "full", time: "medium", en: "Monday, January 23, 1989 at 7:08:09 AM – Tuesday, December 7, 2021 at 5:40:50 PM", ja: "1989年1月23日月曜日 7:08:09~2021年12月7日火曜日 17:40:50" },
|
||||
{ date: "full", time: "short", en: "Monday, January 23, 1989 at 7:08 AM – Tuesday, December 7, 2021 at 5:40 PM", ja: "1989年1月23日月曜日 7:08~2021年12月7日火曜日 17:40" },
|
||||
{ date: "long", time: "full", en: "January 23, 1989 at 7:08:09 AM Coordinated Universal Time – December 7, 2021 at 5:40:50 PM Coordinated Universal Time", ja: "1989年1月23日 7時08分09秒 協定世界時~2021年12月7日 17時40分50秒 協定世界時" },
|
||||
{ date: "long", time: "long", en: "January 23, 1989 at 7:08:09 AM UTC – December 7, 2021 at 5:40:50 PM UTC", ja: "1989年1月23日 7:08:09 UTC~2021年12月7日 17:40:50 UTC" },
|
||||
{ date: "long", time: "medium", en: "January 23, 1989 at 7:08:09 AM – December 7, 2021 at 5:40:50 PM", ja: "1989年1月23日 7:08:09~2021年12月7日 17:40:50" },
|
||||
{ date: "long", time: "short", en: "January 23, 1989 at 7:08 AM – December 7, 2021 at 5:40 PM", ja: "1989年1月23日 7:08~2021年12月7日 17:40" },
|
||||
{ date: "medium", time: "full", en: "Jan 23, 1989, 7:08:09 AM Coordinated Universal Time – Dec 7, 2021, 5:40:50 PM Coordinated Universal Time", ja: "1989/01/23 7時08分09秒 協定世界時~2021/12/07 17時40分50秒 協定世界時" },
|
||||
{ date: "medium", time: "long", en: "Jan 23, 1989, 7:08:09 AM UTC – Dec 7, 2021, 5:40:50 PM UTC", ja: "1989/01/23 7:08:09 UTC~2021/12/07 17:40:50 UTC" },
|
||||
{ date: "medium", time: "medium", en: "Jan 23, 1989, 7:08:09 AM – Dec 7, 2021, 5:40:50 PM", ja: "1989/01/23 7:08:09~2021/12/07 17:40:50" },
|
||||
{ date: "medium", time: "short", en: "Jan 23, 1989, 7:08 AM – Dec 7, 2021, 5:40 PM", ja: "1989/01/23 7:08~2021/12/07 17:40" },
|
||||
{ date: "short", time: "full", en: "1/23/89, 7:08:09 AM Coordinated Universal Time – 12/7/21, 5:40:50 PM Coordinated Universal Time", ja: "1989/01/23 7時08分09秒 協定世界時~2021/12/07 17時40分50秒 協定世界時" },
|
||||
{ date: "short", time: "long", en: "1/23/89, 7:08:09 AM UTC – 12/7/21, 5:40:50 PM UTC", ja: "1989/01/23 7:08:09 UTC~2021/12/07 17:40:50 UTC" },
|
||||
{ date: "short", time: "medium", en: "1/23/89, 7:08:09 AM – 12/7/21, 5:40:50 PM", ja: "1989/01/23 7:08:09~2021/12/07 17:40:50" },
|
||||
{ date: "short", time: "short", en: "1/23/89, 7:08 AM – 12/7/21, 5:40 PM", ja: "1989/01/23 7:08~2021/12/07 17:40" },
|
||||
];
|
||||
|
||||
test("all", () => {
|
||||
data.forEach(d => {
|
||||
const en = new Intl.DateTimeFormat("en", {
|
||||
dateStyle: d.date,
|
||||
timeStyle: d.time,
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(en.formatRange(d0, d1)).toBe(d.en);
|
||||
|
||||
const ja = new Intl.DateTimeFormat("ja", {
|
||||
dateStyle: d.date,
|
||||
timeStyle: d.time,
|
||||
timeZone: "UTC",
|
||||
});
|
||||
expect(ja.formatRange(d0, d1)).toBe(d.ja);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue