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:
Pierre Martin
2026-07-17 11:55:23 +02:00
co-authored by Claude Opus 4.8
parent f994bfac30
commit 596b5e22fd
3 changed files with 129 additions and 7 deletions
+10
View File
@@ -102,6 +102,16 @@ conversion de fuseau. C'est pour la même raison que la liste formate les
journées entières **sans** `timeZone` (`presentation.js`) : forcer `Europe/Paris`
faisait glisser la date au jour précédent depuis Tokyo ou Auckland.
⚠️ **`fin` est un DTEND EXCLUSIF (RFC 5545) — ne pas l'afficher/soumettre tel quel.**
Le payload porte la valeur brute du parseur. Pour une **journée entière**, un
événement du 18 porte `fin` = le **19**, et un festival du 18 au 20 porte `fin` =
le **21** : le dernier jour réel est **`fin` moins un jour** (composantes locales,
jamais « -24h »). Concerne directement la tâche sœur, qui remplit `#input_6_32`
(Date fin) **depuis DTEND** : sans ce recul d'un jour, elle soumettra une date
**fausse** à la mairie. La liste applique déjà la règle (`presentation.js`,
`veilleDe`). Autre cas mesuré : **`DTEND` absent → le parseur pose `fin === debut`**
(il n'y a alors pas de plage à afficher, ni de fin à soumettre).
**`TZ=Europe/Paris` sur `bun test` est PORTEUR — ne pas le retirer.** Le runner
de Bun force **`TZ=UTC`** quand `TZ` est absente (vérifié : `bun -e` lit le
fuseau système, le runner non). Sans le pin, les tests ne tournent donc pas dans