import dayjs from 'dayjs'; /** * Doormile timestamps are IST (Asia/Kolkata) wall-clock stored in Postgres * `timestamp without time zone` columns. Some responses come back with a * trailing Z/offset anyway — a known Go+pgx footgun where a naive DB timestamp * loads into `time.Time` under the UTC location and gets marshalled with a * false "Z" suffix. dayjs reads a Z-suffixed string as a real UTC instant and * converts it to the browser's local time, adding a spurious +5:30 on top of * digits that were already correct IST. * * Stripping any trailing zone marker before parsing makes both cases — truly * naive, or naive-with-false-Z — render and bucket identically as the raw * wall-clock digits. Every page that displays or buckets a Doormile timestamp * must go through here, or two pages will disagree about which day a row is on. */ export const parseDoormileTimestamp = (raw) => { if (!raw) return dayjs(null); const stripped = String(raw).replace(/(Z|[+-]\d{2}:?\d{2})$/, ''); return dayjs(stripped); }; /** `raw` rendered in `format`, or `fallback` when the timestamp is unusable. */ export const formatDoormileTimestamp = (raw, format = 'DD MMM YYYY, hh:mm A', fallback = '—') => { const parsed = parseDoormileTimestamp(raw); return parsed.isValid() ? parsed.format(format) : fallback; }; /** The calendar day (`YYYY-MM-DD`) a Doormile timestamp falls on. */ export const doormileDay = (raw) => { const parsed = parseDoormileTimestamp(raw); return parsed.isValid() ? parsed.format('YYYY-MM-DD') : undefined; };