Skip to content
File

Blob: src/client/lib/format.ts

typescript38 lines
1export function formatDate(iso: string | null | undefined, opts?: { relative?: boolean }): string {
2 if (!iso) return "—";
3 const d = new Date(iso);
4 if (Number.isNaN(d.getTime())) return iso;
5 if (opts?.relative) {
6 const diffMs = d.getTime() - Date.now();
7 const absMs = Math.abs(diffMs);
8 const sec = Math.round(absMs / 1000);
9 const min = Math.round(sec / 60);
10 const hr = Math.round(min / 60);
11 const day = Math.round(hr / 24);
12 const past = diffMs < 0;
13 if (sec < 45) return past ? "just now" : "in a moment";
14 if (min < 60) return past ? `${min}m ago` : `in ${min}m`;
15 if (hr < 24) return past ? `${hr}h ago` : `in ${hr}h`;
16 if (day < 30) return past ? `${day}d ago` : `in ${day}d`;
17 }
18 return d.toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" });
19}
20 
21export function formatBytes(bytes: number | null | undefined): string {
22 if (bytes == null) return "—";
23 if (bytes < 1024) return `${bytes} B`;
24 const units = ["KB", "MB", "GB", "TB"];
25 let value = bytes / 1024;
26 let unitIdx = 0;
27 while (value >= 1024 && unitIdx < units.length - 1) {
28 value /= 1024;
29 unitIdx++;
30 }
31 return `${value.toFixed(value >= 10 ? 0 : 1)} ${units[unitIdx]}`;
32}
33 
34export function truncate(str: string, max: number): string {
35 if (str.length <= max) return str;
36 return str.slice(0, Math.max(0, max - 1)) + "…";
37}