// The business day for every tenant is the Kenyan calendar day // (Africa/Nairobi, EAT). EAT is a fixed UTC+3 with no daylight saving, so a // constant offset is exact — no timezone database needed. // // Never use `new Date().setHours(0)` or `toISOString().slice(0, 10)` for // "today" on the server: on Vercel the server clock is UTC, which would // start the business day at 03:00 EAT and push early-morning sales onto // the previous day. const EAT_OFFSET_MS = 3 * 60 * 60 * 1000; const DAY_MS = 24 * 60 * 60 * 1000; const DATE_RE = /^\d{4}-\d{2}-\d{2}$/; /** Today's business day as YYYY-MM-DD. */ export function todayNairobi(now: Date = new Date()): string { return new Date(now.getTime() + EAT_OFFSET_MS).toISOString().slice(0, 10); } export function isBusinessDate(value: string): boolean { if (!DATE_RE.test(value)) return false; const d = new Date(value + "T00:00:00.000Z"); return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 10) === value; } /** The UTC instants [start, end) covering one business day. */ export function dayRangeNairobi(date: string): { start: Date; end: Date } { if (!isBusinessDate(date)) throw new Error(`Invalid business date: ${date}`); const start = new Date(new Date(date + "T00:00:00.000Z").getTime() - EAT_OFFSET_MS); return { start, end: new Date(start.getTime() + DAY_MS) }; } /** Start of the business day containing `now`. */ export function startOfTodayNairobi(now: Date = new Date()): Date { return dayRangeNairobi(todayNairobi(now)).start; } /** Start of the current business month (1st, 00:00 EAT). */ export function startOfMonthNairobi(now: Date = new Date()): Date { return dayRangeNairobi(todayNairobi(now).slice(0, 8) + "01").start; }