From c65afa0a1ea1ce464648d4e5dec23101a1e38ee6 Mon Sep 17 00:00:00 2001 From: Richard Dern Date: Tue, 2 Dec 2025 16:36:57 +0100 Subject: [PATCH] =?UTF-8?q?Correction=20de=20l'heure=20affect=C3=A9e=20aux?= =?UTF-8?q?=20nouveaux=20posts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/add_link.js | 28 +++------- tools/lib/datetime.js | 117 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 103 insertions(+), 42 deletions(-) diff --git a/tools/add_link.js b/tools/add_link.js index 9dd498b1..e09e8670 100644 --- a/tools/add_link.js +++ b/tools/add_link.js @@ -9,7 +9,7 @@ const YAML = require("yaml"); const { buildUserAgent, checkUrl } = require("./lib/http"); const { getArchiveUrl, saveToArchive } = require("./lib/archive"); const { scrapePage } = require("./lib/puppeteer"); -const { formatDateTime } = require("./lib/datetime"); +const { formatDateTime, toHugoDateTime } = require("./lib/datetime"); const LINKS_ROOT = path.join("content", "interets", "liens-interessants"); @@ -83,26 +83,14 @@ if (duplicateBundlePath) { console.log(`📂 Archive URL ${archiveUrl}...`); // Déterminer la date et l'heure d'enregistrement - let entryDate = customDate ? new Date(customDate) : new Date(); - if (isNaN(entryDate.getTime())) { - console.error("❌ Invalid date format. Use YYYY-MM-DD."); - process.exit(1); - } + const entryDate = customDate ? toHugoDateTime(customDate) : toHugoDateTime(); + const formattedEntryDate = formatDateTime(entryDate); + const formattedStatusDate = formatDateTime(); + const formattedDateFrench = entryDate.setLocale("fr").toFormat("d LLLL yyyy 'à' HH:mm"); - const now = new Date(); // Current date for status - const formattedEntryDate = formatDateTime(entryDate); // ISO 8601 local avec offset - const formattedStatusDate = now.toISOString(); // ISO format - const formattedDateFrench = entryDate.toLocaleDateString("fr-FR", { - year: "numeric", - month: "long", - day: "numeric", - hour: "2-digit", - minute: "2-digit", - }); - - const year = entryDate.getFullYear(); - const month = String(entryDate.getMonth() + 1).padStart(2, "0"); - const day = String(entryDate.getDate()).padStart(2, "0"); + const year = entryDate.year; + const month = String(entryDate.month).padStart(2, "0"); + const day = String(entryDate.day).padStart(2, "0"); // Define paths const bundlePath = path.join(hugoRoot, `content/interets/liens-interessants/${year}/${month}/${day}/${urlHash}/`); diff --git a/tools/lib/datetime.js b/tools/lib/datetime.js index 3ed8d7d3..b277898a 100644 --- a/tools/lib/datetime.js +++ b/tools/lib/datetime.js @@ -1,34 +1,107 @@ +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; + /** - * Ajoute un zéro devant les valeurs inférieures à 10 pour conserver le formatage. - * @param {number|string} value Valeur numérique à normaliser. - * @returns {string} Représentation sur deux caractères. + * Récupère le fuseau horaire configuré pour Hugo. + * @returns {string} Identifiant IANA du fuseau horaire de Hugo. */ -function pad(value) { - return String(value).padStart(2, '0'); +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; } /** - * Retourne le timestamp ISO local formatté avec offset. - * @param {Date} value Date à formater (par défaut : maintenant). - * @returns {string} Timestamp ISO 8601 avec fuseau horaire local. + * 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 formatDateTime(value = new Date()) { - const year = value.getFullYear(); - const month = pad(value.getMonth() + 1); - const day = pad(value.getDate()); - const hours = pad(value.getHours()); - const minutes = pad(value.getMinutes()); - const seconds = pad(value.getSeconds()); +function toHugoDateTime(value = null) { + const zone = getHugoTimeZone(); - const offsetMinutes = value.getTimezoneOffset(); - const sign = offsetMinutes <= 0 ? '+' : '-'; - const absOffset = Math.abs(offsetMinutes); - const offsetHours = pad(Math.floor(absOffset / 60)); - const offsetMins = pad(absOffset % 60); + 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; + } - return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${sign}${offsetHours}:${offsetMins}`; + 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, + formatDateTime, + getHugoTimeZone, + toHugoDateTime, };