Files
Arcrun/cypher-executor/tests/taipei-time.test.ts
cloud-worker 5690d61438 fix(console): 真實性稽核修正——時區統一台北、精耕層數字、今日完成接 sprint 任務板
稽核輪(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 手法)。
2026-07-07 12:25:31 +00:00

79 lines
3.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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=1783349834epoch 秒)
* → 台北 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=1783349834epoch 秒)→ 台北 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 });
});
});