const fs = require("fs"); const path = require("path"); const YAML = require("yaml"); const { DateTime } = require("luxon"); const HUGO_CONFIG_PATH = path.join(process.cwd(), "config", "_default", "config.yaml"); let cachedTimeZone = null; /** * Récupère le fuseau horaire configuré pour Hugo. * @returns {string} Identifiant IANA du fuseau horaire de Hugo. */ function getHugoTimeZone() { if (cachedTimeZone) { return cachedTimeZone; } const rawConfig = fs.readFileSync(HUGO_CONFIG_PATH, "utf8"); const parsedConfig = YAML.parse(rawConfig); if (!parsedConfig || !parsedConfig.timeZone) { throw new Error("Aucun fuseau horaire Hugo n'a été trouvé dans config/_default/config.yaml."); } cachedTimeZone = String(parsedConfig.timeZone).trim(); if (!cachedTimeZone) { throw new Error("Le fuseau horaire Hugo est vide ou invalide."); } return cachedTimeZone; } /** * Convertit une valeur vers un DateTime positionné sur le fuseau horaire Hugo. * @param {Date|import("luxon").DateTime|string|number|null} value Valeur à convertir (null : maintenant). * @returns {import("luxon").DateTime} Instance DateTime alignée sur le fuseau de Hugo. */ function toHugoDateTime(value = null) { const zone = getHugoTimeZone(); if (value === null || value === undefined) { const now = DateTime.now().setZone(zone); if (!now.isValid) { throw new Error(now.invalidReason || "Date actuelle invalide pour le fuseau Hugo."); } return now; } if (DateTime.isDateTime(value)) { const zoned = value.setZone(zone); if (!zoned.isValid) { throw new Error(zoned.invalidReason || "DateTime invalide après application du fuseau Hugo."); } return zoned; } if (value instanceof Date) { const zoned = DateTime.fromJSDate(value, { zone }); if (!zoned.isValid) { throw new Error(zoned.invalidReason || "Date JS invalide pour le fuseau Hugo."); } return zoned; } if (typeof value === "string") { const parsed = DateTime.fromISO(value, { setZone: true }).setZone(zone); if (!parsed.isValid) { throw new Error(parsed.invalidReason || `Chaîne de date invalide : ${value}`); } return parsed; } if (typeof value === "number") { const parsed = DateTime.fromMillis(value, { zone }).setZone(zone); if (!parsed.isValid) { throw new Error(parsed.invalidReason || "Horodatage numérique invalide pour le fuseau Hugo."); } return parsed; } throw new Error("Type de date non pris en charge pour le fuseau horaire Hugo."); } /** * Formate une date en ISO 8601 avec l'offset du fuseau horaire Hugo. * @param {Date|import("luxon").DateTime|string|number|null} value Valeur à formater. * @returns {string} Timestamp ISO 8601 avec offset. */ function formatDateTime(value = null) { const zoned = toHugoDateTime(value); const normalized = zoned.set({ millisecond: 0 }); const formatted = normalized.toISO({ suppressMilliseconds: true }); if (!formatted) { throw new Error("Impossible de formater la date avec le fuseau Hugo."); } return formatted; } module.exports = { formatDateTime, getHugoTimeZone, toHugoDateTime, };