diff --git a/src/lib/tz.ts b/src/lib/tz.ts new file mode 100644 index 0000000..6f656a1 --- /dev/null +++ b/src/lib/tz.ts @@ -0,0 +1,32 @@ +import { fromZonedTime, toZonedTime, format as formatTz } from "date-fns-tz"; + +/** + * Firm timezone — all calendar entries are entered and displayed in EST/EDT + * regardless of the browser's local timezone. + */ +export const FIRM_TZ = "America/New_York"; + +/** + * Convert a "wall clock" date + HH:mm string entered in EST into an ISO UTC + * timestamp suitable for Postgres `timestamptz`. Handles DST automatically. + * + * Example: ("2024-07-04", "09:00") → "2024-07-04T13:00:00.000Z" (EDT, -04:00) + * ("2024-01-15", "09:00") → "2024-01-15T14:00:00.000Z" (EST, -05:00) + */ +export function estWallTimeToUTC(dateStr: string, timeStr: string): string { + // Build a naive local-style string and tell date-fns-tz to interpret it as EST. + const naive = `${dateStr}T${timeStr.length === 5 ? `${timeStr}:00` : timeStr}`; + return fromZonedTime(naive, FIRM_TZ).toISOString(); +} + +/** Format a UTC ISO timestamp in EST using a date-fns format token. */ +export function formatInEST(iso: string | Date, fmt: string): string { + const d = typeof iso === "string" ? new Date(iso) : iso; + return formatTz(toZonedTime(d, FIRM_TZ), fmt, { timeZone: FIRM_TZ }); +} + +/** Get a Date object representing the EST wall-clock for a UTC ISO. */ +export function toESTDate(iso: string | Date): Date { + const d = typeof iso === "string" ? new Date(iso) : iso; + return toZonedTime(d, FIRM_TZ); +}