/** * Asia/Taipei(UTC+8,無日光節約)時間顯示 helper(fix/console-truth-audit,2026-07-07) * * 為什麼存在:console 各頁原本用瀏覽器本地時區(`Date#getFullYear/getMonth/...`)渲染 * created_at / last_used_at / 刷新時間戳——顯示結果隨看的裝置漂移(換個時區的裝置就換一個 * 日期),且與駕駛艙 #36 的「台北日曆日」判定(`taipeiDayKey`)不是同一套。本檔把 * 「epoch ms → 台北牆鐘」收斂成唯一實作: * - server 側(TS):dashboard-data 的台北日判定 import 這裡。 * - client 側(頁面 inline JS):console.ts / console-dashboard.ts 的 HTML 內嵌 * `TAIPEI_CLIENT_JS`(同邏輯的 ES5 版)。等價性由 tests/taipei-time.test.ts 用 * `new Function` 求值 client 版與 server 版逐案對照,防兩份漂移。 * * 台北無 DST、固定 +8——用「UTC getter +固定位移」即可,不需要 Intl 時區資料庫。 */ export const TAIPEI_OFFSET_MS = 8 * 3600 * 1000; function pad2(n: number): string { return String(n).padStart(2, '0'); } /** 台北日曆日 key('YYYY-MM-DD')。#36 駕駛艙「這筆是不是今天寫的」判定用。 */ export function taipeiDayKey(ms: number): string { return new Date(ms + TAIPEI_OFFSET_MS).toISOString().slice(0, 10); } /** 台北日期字串 'YYYY-MM-DD'(顯示用,同 taipeiDayKey,語意別名)。 */ export function taipeiDateStr(ms: number): string { return taipeiDayKey(ms); } /** 台北日期+時分 'YYYY-MM-DD HH:MM'。 */ export function taipeiDateTimeStr(ms: number): string { const d = new Date(ms + TAIPEI_OFFSET_MS); return `${taipeiDayKey(ms)} ${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}`; } /** 台北時分秒 'HH:MM:SS'(駕駛艙「上次刷新」戳記用)。 */ export function taipeiTimeStr(ms: number): string { const d = new Date(ms + TAIPEI_OFFSET_MS); return `${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}:${pad2(d.getUTCSeconds())}`; } /** * client 版(ES5,內嵌進 console 頁 inline