From a74e151cf6299dfff0d888e918810ff24c141034 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 22 Aug 2026 19:43:35 +0200 Subject: [PATCH] Keep running events in the upcoming list until they end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Nächste Veranstaltungen" table selected events with `start > now`, so an event disappeared from the list the moment it began. Someone looking at the start page at 20:30 no longer saw the Plenum that had started at 20:00 and ran until 22:00, which is exactly when that information is most useful. Select on the end of the event instead, so an event stays listed for as long as it is still running. A currently running event sorts first, because the list is ordered by start time. For recurring events the end of the individual occurrence is needed, not the end of the series, so go through `getOccurrenceDetails()`. That also resolves occurrences overridden via RECURRENCE-ID. The chronological break out of the iteration keeps using the raw occurrence time, which stays monotonic even when an override moves a single occurrence. `ICAL.Event.endDate` falls back to DURATION and, for all-day events, to the following day, so events without an explicit DTEND keep working. The `maxDays` window still applies to the start of an event, so a long running event does not extend the window. This is not a regression from the commit below, the Python generator it replaced filtered on `dtstart >= start` in the same way. Checked against https://berlin.ccc.de/calendars/all.ics: the Plenum (20:00 to 22:00) is now listed at 20:30 and 21:59 and gone at 22:01, and the multi-day Amateurfunk trip (30.10. 12:00 to 01.11. 18:00) stays listed throughout. Fixes: c28f04c6e85c ("switch to ics files; make calendars work; fix some minor issues") Assisted-by: Claude:claude-opus-5 Signed-off-by: Hauke Mehrtens --- static/js/upcoming.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/static/js/upcoming.js b/static/js/upcoming.js index cc8ad0b..f031b4d 100644 --- a/static/js/upcoming.js +++ b/static/js/upcoming.js @@ -4,7 +4,7 @@ import ICAL from "https://unpkg.com/ical.js/dist/ical.min.js"; * Parse an ICS calendar and return upcoming event occurrences. * * @param {string} icsText The contents of the .ics file - * @param {Date} now Events must start after this date + * @param {Date} now Events must still be running at this date * @param {number} maxEvents Maximum number of events to return * @param {number} maxDays Maximum number of days into the future * @returns {{start: Date, name: string, url: string}[]} url is empty when the event has no URL @@ -38,17 +38,19 @@ function getUpcomingEvents(icsText, now, maxEvents, maxDays) { break; } - const start = occurrence.toJSDate(); - // Recurrences are chronological, so we're done // once we pass the end of our search window. - if (start > end) { + if (occurrence.toJSDate() > end) { break; } - if (start > now) { + // Details resolve the times of occurrences overridden by RECURRENCE-ID. + const details = event.getOccurrenceDetails(occurrence); + + // A running event stays listed until it is over, so filter on its end. + if (details.endDate.toJSDate() > now) { events.push({ - start, + start: details.startDate.toJSDate(), name: event.summary ?? "", url, }); @@ -57,7 +59,7 @@ function getUpcomingEvents(icsText, now, maxEvents, maxDays) { } else { const start = event.startDate.toJSDate(); - if (start > now && start <= end) { + if (start <= end && event.endDate.toJSDate() > now) { events.push({ start, name: event.summary ?? "",