From 1ac607a7123b0f5116e67edab282e844cf8437af Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sun, 9 Mar 2025 16:49:57 +0100 Subject: [PATCH] Use unix timestamps in timetable logic Parse the iso date strings into millseconds from the unix epoch and use that through the timetable logic instead of reparsing the strings over and over. --- components/Timetable.vue | 56 +++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/components/Timetable.vue b/components/Timetable.vue index 5a7526b..bb30b90 100644 --- a/components/Timetable.vue +++ b/components/Timetable.vue @@ -75,7 +75,7 @@ const oneMinMs = 60 * 1000; type Edge = { type: "start" | "end", slot: TimeSlot }; /** Point in time where multiple edges meet. */ -type Junction = { ts: string, edges: Edge[] }; +type Junction = { ts: number, edges: Edge[] }; /** Span of time between two adjacent junctions */ type Span = { @@ -90,8 +90,8 @@ type Span = { and the endpoint spans are always empty and at least one hour. */ type Stretch = { - start: string, - end: string, + start: number, + end: number, spans: Span[]; } @@ -156,9 +156,9 @@ function* edgesFromEvents(events: Iterable): Generator { } function junctionsFromEdges(edges: Iterable) { - const junctions = new Map(); + const junctions = new Map(); for (const edge of edges) { - const ts = edge.slot[edge.type]; + const ts = Date.parse(edge.slot[edge.type]); const junction = junctions.get(ts); if (junction) { junction.edges.push(edge); @@ -204,14 +204,11 @@ function* spansFromJunctions( } function createStretch(spans: Span[]): Stretch { - let startTs = Date.parse(spans[0].start.ts) - oneHourMs; - let endTs = Date.parse(spans[spans.length - 1].end.ts) + oneHourMs; + let start = spans[0].start.ts - oneHourMs; + let end = spans[spans.length - 1].end.ts + oneHourMs; // Extend stretch to nearest whole hours - startTs = Math.floor(startTs / oneHourMs) * oneHourMs; - endTs = Math.ceil(endTs / oneHourMs) * oneHourMs; - // Convert back to ISO date string - let start = isoStringFromTs(startTs); - let end = isoStringFromTs(endTs); + start = Math.floor(start / oneHourMs) * oneHourMs; + end = Math.ceil(end / oneHourMs) * oneHourMs; return { spans: [ { @@ -237,7 +234,7 @@ function* stretchesFromSpans(spans: Iterable, minSeparation: number): Gene // Based on how spans are generated I can assume that an empty span // will only occur between two spans with timeslots in them. if (span.locations.size === 0 - && Date.parse(span.end.ts) - Date.parse(span.start.ts) >= minSeparation + && span.end.ts - span.start.ts >= minSeparation ) { yield createStretch(currentSpans); currentSpans = []; @@ -251,8 +248,8 @@ function* stretchesFromSpans(spans: Iterable, minSeparation: number): Gene /** Cuts up a span by whole hours that crosses it */ function* cutSpansByHours(span: Span): Generator { - const startHour = Date.parse(span.start.ts) / oneHourMs; - const endHour = Date.parse(span.end.ts) / oneHourMs; + const startHour = span.start.ts / oneHourMs; + const endHour = span.end.ts / oneHourMs; let currentStart = startHour; let currentEnd = Math.min(Math.floor(startHour + 1), endHour); if (currentEnd === endHour) { @@ -262,22 +259,22 @@ function* cutSpansByHours(span: Span): Generator { yield { start: span.start, - end: { ts: isoStringFromTs(currentEnd * oneHourMs), edges: [] }, + end: { ts: currentEnd * oneHourMs, edges: [] }, locations: span.locations, } currentStart = currentEnd; while (++currentEnd < endHour) { yield { - start: { ts: isoStringFromTs(currentStart * oneHourMs), edges: [] }, - end: { ts: isoStringFromTs(currentEnd * oneHourMs), edges: [] }, + start: { ts: currentStart * oneHourMs, edges: [] }, + end: { ts: currentEnd * oneHourMs, edges: [] }, locations: span.locations, } currentStart += 1; } yield { - start: { ts: isoStringFromTs(currentStart * oneHourMs), edges: [] }, + start: { ts: currentStart * oneHourMs, edges: [] }, end: span.end, locations: span.locations, } @@ -322,14 +319,14 @@ function tableElementsFromStretches( if (first) { first = false; startColumnGroup(); - startDay(stretch.start.slice(0, 10)); - startHour(stretch.start.slice(11, 16)); + startDay(isoStringFromTs(stretch.start).slice(0, 10)); + startHour(isoStringFromTs(stretch.start).slice(11, 16)); for(const location of locations) { startLocation(location.id); } } else { startColumnGroup("break"); - const dayName = stretch.start.slice(0, 10) + const dayName = isoStringFromTs(stretch.start).slice(0, 10) const lastDayHeader = dayHeaders[dayHeaders.length - 1] const sameDay = dayName === lastDayHeader.content && lastDayHeader.span; if (!sameDay) @@ -343,7 +340,7 @@ function tableElementsFromStretches( startColumnGroup(); if (!sameDay) startDay(dayName); - startHour(stretch.start.slice(11, 16)); + startHour(isoStringFromTs(stretch.start).slice(11, 16)); for(const location of locations) { startLocation(location.id); } @@ -351,9 +348,8 @@ function tableElementsFromStretches( for (const span of stretch.spans) { for (const cutSpan of cutSpansByHours(span)) { - const startTs = Date.parse(cutSpan.start.ts); - const endTs = Date.parse(cutSpan.end.ts); - const durationMs = endTs - startTs; + const end = cutSpan.end.ts; + const durationMs = end - cutSpan.start.ts; for (const location of locations) { const rows = locationRows.get(location.id)!; @@ -365,11 +361,11 @@ function tableElementsFromStretches( } pushColumn(durationMs / oneMinMs); - if (endTs % oneDayMs === 0) { - startDay(cutSpan.end.ts.slice(0, 10)); + if (end % oneDayMs === 0) { + startDay(isoStringFromTs(cutSpan.end.ts).slice(0, 10)); } - if (endTs % oneHourMs === 0) { - startHour(cutSpan.end.ts.slice(11, 16)); + if (end % oneHourMs === 0) { + startHour(isoStringFromTs(cutSpan.end.ts).slice(11, 16)); } } }