std/datetime/_date_time_formatter_test.ts
2024-08-21 14:42:02 +09:00

294 lines
8.4 KiB
TypeScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assertEquals, assertThrows } from "@std/assert";
import { FakeTime } from "@std/testing/time";
import { DateTimeFormatter } from "./_date_time_formatter.ts";
Deno.test("dateTimeFormatter.format()", () => {
const cases = [
["yyyy-MM-dd HH:mm:ss a", new Date(2020, 0, 1), "2020-01-01 00:00:00 AM"],
[
"yyyy-MM-dd HH:mm:ss a",
new Date(2020, 0, 1, 23, 59, 59),
"2020-01-01 23:59:59 PM",
],
[
"yyyy-MM-dd hh:mm:ss a",
new Date(2020, 0, 1, 23, 59, 59),
"2020-01-01 11:59:59 PM",
],
["yyyy-MM-dd a", new Date(2020, 0, 1), "2020-01-01 AM"],
["yyyy-MM-dd HH:mm:ss a", new Date(2020, 0, 1), "2020-01-01 00:00:00 AM"],
["yyyy-MM-dd hh:mm:ss a", new Date(2020, 0, 1), "2020-01-01 12:00:00 AM"],
["yyyy", new Date(2020, 0, 1), "2020"],
["MM", new Date(2020, 0, 1), "01"],
] as const;
for (const [format, date, expected] of cases) {
const formatter = new DateTimeFormatter(format);
assertEquals(formatter.format(date), expected);
}
});
Deno.test("dateTimeFormatter.format() with empty format string returns empty string", () => {
const format = "";
const formatter = new DateTimeFormatter(format);
assertEquals(
formatter.format(new Date(2020, 0, 1)),
"",
);
});
Deno.test("dateTimeFormatter.parse()", () => {
const format = "yyyy-MM-dd";
const formatter = new DateTimeFormatter(format);
assertEquals(formatter.parse("2020-01-01"), new Date(2020, 0, 1));
});
Deno.test("dateTimeFormatter.formatToParts()", () => {
const format = "yyyy-MM-dd";
const formatter = new DateTimeFormatter(format);
assertEquals(formatter.formatToParts("2020-01-01"), [
{ type: "year", value: "2020" },
{ type: "literal", value: "-" },
{ type: "month", value: "01" },
{ type: "literal", value: "-" },
{ type: "day", value: "01" },
]);
});
Deno.test("dateTimeFormatter.formatToParts() throws on an empty string", () => {
const format = "yyyy-MM-dd";
const formatter = new DateTimeFormatter(format);
assertThrows(
() => formatter.formatToParts(""),
Error,
"Cannot format value: The value is not valid for part { year undefined } ",
);
});
Deno.test("dateTimeFormatter.formatToParts() throws on a string which exceeds the format", () => {
const format = "yyyy-MM-dd";
const formatter = new DateTimeFormatter(format);
assertThrows(
() => formatter.formatToParts("2020-01-01T00:00:00.000Z"),
Error,
"datetime string was not fully parsed!",
);
});
Deno.test("dateTimeFormatter.partsToDate()", () => {
const date = new Date("2020-01-01T00:00:00.000Z");
using _time = new FakeTime(date);
const format = "yyyy-MM-dd HH:mm:ss.SSS a";
const formatter = new DateTimeFormatter(format);
assertEquals(
formatter.partsToDate([
{ type: "year", value: "2020" },
{ type: "month", value: "01" },
{ type: "day", value: "01" },
{ type: "hour", value: "00" },
{ type: "minute", value: "00" },
{ type: "second", value: "00" },
{ type: "fractionalSecond", value: "000" },
{ type: "dayPeriod", value: "AM" },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
});
Deno.test("dateTimeFormatter.partsToDate() works with am dayPeriod", () => {
const date = new Date("2020-01-01T00:00:00.000Z");
using _time = new FakeTime(date);
const format = "HH a";
const formatter = new DateTimeFormatter(format);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "AM" },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "AM." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "A.M." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "am" },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "am." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "a.m." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
});
Deno.test("dateTimeFormatter.partsToDate() works with pm dayPeriod", () => {
const date = new Date("2020-01-01T13:00:00.000Z");
using _time = new FakeTime(date);
const format = "HH a";
const formatter = new DateTimeFormatter(format);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "01" },
{ type: "dayPeriod", value: "PM" },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "01" },
{ type: "dayPeriod", value: "PM." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "01" },
{ type: "dayPeriod", value: "P.M." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "01" },
{ type: "dayPeriod", value: "pm" },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "01" },
{ type: "dayPeriod", value: "pm." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
assertEquals(
formatter.partsToDate([
{ type: "hour", value: "01" },
{ type: "dayPeriod", value: "p.m." },
{ type: "timeZoneName", value: "UTC" },
]),
date,
);
});
Deno.test("dateTimeFormatter.partsToDate() throws with invalid dayPeriods", () => {
const format = "HH a";
const formatter = new DateTimeFormatter(format);
assertThrows(
() =>
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "A.M" },
{ type: "timeZoneName", value: "UTC" },
]),
Error,
"dayPeriod 'A.M' is not supported.",
);
assertThrows(
() =>
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "a.m" },
{ type: "timeZoneName", value: "UTC" },
]),
Error,
"dayPeriod 'a.m' is not supported.",
);
assertThrows(
() =>
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "P.M" },
{ type: "timeZoneName", value: "UTC" },
]),
Error,
"dayPeriod 'P.M' is not supported.",
);
assertThrows(
() =>
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "p.m" },
{ type: "timeZoneName", value: "UTC" },
]),
Error,
"dayPeriod 'p.m' is not supported.",
);
assertThrows(
() =>
formatter.partsToDate([
{ type: "hour", value: "00" },
{ type: "dayPeriod", value: "noon" },
{ type: "timeZoneName", value: "UTC" },
]),
Error,
"dayPeriod 'noon' is not supported.",
);
});
Deno.test("dateTimeFormatter.partsToDate() sets utc", () => {
const date = new Date("2020-01-01T00:00:00.000Z");
using _time = new FakeTime(date);
const cases = [
["yyyy-MM-dd HH:mm:ss.SSS a", [
{ type: "year", value: "2020" },
{ type: "month", value: "01" },
{ type: "day", value: "01" },
{ type: "hour", value: "00" },
{ type: "minute", value: "00" },
{ type: "second", value: "00" },
{ type: "fractionalSecond", value: "000" },
{ type: "timeZoneName", value: "UTC" },
{ type: "dayPeriod", value: "AM" },
], date],
["yyyy-MM-dd", [
{ type: "year", value: "2020" },
{ type: "month", value: "01" },
{ type: "day", value: "01" },
{ type: "timeZoneName", value: "UTC" },
], date],
["yyyy-MM", [
{ type: "year", value: "2020" },
{ type: "month", value: "01" },
{ type: "timeZoneName", value: "UTC" },
], date],
] as const;
for (const [format, input, output] of cases) {
const formatter = new DateTimeFormatter(format);
assertEquals(formatter.partsToDate([...input]), output);
}
});