UNPKG

@tricoteuses/senat

Version:

Handle French Sénat's open data

127 lines (126 loc) 4.16 kB
import { DateTime } from "luxon"; export function yyyymmddFromPath(xmlFilePath) { return xmlFilePath.replace(/^.*?(\d{8}).*$/i, "$1"); } export function parseYYYYMMDD(yyyymmdd) { if (!/^\d{8}$/.test(yyyymmdd)) return null; const y = Number(yyyymmdd.slice(0, 4)); const m = Number(yyyymmdd.slice(4, 6)) - 1; const d = Number(yyyymmdd.slice(6, 8)); const dt = new Date(y, m, d); return Number.isFinite(dt.getTime()) ? dt : null; } export function frDateToISO(s) { if (!s) return; const months = { janvier: 1, février: 2, fevrier: 2, mars: 3, avril: 4, mai: 5, juin: 6, juillet: 7, août: 8, aout: 8, septembre: 9, octobre: 10, novembre: 11, décembre: 12, decembre: 12, }; const cleaned = s .trim() .replace(/\u00A0/g, " ") .replace(/ +/g, " "); const m = cleaned.match(/^(\d{1,2})(?:er)?\s+([a-zéèêîïôûùç]+)\s+(\d{4})$/i); if (!m) return; const d = String(parseInt(m[1], 10)).padStart(2, "0"); const mon = months[m[2].toLowerCase()]; if (!mon) return; const y = m[3]; return `${y}-${String(mon).padStart(2, "0")}-${d}`; } export function hourShortToStartTime(hourShort) { if (!hourShort || hourShort === "NA") return null; if (!/^\d{4}$/.test(hourShort)) return null; const hh = hourShort.slice(0, 2); const mm = hourShort.slice(2, 4); return `${hh}:${mm}`; } export function epochToParisDateTime(epochSec) { if (!Number.isFinite(epochSec)) return null; const dUtc = new Date(epochSec * 1000); // Offset heuristic (same logique que parisOffsetForDate) const m = dUtc.getUTCMonth() + 1; // 1..12 const offsetHours = m >= 4 && m <= 10 ? 2 : 1; const offsetStr = offsetHours === 2 ? "+02:00" : "+01:00"; // Applique l'offset pour obtenir la date/heure locales Paris const localMs = dUtc.getTime() + offsetHours * 3600 * 1000; const dl = new Date(localMs); const yyyy = String(dl.getUTCFullYear()); const mm = String(dl.getUTCMonth() + 1).padStart(2, "0"); const dd = String(dl.getUTCDate()).padStart(2, "0"); const hh = String(dl.getUTCHours()).padStart(2, "0"); const mi = String(dl.getUTCMinutes()).padStart(2, "0"); const ss = String(dl.getUTCSeconds()).padStart(2, "0"); const ms = String(dl.getUTCMilliseconds()).padStart(3, "0"); return { date: `${yyyy}-${mm}-${dd}`, startTime: `${hh}:${mi}:${ss}.${ms}${offsetStr}`, }; } export function toTargetEpoch(time, date) { if (!time) return null; let dtLocal; if (time.includes("T")) { dtLocal = DateTime.fromISO(time, { zone: "Europe/Paris" }); } else if (date) { dtLocal = DateTime.fromISO(`${date}T${time}`, { zone: "Europe/Paris" }); } else { return null; } if (!dtLocal.isValid) return null; return Math.floor(dtLocal.toUTC().toSeconds()); } export function toFRDate(dateYYYYMMDD) { const [y, m, d] = dateYYYYMMDD.split("-"); return `${d}/${m}/${y}`; // DD/MM/YYYY } export function isAmbiguousTimeOriginal(timeOriginal) { if (!timeOriginal) return false; const s = timeOriginal.toLowerCase(); // Catches "14h", "14 h", "14h30", "14 h 30", "14 heures", "14 heure" const timeRe = /\b([01]?\d|2[0-3])\s*(?:h|heures?|heure)\s*(?:([0-5]\d))?\b/g; const times = new Set(); let m; while ((m = timeRe.exec(s))) { const hh = String(m[1]).padStart(2, "0"); const mm = m[2] ? String(m[2]).padStart(2, "0") : "00"; times.add(`${hh}:${mm}`); } // "midi" / "minuit" if (/\bmidi\b/.test(s)) times.add("12:00"); if (/\bminuit\b/.test(s)) times.add("00:00"); if (times.size >= 2) return true; const hasDayPeriod = /\b(matin|après-?midi|soir|nuit|journée|toute la journée)\b/.test(s); const hasLinking = /,|\bet\b|\bou\b|\bpuis\b/.test(s); if (times.size === 1 && hasDayPeriod && hasLinking) return true; return false; }