import { expect } from "chai"; import assert from "node:assert"; import { describe, it } from "node:test"; import { failWith } from "./Function.js"; import { format, parse, patternToParts, splitBySeperators, uts35__Date, } from "./UTS35.js"; import { pipe } from "effect/Function"; import * as Either from "effect/Either"; describe("UTS35", () => { describe("patternToParts", () => { it("should split iso strings", () => { const parts = patternToParts("yyyy-MM-dd"); expect(parts).to.deep.eq([ { type: "year", pattern: "yyyy" }, { type: "literal", pattern: "-" }, { type: "month", pattern: "MM" }, { type: "literal", pattern: "-" }, { type: "day", pattern: "dd" }, ]); }); it("should be able to deal with strings that are not a recognized pattern", () => { const parts = patternToParts("yyyy-MM-ddTHH:mm:ss"); expect(parts).to.deep.eq([ { type: "year", pattern: "yyyy" }, { type: "literal", pattern: "-" }, { type: "month", pattern: "MM" }, { type: "literal", pattern: "-" }, { type: "day", pattern: "dd" }, { type: "literal", pattern: "T" }, { type: "hour", pattern: "HH" }, { type: "literal", pattern: ":" }, { type: "minute", pattern: "mm" }, { type: "literal", pattern: ":" }, { type: "second", pattern: "ss" }, ]); }); }); describe("splitBySeperators", () => { it("should split iso string separators", () => { const parts = splitBySeperators("years-months-days", "yyyy-MM-dd"); expect(parts).to.deep.eq([ { type: "year", value: "years" }, { type: "literal", value: "-" }, { type: "month", value: "months" }, { type: "literal", value: "-" }, { type: "day", value: "days" }, ]); }); it("should return as many parts as possible from values that don't contain each part", () => { const parts = splitBySeperators("yearsmonths-days", "yyyy-MM-dd"); expect(parts).to.deep.eq([ { type: "year", value: "yearsmonths" }, { type: "literal", value: "-" }, { type: "month", value: "days" }, ]); }); }); describe("parse", () => { it("should be able to parse iso strings", () => { expect(parse("2024-10-10", "yyyy-MM-dd").toISOString()).to.eq( "2024-10-09T22:00:00.000Z", ); }); it("should treat string with timezone according to the timezone", () => { expect(parse("2024-10-10Z", "yyyy-MM-ddX").toISOString()).to.eq( "2024-10-10T00:00:00.000Z", ); }); it("should treat strings without timezone as local time", () => { expect(parse("2024-10-10", "yyyy-MM-ddX").toISOString()).to.eq( "2024-10-09T22:00:00.000Z", ); }); it("should be able to parse custom formats", () => { expect( parse("2024/10-10 11:12_13.456", "yyyy/MM-dd HH:mm_ss.SSS"), ).to.deep.eq(new Date(2024, 9, 10, 11, 12, 13, 456)); }); it("should be able to parse years into a wider format", () => { const target = new Date(0, 0, 1, 0, 0, 0); target.setFullYear(20); expect(parse("20", "yyyy")).to.deep.eq(target); }); it("should autofill parts that are missing from the value", () => { expect(parse("2024", "yyyy-MM")).to.deep.eq( new Date(2024, 0, 1, 0, 0, 0, 0), ); }); }); describe("format", () => { it("should format iso date strings", () => { expect(format(new Date(2024, 9, 10), "yyyy-MM-dd")).to.eq("2024-10-10"); }); it("should format custom date format", () => { expect( format(new Date(2024, 9, 10, 11, 12, 13, 0), "yyyy/MM-dd HH:mm_ss.SSS"), ).to.eq("2024/10-10 11:12_13.000"); }); it("should fill in missing parts if specified in the pattern", () => { expect(format(new Date(2024, 9, 10), "yyyy-MM-ddTHH")).to.eq( "2024-10-10T00", ); }); }); }); describe("uts35__Date", () => { it("should create a date from perfect strings", () => { const codec = uts35__Date("yyyy-MM-dd HH:mm:ss.SSS"); const result = pipe( codec.decode("2024-01-01 00:00:00.000"), Either.getOrElse(failWith), ); assert.deepEqual(result.toISOString(), "2023-12-31T23:00:00.000Z"); }); });