spb/internetpressure
Public
TypeScript 36.3%
Python 31.8%
Go 18%
JavaScript 9.8%
Shell 1.9%
SQL 1.4%
CSS 0.5%
1/** Formatting helpers. All numerals are rendered in mono/tabular; all timestamps go through formatTime(). */23export type TimeMode = 'utc' | 'local';45const nf = (digits: number) => new Intl.NumberFormat('en-US', { minimumFractionDigits: digits, maximumFractionDigits: digits });6const NF0 = nf(0);7const NF1 = nf(1);8const NF2 = nf(2);910export function fmt(v: number | null | undefined, digits = 1): string {11 if (v == null || Number.isNaN(v)) return '—';12 return digits === 0 ? NF0.format(v) : digits === 2 ? NF2.format(v) : digits === 1 ? NF1.format(v) : nf(digits).format(v);13}14export const fmtInt = (v: number | null | undefined) => fmt(v, 0);1516/** Signed delta with a true minus sign: +6.3 / −2.1 / 0.0 */17export function fmtDelta(v: number | null | undefined, digits = 1): string {18 if (v == null || Number.isNaN(v)) return '—';19 const s = fmt(Math.abs(v), digits);20 if (v > 0) return `+${s}`;21 if (v < 0) return `−${s}`;22 return s;23}2425export function fmtPct(ratio: number | null | undefined, digits = 0): string {26 if (ratio == null || Number.isNaN(ratio)) return '—';27 return `${fmt(ratio * 100, digits)} %`;28}2930export function fmtMs(v: number | null | undefined, digits = 0): string {31 if (v == null || Number.isNaN(v)) return '—';32 return `${fmt(v, digits)} ms`;33}3435export function fmtBytes(b: number | null | undefined): string {36 if (b == null) return '—';37 const u = ['B', 'KB', 'MB', 'GB', 'TB'];38 let i = 0;39 let v = b;40 while (v >= 1024 && i < u.length - 1) {41 v /= 1024;42 i++;43 }44 return `${fmt(v, i === 0 ? 0 : 1)} ${u[i]}`;45}4647export function fmtRatio(v: number | null | undefined): string {48 if (v == null || Number.isNaN(v)) return '—';49 return `${fmt(v, v >= 10 ? 0 : 1)}×`;50}5152export function fmtDuration(seconds: number | null | undefined): string {53 if (seconds == null || Number.isNaN(seconds)) return '—';54 const s = Math.max(0, Math.round(seconds));55 if (s < 60) return `${s} s`;56 const m = Math.floor(s / 60);57 if (m < 60) return `${m} min`;58 const h = Math.floor(m / 60);59 const rm = m % 60;60 if (h < 48) return rm ? `${h} h ${rm} min` : `${h} h`;61 const d = Math.floor(h / 24);62 return `${d} d ${h % 24} h`;63}6465/** "3 s ago", "2 min ago", "4 h ago" — relative to `nowMs`. */66export function fmtAgo(ts: string | number | Date | null | undefined, nowMs = Date.now()): string {67 if (!ts) return '—';68 const t = typeof ts === 'number' ? ts : new Date(ts).getTime();69 if (Number.isNaN(t)) return '—';70 const s = Math.max(0, Math.round((nowMs - t) / 1000));71 if (s < 60) return `${s} s ago`;72 const m = Math.floor(s / 60);73 if (m < 60) return `${m} min ago`;74 const h = Math.floor(m / 60);75 if (h < 48) return `${h} h ago`;76 return `${Math.floor(h / 24)} d ago`;77}7879export type TimeStyle = 'time' | 'short' | 'full' | 'date' | 'month';8081/** Single time formatter. UTC is the default (spec §67: UTC storage, local display with a toggle). */82export function formatTime(ts: string | number | Date | null | undefined, mode: TimeMode = 'utc', style: TimeStyle = 'short'): string {83 if (!ts) return '—';84 const d = ts instanceof Date ? ts : new Date(ts);85 if (Number.isNaN(d.getTime())) return '—';86 const tz = mode === 'utc' ? 'UTC' : undefined;87 const opts: Intl.DateTimeFormatOptions =88 style === 'time'89 ? { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, timeZone: tz }90 : style === 'date'91 ? { year: 'numeric', month: 'short', day: '2-digit', timeZone: tz }92 : style === 'month'93 ? { year: 'numeric', month: 'long', timeZone: tz }94 : style === 'full'95 ? { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, timeZone: tz, timeZoneName: 'short' }96 : { month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false, timeZone: tz };97 let out = new Intl.DateTimeFormat('en-GB', opts).format(d);98 if (mode === 'utc' && (style === 'short' || style === 'time')) out += ' UTC';99 return out;100}101102export function isoDate(ts: string | Date): string {103 return (ts instanceof Date ? ts : new Date(ts)).toISOString().slice(0, 10);104}105106export const MONTH_NAMES = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];107