/** * utilities for working with JS Dates * * @module */ import * as Either from "effect/Either"; import { type Codec, decodingError } from "./Codec.js"; export const iso8601ToDate: Codec = { encode: (value: Date) => Number.isNaN(value.valueOf()) ? Either.left(new Error("invalid date")) : Either.right(value.toISOString()), decode: (value) => { if (value instanceof Date) { return Number.isNaN(value.valueOf()) ? Either.left(new Error("invalid date")) : Either.right(value); } switch (typeof value) { case "number": return Either.right(new Date(value)); case "string": { const parsed = new Date(value); if (!value.includes("T")) { // Date constructor assumes UTC for strings without time component parsed.setMinutes(parsed.getMinutes() + parsed.getTimezoneOffset()); } return Number.isNaN(parsed.valueOf()) ? Either.left(new Error("invalid date string")) : Either.right(parsed); } default: return Either.left(decodingError(value)); } }, }; /** * convert between Date und string. Invalid values are treated as a right undefined */ export const iso8601ContentAttribute__maybeDate: Codec< string, undefined | Date > = { encode: (value) => { return value == null ? Either.right("") : iso8601ToDate.encode(value); }, decode: (value) => value === "" || value == null ? Either.right(undefined) : iso8601ToDate.decode(value), };