FactuGES_ERP/packages/rdx-ddd/src/value-objects/utc-date.ts
2025-11-05 18:16:27 +01:00

105 lines
2.9 KiB
TypeScript

import { Result } from "@repo/rdx-utils";
import { z } from "zod/v4";
import { translateZodValidationError } from "../helpers";
import { ValueObject } from "./value-object";
interface UtcDateProps {
value: string;
}
export class UtcDate extends ValueObject<UtcDateProps> {
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<UtcDate, Error> {
const dateIsValid = UtcDate.validate(isoDateString);
if (!dateIsValid.success) {
return Result.fail(translateZodValidationError("UtcDate creation failed", dateIsValid.error));
}
return Result.ok(new UtcDate({ value: isoDateString }));
}
/**
* Creador estático: devuelve la fecha de HOY en UTC a medianoche (00:00:00Z).
* - Evita ambigüedades de zona horaria construyendo el ISO explícitamente.
*/
static today(): UtcDate {
const now = new Date();
const y = now.getUTCFullYear();
const m = String(now.getUTCMonth() + 1).padStart(2, "0");
const d = String(now.getUTCDate()).padStart(2, "0");
const iso = `${y}-${m}-${d}T00:00:00Z`;
return new UtcDate({ value: iso });
}
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();
}
/**
* Devuelve la fecha en formato dd/mm/yyyy (formato europeo).
*/
toEuropeanString(): string {
const day = String(this.date.getUTCDate()).padStart(2, "0");
const month = String(this.date.getUTCMonth() + 1).padStart(2, "0"); // Los meses en JS empiezan en 0
const year = this.date.getUTCFullYear();
return `${day}/${month}/${year}`;
}
/**
* Compara si dos instancias de UtcDate son iguales.
*/
equals(other: UtcDate): boolean {
return this.toISOString() === other.toISOString();
}
}