import dayjs from "dayjs"; import duration from "dayjs/plugin/duration"; import utc from "dayjs/plugin/utc"; import timezone from "dayjs/plugin/timezone"; import customParseFormat from "dayjs/plugin/customParseFormat"; import prettyMilliseconds from "pretty-ms"; dayjs.extend(utc); dayjs.extend(timezone); dayjs.extend(customParseFormat); dayjs.extend(duration); export const MS_PER_SECOND = 1000; export const MS_PER_MINUTE = 60 * MS_PER_SECOND; export const MS_PER_HOUR = 60 * MS_PER_MINUTE; export const MS_PER_DAY = 24 * MS_PER_HOUR; export const MS_PER_WEEK = MS_PER_DAY * 7; const resolveSystemTimezone = (): string => { try { return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC"; } catch { return "UTC"; } }; export const SYSTEM_TIMEZONE = resolveSystemTimezone(); export const resolveTimezone = (preferred?: string | null): string => preferred?.trim() || SYSTEM_TIMEZONE; export const formatDateWithTz = ( timestamp: string, format: string, timezone?: string ) => { if (!timestamp) { return "Unknown time"; } const tz = resolveTimezone(timezone); try { return dayjs(timestamp).tz(tz).format(format); } catch { return dayjs(timestamp).utc().format(format); } }; export const tickDateFormatLookup = (range: string) => { const tickFormatLookup: Record = { recent: "h:mm A", day: "h:mm A", week: "MM/D, h:mm A", month: "ddd. M/D", }; const format = tickFormatLookup[range]; if (format === undefined) { return ""; } return format; }; export const tooltipDateFormatLookup = (range: string) => { const dateFormatLookup: Record = { recent: "ddd. MMMM D, YYYY, hh:mm A", day: "ddd. MMMM D, YYYY, hh:mm A", week: "ddd. MMMM D, YYYY, hh:mm A", month: "ddd. MMMM D, YYYY", }; const format = dateFormatLookup[range]; if (format === undefined) { return ""; } return format; }; export const formatTimestamp = (timestamp: string | number | null): string => { if (!timestamp) return "-"; const date = new Date(timestamp); return date.toLocaleString(); }; export const formatMs = (ms: number): string => { return prettyMilliseconds(ms, { compact: true, formatSubMilliseconds: true, secondsDecimalDigits: 0, }); };