fix: render today's wait chart in viewer's local time + close stale live state
Build and Deploy / Build & Push (push) Successful in 1m8s

Two related polish fixes for the ride detail page:

1. Wait-time chart x-axis now uses Intl.DateTimeFormat with no timezone
   argument, so an Eastern-time user viewing a Pacific park sees ET on
   the axis. Backend now sends recorded_at (UTC) alongside local_time.

2. Ride-history endpoint now applies the same operating-window gate the
   /rides route uses. Queue-Times keeps reporting yesterday's last wait
   with isOpen=true overnight, which made the "Right now" pill show a
   live wait time when the park was actually closed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 08:23:00 -04:00
parent 7c88a3e568
commit 44d079efb9
4 changed files with 30 additions and 6 deletions
+14 -3
View File
@@ -12,6 +12,7 @@
import { Hono } from "hono";
import { PARK_MAP } from "../../../lib/parks";
import {
getDayData,
getRideBySlug,
getRideSamplesForDay,
getRideDailyAggregates,
@@ -22,6 +23,7 @@ import {
import { liveRidesCache, fastLaneCache } from "../services/live-cache";
import { slugifyRideName } from "../../../lib/ride-slug";
import { lookupFastLane } from "../../../lib/scrapers/sixflags-waittimes";
import { getTodayLocal, isWithinOperatingWindow } from "../../../lib/env";
const app = new Hono();
@@ -72,6 +74,15 @@ app.get("/:parkId/rides/:slug", (c) => {
const fastLaneCacheEntry = fastLaneCache.get(parkId);
const flMatch = liveMatch && fastLaneCacheEntry ? lookupFastLane(liveMatch.name, fastLaneCacheEntry) : null;
// Operating-window gate. Queue-Times keeps reporting yesterday's last wait
// with isOpen=true overnight, so we override to closed when we're outside
// the park's hours — same behaviour as the /rides route.
const todayData = getDayData(parkId, getTodayLocal());
const withinWindow = todayData?.hoursLabel
? isWithinOperatingWindow(todayData.hoursLabel, park.timezone)
: false;
const liveIsOpen = Boolean(liveMatch?.isOpen) && withinWindow;
c.header("Cache-Control", "public, max-age=60, stale-while-revalidate=120");
return c.json({
park: {
@@ -91,10 +102,10 @@ app.get("/:parkId/rides/:slug", (c) => {
},
live: liveMatch
? {
isOpen: liveMatch.isOpen,
waitMinutes: liveMatch.waitMinutes,
isOpen: liveIsOpen,
waitMinutes: liveIsOpen ? liveMatch.waitMinutes : 0,
hasFastLane: Boolean(flMatch?.hasFastLane),
fastLaneMinutes: liveMatch.isOpen ? (flMatch?.fastLaneMinutes ?? null) : null,
fastLaneMinutes: liveIsOpen ? (flMatch?.fastLaneMinutes ?? null) : null,
lastUpdated: liveMatch.lastUpdated,
}
: null,