/** * Helpers de date purs / testables (partages inter-modules). */ /** * Date du jour au format ISO `YYYY-MM-DD` en heure LOCALE. * * On NE passe PAS par `toISOString()` (UTC) : pres de minuit, le decalage de * fuseau (FR = UTC+1/+2) renverrait la veille ou le lendemain. On lit donc les * composantes locales. Parametre `now` injectable pour les tests. */ export function todayIso(now: Date = new Date()): string { const year = now.getFullYear() const month = String(now.getMonth() + 1).padStart(2, '0') const day = String(now.getDate()).padStart(2, '0') return `${year}-${month}-${day}` } /** * Date-heure courante au format ISO LOCAL `YYYY-MM-DDTHH:mm:ss` (sans fuseau). * * C'est le format attendu par `MalioDateTime` (secondes incluses, pas d'offset * horaire). Comme `todayIso`, on lit les composantes LOCALES (jamais * `toISOString()`/UTC) pour ne pas décaler l'heure réelle. Paramètre `now` * injectable pour les tests. */ export function nowIsoDateTime(now: Date = new Date()): string { const hours = String(now.getHours()).padStart(2, '0') const minutes = String(now.getMinutes()).padStart(2, '0') const seconds = String(now.getSeconds()).padStart(2, '0') return `${todayIso(now)}T${hours}:${minutes}:${seconds}` } /** * Date courte française `JJ-MM-AAAA` à partir d'une valeur ISO (`YYYY-MM-DD` ou * datetime `YYYY-MM-DDTHH:mm:ss±HH:mm`). Chaîne vide si absente ou non ISO. * * On lit les composantes DIRECTEMENT dans la chaîne (10 premiers caractères) au * lieu de `new Date(value).getDate()` : un datetime porteur d'un offset (ex. * `…T00:30:00+02:00`, ou `…Z`) basculerait d'un jour selon le fuseau du * navigateur / du runner CI. Rendu ainsi déterministe et cohérent avec l'écran * d'édition (slice de la chaîne brute) et l'export serveur (`format('d/m/Y')`). */ export function formatDateFr(value: string | null | undefined): string { const match = value ? /^(\d{4})-(\d{2})-(\d{2})/.exec(value) : null if (!match) { return '' } const [, year, month, day] = match return `${day}-${month}-${year}` }