feat: show the event time range, not just its start
Pierre's field test: the agenda announces "10:30 → 12:30", the list only said "à 10:30". The end date was already parsed and already in the payload; it was purely missing from the display. Naively rendering start → end would have been wrong four ways, all measured against the real parser: - no DTEND: the parser sets fin === debut, so "de 10:30 à 10:30" - crossing midnight: "samedi de 22:00 à 02:00" hides the end date - all-day: DTEND is EXCLUSIVE (RFC 5545), so a one-day event carries the next day, and a 18→20 festival carries the 21st The last one is the dangerous one: it yields a wrong date, not just an ugly one. The end day is therefore fin minus one day, computed from local components since a floating date has no timezone. DECISIONS.md records the exclusive DTEND for the sibling task, which fills the town hall's end date field straight from DTEND. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f994bfac30
commit
596b5e22fd
@@ -10,9 +10,12 @@ export const LIEU_PAR_DEFAUT = "8 Rue du Pré Vicinal 31270 Cugnaux";
|
||||
|
||||
// Un événement horodaté porte un vrai instant : on l'affiche à l'heure de
|
||||
// Cugnaux, quel que soit le fuseau de la machine.
|
||||
const FORMAT_AVEC_HEURE = new Intl.DateTimeFormat(LOCALE, {
|
||||
const FORMAT_JOUR_PARIS = new Intl.DateTimeFormat(LOCALE, {
|
||||
timeZone: FUSEAU,
|
||||
dateStyle: "full",
|
||||
});
|
||||
const FORMAT_HEURE_PARIS = new Intl.DateTimeFormat(LOCALE, {
|
||||
timeZone: FUSEAU,
|
||||
timeStyle: "short",
|
||||
});
|
||||
|
||||
@@ -20,7 +23,7 @@ const FORMAT_AVEC_HEURE = new Intl.DateTimeFormat(LOCALE, {
|
||||
// entière est une date *flottante* (RFC 5545), sans fuseau. ical.js la
|
||||
// matérialise à minuit local ; la relire en local restitue le bon jour partout,
|
||||
// alors que la convertir vers Paris la ferait glisser au 9 depuis Tokyo.
|
||||
const FORMAT_SANS_HEURE = new Intl.DateTimeFormat(LOCALE, {
|
||||
const FORMAT_JOUR_FLOTTANT = new Intl.DateTimeFormat(LOCALE, {
|
||||
dateStyle: "full",
|
||||
});
|
||||
|
||||
@@ -31,8 +34,45 @@ export function trierParDebut(evenements) {
|
||||
|
||||
// Une journée entière n'a pas d'heure : afficher « 00:00 » serait un mensonge.
|
||||
export function formaterDate(evenement) {
|
||||
const format = evenement.journeeEntiere ? FORMAT_SANS_HEURE : FORMAT_AVEC_HEURE;
|
||||
return format.format(evenement.debut);
|
||||
return evenement.journeeEntiere
|
||||
? formaterJourneeEntiere(evenement)
|
||||
: formaterHorodate(evenement);
|
||||
}
|
||||
|
||||
function formaterJourneeEntiere({ debut, fin }) {
|
||||
const premierJour = FORMAT_JOUR_FLOTTANT.format(debut);
|
||||
const dernierJour = veilleDe(fin);
|
||||
|
||||
// Un seul jour, ou pas de DTEND exploitable (le parseur pose alors fin === debut).
|
||||
if (dernierJour.getTime() <= debut.getTime()) return premierJour;
|
||||
|
||||
return `du ${premierJour} au ${FORMAT_JOUR_FLOTTANT.format(dernierJour)}`;
|
||||
}
|
||||
|
||||
// DTEND est EXCLUSIF (RFC 5545) : un événement du 18 porte DTEND=19, un festival
|
||||
// du 18 au 20 porte DTEND=21. Sans ce recul d'un jour, on annoncerait un jour de
|
||||
// trop — une date FAUSSE, pas seulement laide.
|
||||
// Composantes locales (jamais « -24h ») : la date est flottante, et un
|
||||
// changement d'heure ferait basculer le jour.
|
||||
function veilleDe(date) {
|
||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - 1);
|
||||
}
|
||||
|
||||
function formaterHorodate({ debut, fin }) {
|
||||
const jourDebut = FORMAT_JOUR_PARIS.format(debut);
|
||||
const heureDebut = FORMAT_HEURE_PARIS.format(debut);
|
||||
|
||||
// DTEND absent : le parseur pose fin === debut. « de 10:30 à 10:30 » serait absurde.
|
||||
if (fin.getTime() <= debut.getTime()) return `${jourDebut} à ${heureDebut}`;
|
||||
|
||||
const jourFin = FORMAT_JOUR_PARIS.format(fin);
|
||||
const heureFin = FORMAT_HEURE_PARIS.format(fin);
|
||||
|
||||
// Comparaison des jours tels qu'AFFICHÉS (donc à Paris) : un événement de
|
||||
// 22:00 à 02:00 change de jour, l'annoncer sur un seul serait un mensonge.
|
||||
if (jourFin === jourDebut) return `${jourDebut} de ${heureDebut} à ${heureFin}`;
|
||||
|
||||
return `du ${jourDebut} à ${heureDebut} au ${jourFin} à ${heureFin}`;
|
||||
}
|
||||
|
||||
// La plupart des événements se tiennent au café et n'ont pas de LOCATION :
|
||||
|
||||
Reference in New Issue
Block a user