import { Result } from "@repo/rdx-utils"; import * as z from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; interface UtcDateProps { value: string; } export class UtcDate extends ValueObject { private readonly date!: Date; private constructor(props: UtcDateProps) { super(props); const { value: dateString } = props; this.date = Object.freeze(new Date(dateString)); } static validate(dateString: string) { const dateStr = z.union([ z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, "Invalid ISO 8601 format"), z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid YYYY-MM-DD format"), ]); const dateStrToDate = dateStr.pipe(z.coerce.date()); return dateStrToDate.safeParse(dateString); } /** * Crea una instancia de UtcDate a partir de un string en formato UTC ISO 8601. * @param isoDateString Fecha en formato UTC (con o sin hora YYYY-MM-DD) * @returns UtcDate si es vĂ¡lida, Error en caso contrario. */ static createFromISO(isoDateString: string): Result { const dateIsValid = UtcDate.validate(isoDateString); if (!dateIsValid.success) { return Result.fail(translateZodValidationError("UtcDate creation failed", dateIsValid.error)); } return Result.ok(new UtcDate({ value: isoDateString })); } getProps(): string { return this.props.value; } /** * Devuelve la fecha completa en formato UTC con hora (ISO 8601). Ejemplo: 2025-12-31T23:59:59Z. */ toPrimitive() { return this.toISOString(); } /** * Devuelve la fecha en formato UTC sin hora (YYYY-MM-DD). */ toDateString(): string { return this.date.toISOString().split("T")[0]; } toString() { return this.toDateString(); } /** * Devuelve la fecha en formato UTC con hora (ISO 8601). Ejemplo: 2025-12-31T23:59:59Z. */ toISOString(): string { return this.date.toISOString(); } /** * Compara si dos instancias de UtcDate son iguales. */ equals(other: UtcDate): boolean { return this.toISOString() === other.toISOString(); } }