diff --git a/app/page.tsx b/app/page.tsx index e7642d1..40329da 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -5,6 +5,7 @@ import { Legend } from "@/components/Legend"; import { EmptyState } from "@/components/EmptyState"; import { PARKS, groupByRegion } from "@/lib/parks"; import { openDb, getDateRange } from "@/lib/db"; +import { getTodayLocal } from "@/lib/env"; interface PageProps { searchParams: Promise<{ week?: string }>; @@ -18,9 +19,10 @@ function getWeekStart(param: string | undefined): string { return d.toISOString().slice(0, 10); } } - const today = new Date(); - today.setDate(today.getDate() - today.getDay()); - return today.toISOString().slice(0, 10); + const todayIso = getTodayLocal(); + const d = new Date(todayIso + "T00:00:00"); + d.setDate(d.getDate() - d.getDay()); + return d.toISOString().slice(0, 10); } function getWeekDates(sundayIso: string): string[] { @@ -32,9 +34,10 @@ function getWeekDates(sundayIso: string): string[] { } function getCurrentWeekStart(): string { - const today = new Date(); - today.setDate(today.getDate() - today.getDay()); - return today.toISOString().slice(0, 10); + const todayIso = getTodayLocal(); + const d = new Date(todayIso + "T00:00:00"); + d.setDate(d.getDate() - d.getDay()); + return d.toISOString().slice(0, 10); } export default async function HomePage({ searchParams }: PageProps) { @@ -42,7 +45,7 @@ export default async function HomePage({ searchParams }: PageProps) { const weekStart = getWeekStart(params.week); const weekDates = getWeekDates(weekStart); const endDate = weekDates[6]; - const today = new Date().toISOString().slice(0, 10); + const today = getTodayLocal(); const isCurrentWeek = weekStart === getCurrentWeekStart(); const db = openDb(); diff --git a/app/park/[id]/page.tsx b/app/park/[id]/page.tsx index 92309e8..5dd6d7b 100644 --- a/app/park/[id]/page.tsx +++ b/app/park/[id]/page.tsx @@ -10,6 +10,7 @@ import { ParkMonthCalendar } from "@/components/ParkMonthCalendar"; import { LiveRidePanel } from "@/components/LiveRidePanel"; import type { RideStatus, RidesFetchResult } from "@/lib/scrapers/sixflags"; import type { LiveRidesResult } from "@/lib/scrapers/queuetimes"; // used as prop type below +import { getTodayLocal } from "@/lib/env"; interface PageProps { params: Promise<{ id: string }>; @@ -23,8 +24,8 @@ function parseMonthParam(param: string | undefined): { year: number; month: numb return { year: y, month: m }; } } - const now = new Date(); - return { year: now.getFullYear(), month: now.getMonth() + 1 }; + const [y, m] = getTodayLocal().split("-").map(Number); + return { year: y, month: m }; } 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); if (!park) notFound(); - const today = new Date().toISOString().slice(0, 10); + const today = getTodayLocal(); const { year, month } = parseMonthParam(monthParam); const db = openDb(); diff --git a/components/WeekCalendar.tsx b/components/WeekCalendar.tsx index b895c56..f3df39f 100644 --- a/components/WeekCalendar.tsx +++ b/components/WeekCalendar.tsx @@ -3,6 +3,7 @@ import Link from "next/link"; import type { Park } from "@/lib/scrapers/types"; import type { DayData } from "@/lib/db"; import type { Region } from "@/lib/parks"; +import { getTodayLocal } from "@/lib/env"; interface WeekCalendarProps { parks: Park[]; @@ -222,7 +223,7 @@ function ParkRow({ } 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 firstMonth = parsedDates[0].month; diff --git a/lib/env.ts b/lib/env.ts index 9e13b93..36ae2f8 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -11,3 +11,25 @@ export function parseStalenessHours(envVar: string | undefined, defaultHours: nu const parsed = parseInt(envVar ?? "", 10); 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}`; +}