/** * 相對時間格式化(共用 util) * * 從 `components/cloud/remote-device-badge.tsx` 的 `formatRelativeTime` 抽出共用, * 讓「模型共享」的 owner 資訊列 / 共享時間沿用同一份規格與 i18n key,避免重複實作。 * * 規格(components.md §10.3): * - < 60 秒 → 「剛剛」(remote.lastSeen.justNow) * - < 60 分 → 「X 分鐘前」(remote.lastSeen.minutesAgo) * - < 24 時 → 「X 小時前」(remote.lastSeen.hoursAgo) * - ≥ 24 時 → 絕對時間「MM/DD HH:mm」 */ /** * @param isoString ISO 8601 時間字串(無法解析時回空字串) * @param nowMs 當前時間(ms)— 由 caller 傳入以便測試 deterministic * @param t i18n 翻譯函式(需含 remote.lastSeen.* key) */ export function formatRelativeTime( isoString: string, nowMs: number, t: (k: string) => string, ): string { const ts = Date.parse(isoString); if (Number.isNaN(ts)) return ""; const diffSec = Math.max(0, Math.floor((nowMs - ts) / 1000)); if (diffSec < 60) return t("remote.lastSeen.justNow"); const diffMin = Math.floor(diffSec / 60); if (diffMin < 60) return t("remote.lastSeen.minutesAgo").replace("{n}", String(diffMin)); const diffHour = Math.floor(diffMin / 60); if (diffHour < 24) return t("remote.lastSeen.hoursAgo").replace("{n}", String(diffHour)); const d = new Date(ts); const mm = String(d.getMonth() + 1).padStart(2, "0"); const dd = String(d.getDate()).padStart(2, "0"); const hh = String(d.getHours()).padStart(2, "0"); const mi = String(d.getMinutes()).padStart(2, "0"); return `${mm}/${dd} ${hh}:${mi}`; }