export function formatDuration(ms: number): string { const totalSec = Math.floor(ms / 1000); const h = Math.floor(totalSec / 3600); const m = Math.floor((totalSec % 3600) / 60); const s = totalSec % 60; if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`; return `${m}:${String(s).padStart(2, '0')}`; } export function formatFileSize(bytes: number): string { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; } export function formatDateTime(iso: string | undefined): string | undefined { if (!iso) return undefined; const d = new Date(iso); if (Number.isNaN(d.getTime())) return undefined; return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short', }).format(d); } /** Human "X days Y hours" style for big spans (e.g. total library playtime). * Shows the two most-significant non-zero units; falls back to "0m". */ export function formatLongDuration(seconds: number): string { if (seconds <= 0) return '0m'; const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const mins = Math.floor((seconds % 3600) / 60); const parts: string[] = []; if (days) parts.push(`${days}d`); if (hours) parts.push(`${hours}h`); if (mins && parts.length < 2) parts.push(`${mins}m`); return parts.slice(0, 2).join(' ') || '0m'; } export function formatCount(n: number): string { if (n < 1000) return String(n); if (n < 1_000_000) return `${(n / 1000).toFixed(1)}K`; return `${(n / 1_000_000).toFixed(1)}M`; }