Files
oysqn.app/app/utils/toronto.ts

84 lines
2.8 KiB
TypeScript

export const TZ = 'America/Toronto'
/** YYYY-MM-DD for right now in Toronto */
export function todayToronto(): string {
return toDateToronto(new Date())
}
/** YYYY-MM-DD in Toronto for any Date */
export function toDateToronto(date: Date): string {
return new Intl.DateTimeFormat('en-CA', { timeZone: TZ }).format(date)
}
/**
* Add n calendar days to a YYYY-MM-DD string.
* Uses noon UTC so the shift is always exactly 24 h and never crosses
* a Toronto DST boundary ambiguously.
*/
export function addDays(isoDate: string, n: number): string {
const d = new Date(isoDate + 'T12:00:00Z')
d.setUTCDate(d.getUTCDate() + n)
return d.toISOString().slice(0, 10)
}
/** HH:MM in Toronto for a UTC ISO string */
export function fmtTime(utcIso: string): string {
return new Date(utcIso).toLocaleTimeString('en-CA', {
timeZone: TZ,
hour: '2-digit',
minute: '2-digit',
hour12: false,
})
}
/** "Wednesday, April 20" style label for a YYYY-MM-DD string */
export function fmtDateLong(isoDate: string): string {
return new Date(isoDate + 'T12:00:00Z').toLocaleDateString('en-CA', {
timeZone: TZ,
weekday: 'long',
month: 'long',
day: 'numeric',
})
}
/** { weekday: "Wed", short: "Apr 20" } for a YYYY-MM-DD string */
export function fmtDayHeader(isoDate: string): { weekday: string; short: string } {
const d = new Date(isoDate + 'T12:00:00Z')
return {
weekday: d.toLocaleDateString('en-CA', { timeZone: TZ, weekday: 'short' }),
short: d.toLocaleDateString('en-CA', { timeZone: TZ, month: 'short', day: 'numeric' }),
}
}
/**
* YYYY-MM-DD of the Monday that starts the ISO week containing isoDate.
* Uses the en-CA weekday name to determine day-of-week in Toronto.
*/
export function weekMonday(isoDate: string): string {
const d = new Date(isoDate + 'T12:00:00Z')
const wd = new Intl.DateTimeFormat('en-CA', { timeZone: TZ, weekday: 'short' }).format(d)
const offsets: Record<string, number> = { Mon: 0, Tue: 1, Wed: 2, Thu: 3, Fri: 4, Sat: 5, Sun: 6 }
const offset = offsets[wd] ?? 0
const monday = new Date(d)
monday.setUTCDate(d.getUTCDate() - offset)
return monday.toISOString().slice(0, 10)
}
/** All 7 YYYY-MM-DD strings for the ISO week containing isoDate (Mon → Sun) */
export function weekDates(isoDate: string): string[] {
const mon = weekMonday(isoDate)
return Array.from({ length: 7 }, (_, i) => addDays(mon, i))
}
/**
* UTC range string pair that safely covers all Toronto-local timestamps
* falling within the isoFrom…isoTo date range.
* Adds a 1-day buffer on each side so client-side date filtering is authoritative.
*/
export function utcRange(isoFrom: string, isoTo: string): { from: string; to: string } {
return {
from: addDays(isoFrom, -1) + 'T00:00:00Z',
to: addDays(isoTo, +1) + 'T23:59:59Z',
}
}