5690d61438
稽核輪(fix/console-truth-audit,總管派工+leo 三裁決): B1 時區:console 全站日期/時間顯示統一 Asia/Taipei(新 lib/taipei-time.ts, server 判定與頁面 client JS 同一套、等價性單測互鎖)。原本用瀏覽器本地 getter——換裝置就換日期;憑證頁改顯「日期+時分(台北)」:raw 1783349834 =台北 2026-07-06 22:57,7/6 顯示是真的,缺的是時分與固定時區。 B2 總庫數字(leo 裁:14-E 遺產 deprecated 不再顯示):總庫搜尋/設定頁頭部 統計改讀新 GET /console/kb-scale-data(精耕層 wiki 卡/三元組/已嵌入+最近 寫入,全 live、limit=1/stats 聚合不掃庫);搜尋仍搜全庫、結果 wiki_card 加「精耕」綠標;dashboard-data 的 entries 計數補 owner_id(原混租戶: 459,137 vs leo 458,732)。 B3 設定頁:vectorize 文案改具體事實(config kbdb_embed+acr update,#32 教訓)+live 狀態;新增 MCP token TTL 誠實佔位(GET /console/settings-data, 可調功能=Arcrun#19,不假裝能遠端改)。 C 今日完成/今日路線接 sprint 任務板(leo 拍板):比照 #36 等leo清單模式, 同一輪 Gitea fetch(90s CF cache 共用)解析「## 任務板」checkbox;「今日 完成」只認「完成(今天台北日)」標記,[x] 無日期不冒領;快取存原始 completed_days,跨台北午夜不誤算;板檔今天沒 commit → 頁面誠實標「今日 任務板未更新」;dash_task 降 fallback、燈號判定不變。parser 以 live 07a/07b 檔實測(標題抽取棄「首個粗體」——實讀發現會抽到完成註記)。 驗證:tsc exit 0;vitest 82/83(1 失敗=pre-existing executor「不存在的 零件」,stash 於 main 複驗同樣紅);新增 taipei-time 10 案例(含跨日/跨年/ client-server 等價/leo 實測 epoch)+任務板 parser 7 案例;兩頁 inline JS 渲染後抽 <script> node --check 全過(mistakes #24 手法)。
79 lines
3.5 KiB
TypeScript
79 lines
3.5 KiB
TypeScript
/**
|
||
* lib/taipei-time.ts 測試(fix/console-truth-audit):
|
||
* 1. server 版跨日案例——UTC 傍晚已是台北隔天(時區 bug 的核心場景)。
|
||
* 2. client 版(TAIPEI_CLIENT_JS,內嵌進 console 頁的 ES5 字串)用 new Function 求值,
|
||
* 與 server 版逐案對照——兩份實作漂移會直接紅,這是「同一套 helper」的客觀證據。
|
||
* 3. leo 實測案例:leo21c /credentials 的 gitea_token created_at=1783349834(epoch 秒)
|
||
* → 台北 2026-07-06 22:57(顯示 7/6 是真的,但原本只顯示日期且吃裝置時區——本修加時分固定台北)。
|
||
*/
|
||
import { describe, it, expect } from 'vitest';
|
||
import {
|
||
TAIPEI_CLIENT_JS,
|
||
taipeiDayKey,
|
||
taipeiDateStr,
|
||
taipeiDateTimeStr,
|
||
taipeiTimeStr,
|
||
} from '../src/lib/taipei-time';
|
||
|
||
// client 版求值:跟頁面一樣把字串當 JS 跑起來,拿到同名函式
|
||
const client = new Function(
|
||
`${TAIPEI_CLIENT_JS}; return { taipeiDayKey, taipeiDateStr, taipeiDateTimeStr, taipeiTimeStr, taipeiMonthDay };`,
|
||
)() as {
|
||
taipeiDayKey: (ms: number) => string;
|
||
taipeiDateStr: (ms: number) => string;
|
||
taipeiDateTimeStr: (ms: number) => string;
|
||
taipeiTimeStr: (ms: number) => string;
|
||
taipeiMonthDay: (ms: number) => { month: number; day: number };
|
||
};
|
||
|
||
describe('taipei-time — server 版', () => {
|
||
it('UTC 16:30 已是台北隔天 00:30(跨日核心案例)', () => {
|
||
const ms = Date.parse('2026-07-06T16:30:00Z');
|
||
expect(taipeiDayKey(ms)).toBe('2026-07-07');
|
||
expect(taipeiDateTimeStr(ms)).toBe('2026-07-07 00:30');
|
||
});
|
||
|
||
it('UTC 15:59 仍是台北同日 23:59(跨日邊界的另一側)', () => {
|
||
const ms = Date.parse('2026-07-06T15:59:00Z');
|
||
expect(taipeiDayKey(ms)).toBe('2026-07-06');
|
||
expect(taipeiDateTimeStr(ms)).toBe('2026-07-06 23:59');
|
||
});
|
||
|
||
it('跨月/跨年也對:UTC 12-31 20:00 → 台北 01-01 04:00', () => {
|
||
const ms = Date.parse('2026-12-31T20:00:00Z');
|
||
expect(taipeiDateStr(ms)).toBe('2027-01-01');
|
||
expect(taipeiTimeStr(ms)).toBe('04:00:00');
|
||
});
|
||
|
||
it('leo 實測值:credentials created_at=1783349834(epoch 秒)→ 台北 2026-07-06 22:57', () => {
|
||
expect(taipeiDateTimeStr(1783349834 * 1000)).toBe('2026-07-06 22:57');
|
||
// 同一時刻 UTC 是 14:57——若顯示端誤用 UTC 或別的裝置時區,日期/時間就會漂
|
||
expect(new Date(1783349834 * 1000).toISOString().slice(0, 16)).toBe('2026-07-06T14:57');
|
||
});
|
||
});
|
||
|
||
describe('taipei-time — client 版(TAIPEI_CLIENT_JS)與 server 版等價', () => {
|
||
const cases = [
|
||
Date.parse('2026-07-06T16:30:00Z'), // 跨日
|
||
Date.parse('2026-07-06T15:59:59Z'), // 跨日邊界前一秒
|
||
Date.parse('2026-12-31T20:00:00Z'), // 跨年
|
||
Date.parse('2026-02-28T17:00:00Z'), // 跨月(非閏年 2 月)
|
||
1783349834 * 1000, // leo 實測 credential created_at
|
||
0, // epoch 起點(1970-01-01 08:00 台北)
|
||
];
|
||
|
||
it('taipeiDayKey / DateStr / DateTimeStr / TimeStr 全案例一致', () => {
|
||
for (const ms of cases) {
|
||
expect(client.taipeiDayKey(ms)).toBe(taipeiDayKey(ms));
|
||
expect(client.taipeiDateStr(ms)).toBe(taipeiDateStr(ms));
|
||
expect(client.taipeiDateTimeStr(ms)).toBe(taipeiDateTimeStr(ms));
|
||
expect(client.taipeiTimeStr(ms)).toBe(taipeiTimeStr(ms));
|
||
}
|
||
});
|
||
|
||
it('taipeiMonthDay(頁首中文日期用):跨日案例回台北的月/日', () => {
|
||
expect(client.taipeiMonthDay(Date.parse('2026-07-06T16:30:00Z'))).toEqual({ month: 7, day: 7 });
|
||
expect(client.taipeiMonthDay(Date.parse('2026-12-31T20:00:00Z'))).toEqual({ month: 1, day: 1 });
|
||
});
|
||
});
|