一個月在這頁只有 30 天那麼長
起因是 29 天前的記錄寫「29 天前」、30 天前的寫「1 個月前」,中間沒有「一個月零幾天」。為找切換點,我把這頁腳本單獨跑了一輪:模板 341 行 / 12362 位元組,腳本塊原樣執行,DOM 只給按 id 建的樁,時區在命令列釘成兩檔(getTimezoneOffset 實測 -480 分鐘與 +300 分鐘)。
被測的是時間戳轉換這一頁,相對時間掛在第一個 tab 的結果區裡。
六檔除數是寫死的常數
relativeTime(L285–L295)是一條 if 鏈,除數依次 1000 / 60000 / 3600000 / 86400000 / 2592000000 / 31536000000,沒有日曆參與:2592000000 除以 86400000 得 30,年檔同理得 365,「一個月」在這頁恆等於 30 天。交界讀數:
| diff(毫秒) | 讀數 |
|---|---|
| 59999 / 60000 | 59 秒前 / 1 分鐘前 |
| 86399999 / 86400000 | 23 小時前 / 1 天前 |
| 2591999999 / 2592000000 | 29 天前 / 1 個月前 |
| 31535999999 / 31536000000 | 12 個月前 / 1 年前 |
兩檔時區各跑一遍,表的差值與讀數逐字相同,只有起點 ts 差 46800000 毫秒。過去與未來只差後綴:數字出自 Math.abs,方向出自 sign 的 diff>=0,diff=0 落「0 秒前」。
跨月與跨閏年各讀到什麼
28 天(2419200000 毫秒)讀「28 天前」,29 天讀「29 天前」,30 天整才第一次見「1 個月前」,31 天(2678400000)仍只讀「1 個月前」;跨閏的 366 天與平年 365 天同讀「1 年前」。13 個 30 天(33696000000 毫秒)已落年檔,字面「13 個月」不可達。按真實日曆加月份是另一頁:時間加減計算。
圖 1:跨月與跨閏的讀數階梯,30 天與 31 天落在同一格。
位數識別不是 10 與 13 兩檔
輸入側(L306–L309)先 parseInt(val,10),再判 String(ts).length<=10 才乘 1000:識別按位數走,卻不是那兩檔。13 位「1717200000123」不乘,iso 出「2024-06-01T00:00:00.123Z」;11 位與 12 位同樣被當毫秒,落 1970-07-18 與 1975-06-11。負數最彆扭:「-1717200000」的負號佔進 String 長度成 11,落 1969-12-12T03:00:00.000Z,9 位「-171720000」反而正確走秒檔——分界在位數,不在正負。
早退只有三條:空串藏掉結果區,NaN 彈 toast「請輸入有效的時間戳數字」,越界彈「無效的時間戳」,後兩條只彈提示、六格殘留上一輪讀數。其餘連提示都沒有:「20240531」當秒乘 1000 落 1970-08-23T06:22:11.000Z。
「填入現在」丟掉的正好是秒
fillNowDt(L323–L328)先按 getTimezoneOffset()*60000 平移再 slice(0,16)。取 FIXED_NOW=1717214437500:UTC+8 檔平移後是 24 字元「2024-06-01T12:00:37.500Z」,截成 16 字元、丟 8 字元,回跑得 1717214400,比真實秒 1717214437 低 37 秒;UTC-5 檔同值截出「2024-05-31T23:00」,回跑同為 1717214400。同一日期框串「2024-06-01T00:00」兩檔給 1717171200 與 1717218000,差 46800 秒即 13 小時,全頁沒有時區控件(grep select 命中 0 處)。
圖 2:截斷前後各剩幾字元,與兩檔偏移的差。
取整方向與往還原差多少
Math.floor 向負無窮取整:FIXED_NOW=-500 時秒格讀「-1」,-1500 讀「-2」,-1717200000500 讀「-1717200001」,比截絕對值少 1;這串回填後再餵回去,因長度 11 又被當毫秒,讀「54 年後」。同檔內往返乾淨:「1717200000」回填日期框再回跑差 0,「1717200000123」的毫秒只進 iso 不進本地框,回填後尾數歸零、差 123。
多次行為與沒測到的
計時器樁實測 setInterval 只註冊 1 條、間隔 1000 毫秒(L270);NOW 推進 86400000 後,同一個 ts=1717200000000 從「0 秒前」變「1 天前」,這格每次現讀、不緩存。真實跳字與渲染次數本輪純 Node 無渲染器,標未實測。
文案與代碼差在哪兩條
config/tools.php 的 timestamp 條目(L102–L115)逐條判,10 條裡 [一致] 6、[部分一致] 2、[衝突] 2。衝突兩條:description(L111)的「多時區選擇」——grep select 命中 0 處,日期框只是 type="datetime-local";intro(L112)連同模板 L51 的標籤「北京時間(Asia/Shanghai)」——那格走本機 getter,UTC-5 檔實測顯示「2024-05-31 19:00:00」。部分一致是 summary「支援時區」與佔位符位數口徑;本頁只讀本機 Date。日期按月份加減落到哪一天,站內舊文寫過一次,這裡不複述。
常見問題
Q:為什麼 31 天前的記錄只寫「1 個月前」?
月檔除數寫死為 2592000000 毫秒即 30 天,超出部分按常數取整。
Q:13 位毫秒要不要先自己換算?
不用換算,但它不只認 13 位:判據是不超過 10 位才乘 1000,11 位與 12 位一樣被當毫秒。
Q:結果區的數一定是這一輪的嗎?
不一定,非法輸入只彈提示,六格殘留上一輪讀數。