fix: use local time with 3am cutover for today's date

new Date().toISOString() returns UTC, causing the calendar to advance
to the next day at 8pm EDT / 7pm EST. getTodayLocal() reads local
wall-clock time and rolls back one day before 3am so the calendar
stays on the current day through the night.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 20:15:52 -04:00
parent fdea8443fb
commit a87f97ef53
4 changed files with 38 additions and 11 deletions

View File

@@ -5,6 +5,7 @@ import { Legend } from "@/components/Legend";
import { EmptyState } from "@/components/EmptyState"; import { EmptyState } from "@/components/EmptyState";
import { PARKS, groupByRegion } from "@/lib/parks"; import { PARKS, groupByRegion } from "@/lib/parks";
import { openDb, getDateRange } from "@/lib/db"; import { openDb, getDateRange } from "@/lib/db";
import { getTodayLocal } from "@/lib/env";
interface PageProps { interface PageProps {
searchParams: Promise<{ week?: string }>; searchParams: Promise<{ week?: string }>;
@@ -18,9 +19,10 @@ function getWeekStart(param: string | undefined): string {
return d.toISOString().slice(0, 10); return d.toISOString().slice(0, 10);
} }
} }
const today = new Date(); const todayIso = getTodayLocal();
today.setDate(today.getDate() - today.getDay()); const d = new Date(todayIso + "T00:00:00");
return today.toISOString().slice(0, 10); d.setDate(d.getDate() - d.getDay());
return d.toISOString().slice(0, 10);
} }
function getWeekDates(sundayIso: string): string[] { function getWeekDates(sundayIso: string): string[] {
@@ -32,9 +34,10 @@ function getWeekDates(sundayIso: string): string[] {
} }
function getCurrentWeekStart(): string { function getCurrentWeekStart(): string {
const today = new Date(); const todayIso = getTodayLocal();
today.setDate(today.getDate() - today.getDay()); const d = new Date(todayIso + "T00:00:00");
return today.toISOString().slice(0, 10); d.setDate(d.getDate() - d.getDay());
return d.toISOString().slice(0, 10);
} }
export default async function HomePage({ searchParams }: PageProps) { export default async function HomePage({ searchParams }: PageProps) {
@@ -42,7 +45,7 @@ export default async function HomePage({ searchParams }: PageProps) {
const weekStart = getWeekStart(params.week); const weekStart = getWeekStart(params.week);
const weekDates = getWeekDates(weekStart); const weekDates = getWeekDates(weekStart);
const endDate = weekDates[6]; const endDate = weekDates[6];
const today = new Date().toISOString().slice(0, 10); const today = getTodayLocal();
const isCurrentWeek = weekStart === getCurrentWeekStart(); const isCurrentWeek = weekStart === getCurrentWeekStart();
const db = openDb(); const db = openDb();

View File

@@ -10,6 +10,7 @@ import { ParkMonthCalendar } from "@/components/ParkMonthCalendar";
import { LiveRidePanel } from "@/components/LiveRidePanel"; import { LiveRidePanel } from "@/components/LiveRidePanel";
import type { RideStatus, RidesFetchResult } from "@/lib/scrapers/sixflags"; import type { RideStatus, RidesFetchResult } from "@/lib/scrapers/sixflags";
import type { LiveRidesResult } from "@/lib/scrapers/queuetimes"; // used as prop type below import type { LiveRidesResult } from "@/lib/scrapers/queuetimes"; // used as prop type below
import { getTodayLocal } from "@/lib/env";
interface PageProps { interface PageProps {
params: Promise<{ id: string }>; params: Promise<{ id: string }>;
@@ -23,8 +24,8 @@ function parseMonthParam(param: string | undefined): { year: number; month: numb
return { year: y, month: m }; return { year: y, month: m };
} }
} }
const now = new Date(); const [y, m] = getTodayLocal().split("-").map(Number);
return { year: now.getFullYear(), month: now.getMonth() + 1 }; return { year: y, month: m };
} }
export default async function ParkPage({ params, searchParams }: PageProps) { export default async function ParkPage({ params, searchParams }: PageProps) {
@@ -34,7 +35,7 @@ export default async function ParkPage({ params, searchParams }: PageProps) {
const park = PARK_MAP.get(id); const park = PARK_MAP.get(id);
if (!park) notFound(); if (!park) notFound();
const today = new Date().toISOString().slice(0, 10); const today = getTodayLocal();
const { year, month } = parseMonthParam(monthParam); const { year, month } = parseMonthParam(monthParam);
const db = openDb(); const db = openDb();

View File

@@ -3,6 +3,7 @@ import Link from "next/link";
import type { Park } from "@/lib/scrapers/types"; import type { Park } from "@/lib/scrapers/types";
import type { DayData } from "@/lib/db"; import type { DayData } from "@/lib/db";
import type { Region } from "@/lib/parks"; import type { Region } from "@/lib/parks";
import { getTodayLocal } from "@/lib/env";
interface WeekCalendarProps { interface WeekCalendarProps {
parks: Park[]; parks: Park[];
@@ -222,7 +223,7 @@ function ParkRow({
} }
export function WeekCalendar({ parks, weekDates, data, grouped }: WeekCalendarProps) { export function WeekCalendar({ parks, weekDates, data, grouped }: WeekCalendarProps) {
const today = new Date().toISOString().slice(0, 10); const today = getTodayLocal();
const parsedDates = weekDates.map(parseDate); const parsedDates = weekDates.map(parseDate);
const firstMonth = parsedDates[0].month; const firstMonth = parsedDates[0].month;

View File

@@ -11,3 +11,25 @@ export function parseStalenessHours(envVar: string | undefined, defaultHours: nu
const parsed = parseInt(envVar ?? "", 10); const parsed = parseInt(envVar ?? "", 10);
return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultHours; return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultHours;
} }
/**
* Returns today's date as YYYY-MM-DD using local wall-clock time with a 3 AM
* switchover. Before 3 AM local time we still consider it "yesterday", so the
* calendar doesn't flip to the next day at midnight while people are still out
* at the park.
*
* Important: `new Date().toISOString()` returns UTC, which causes the date to
* advance at 8 PM EDT (UTC-4) or 7 PM EST (UTC-5) — too early. This helper
* corrects that by using local year/month/day components and rolling back one
* day when the local hour is before 3.
*/
export function getTodayLocal(): string {
const now = new Date();
if (now.getHours() < 3) {
now.setDate(now.getDate() - 1);
}
const y = now.getFullYear();
const m = String(now.getMonth() + 1).padStart(2, "0");
const d = String(now.getDate()).padStart(2, "0");
return `${y}-${m}-${d}`;
}