/** * Environment variable helpers. */ /** * Parse a staleness window from an env var string (interpreted as hours). * Falls back to `defaultHours` when the value is missing, non-numeric, * non-finite, or <= 0 — preventing NaN from silently breaking staleness checks. */ export function parseStalenessHours(envVar: string | undefined, defaultHours: number): number { 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}`; } /** * Returns true when the current local time is within 1 hour before open * or 1 hour after close, based on a hoursLabel like "10am – 6pm". * Falls back to true when the label can't be parsed. */ export function isWithinOperatingWindow(hoursLabel: string): boolean { const m = hoursLabel.match( /^(\d+)(?::(\d+))?(am|pm)\s*[–-]\s*(\d+)(?::(\d+))?(am|pm)$/i ); if (!m) return true; const toMinutes = (h: string, min: string | undefined, period: string) => { let hours = parseInt(h, 10); const minutes = min ? parseInt(min, 10) : 0; if (period.toLowerCase() === "pm" && hours !== 12) hours += 12; if (period.toLowerCase() === "am" && hours === 12) hours = 0; return hours * 60 + minutes; }; const openMin = toMinutes(m[1], m[2], m[3]); const closeMin = toMinutes(m[4], m[5], m[6]); const now = new Date(); const nowMin = now.getHours() * 60 + now.getMinutes(); return nowMin >= openMin - 60 && nowMin <= closeMin + 60; }