JavaScript Date.now():取得與轉換 Unix 時間戳
聚焦 JavaScript Date.now() 的指南:取得當前 Unix 時間戳、轉換秒與毫秒、把時間戳變成 Date 物件、用 Intl 格式化,並避免常見的解析陷阱。
JavaScript 內部如何儲存時間
每個 JavaScript Date 在內部都是一個表示自 Unix 紀元(1970 年 1 月 1 日 00:00:00 UTC)以來毫秒數的 64 位浮點數。這個數就是 Date.getTime() 和 Date.now() 回傳的值。Date 內部不儲存時區——它始終是一個 UTC 毫秒計數。只有在為顯示而格式化日期時時區資訊才重要,這就是為什麼同一個 Date 物件在洛杉磯可能顯示為週一晚上,在東京顯示為週二早上。本文聚焦於 Date.now() 和轉換時間戳;若想更全面地了解 JavaScript 中每一項時間戳任務,請參閱下方連結的完整參考指南。
取得當前 Unix 時間戳
毫秒用 Date.now(),秒用 Math.floor(Date.now() / 1000)。兩者都被廣泛支援,且無需匯入。重要的命名習慣是在變數名中包含單位:createdAtMs、expiresAtSeconds 或 unixSeconds。帶單位的名稱能防止未來的 API 使用者猜測一個無單位的時間戳欄位意味著什麼。
- Date.now() → 1700000000000 (milliseconds, 13 digits)
- Math.floor(Date.now() / 1000) → 1700000000 (seconds, 10 digits)
- +new Date() → same as Date.now() via unary coercion
- new Date().getTime() → same result, slightly more verbose
Date.now() vs performance.now()
Date.now() 用於掛鐘時間戳:日誌、API 負載、資料庫欄位、快取過期,以及任何需要與真實日曆時間對齊的東西。performance.now() 用於測量當前頁面或行程內的經過時長。它是單調且高精度的,但不是 Unix 時間戳,且若無額外參考點便無法轉換為真實日期。
- 當值將被儲存、傳送到 API 或作為日期顯示時,使用 Date.now()
- 測量算繪、解析或請求耗時時,使用 performance.now()
- 不要把 performance.now() 作為事件時間存入資料庫
- 不要為安全敏感的計時相減兩個 Date.now() 值;系統時鐘更改會影響它們
把時間戳轉換為 Date
Date 建構函式接受毫秒。如果你的時間戳是秒(10 位),傳入前請乘以 1000。忘記這一點是 JavaScript 中最常見的時間戳錯誤。一個快速檢查是位數:當前 Unix 秒為 10 位,當前 Unix 毫秒為 13 位,而 Date 建構函式呼叫應當收到 13 位的毫秒形式。
- new Date(1700000000 * 1000) → Tue Nov 14 2023 22:13:20 UTC ✓ correct
- new Date(1700000000) → Tue Jan 20 1970 16:13:20 UTC ✗ missing × 1000
- new Date(1700000000 * 1000).toISOString() → '2023-11-14T22:13:20.000Z'
- new Date(1700000000 * 1000).toUTCString() → 'Tue, 14 Nov 2023 22:13:20 GMT'
用 Intl 進行時區感知格式化
用 Intl.DateTimeFormat 取得按地區設定和時區的輸出。它自動處理日光節約時間,且無需外部函式庫。對於儀表板、管理工具、狀態頁和面向使用者的時間戳,這是最安全的內建途徑,因為它讓你顯式選擇地區設定和 IANA 時區。
- new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'long' }).format(date)
- date.toLocaleString('en-GB', { timeZone: 'Europe/London', hour12: false })
- date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
- new Intl.DateTimeFormat('en-CA', { timeZone: tz }).formatToParts(date) → array of {type, value} for custom layouts
安全地解析日期字串
解析是 JavaScript 變得出人意料的地方。帶顯式 Z 或偏移的 ISO 字串是安全的,因為它們標識一個確切的瞬間。裸日期和非正式字串更易讀,但常依賴瀏覽器規則或執行階段時區。對於 API 契約,優先使用帶時區的 ISO 8601 字串,或把單位寫入欄位名的數值 Unix 時間戳。
- Safe: new Date('2026-05-19T14:30:00Z') — explicit UTC
- Safe: new Date('2026-05-19T10:30:00-04:00') — explicit offset
- Risky: new Date('05/19/2026') — locale-dependent and ambiguous
- Risky: new Date('2026-05-19 10:30') — not a strict ISO timestamp in all runtimes
JavaScript 中常見的時間戳錯誤
- 寫成 new Date(1700000000) 而非 new Date(1700000000 * 1000) —— 落在 1970 而非 2023
- getMonth() 回傳 0–11,而非 1–12 —— 顯示時始終用 date.getMonth() + 1
- new Date('2024-01-01') 解析為 UTC 午夜;new Date('2024/01/01') 解析為本地午夜
- 為「明天」加 86400000 毫秒會在日光節約時間切換處出錯 —— 改用 setDate(d.getDate() + 1)
- 用 === 比較 Date 物件總會失敗 —— 改為比較它們的 .getTime() 值
推薦的 JavaScript 時間戳清單
最簡單的生產模式是儲存一個規範的瞬間,只在邊緣進行格式化。時間戳保持 UTC,名稱中包含單位,只在介面或報表層轉換為可讀時區。
- 僅瀏覽器狀態和 JavaScript Date 建構使用 Unix 毫秒
- 呼叫以秒記錄 Unix 時間的 API 時使用 Unix 秒
- 當人可能檢查負載時使用帶 Z 或顯式偏移的 ISO 8601
- 顯示使用帶顯式 timeZone 的 Intl.DateTimeFormat
- 當本地日曆日期重要時,圍繞日光節約時間邊界加入測試
JavaScript 時間戳常見問題
- Date.now() 回傳秒還是毫秒?
- Date.now() 回傳自 1970 年 1 月 1 日 00:00:00 UTC 以來的毫秒。當 API 期望 Unix 秒時,除以 1000 並使用 Math.floor()。
- 為什麼 new Date(1700000000) 顯示 1970?
- Date 建構函式期望毫秒。1700000000 是秒時間戳,所以 JavaScript 把它讀作紀元後僅 17 億毫秒。請用 new Date(1700000000 * 1000)。
- JavaScript Date 會儲存時區嗎?
- 不會。Date 儲存一個 UTC 毫秒計數。時區只在用 toString()、toLocaleString() 或 Intl.DateTimeFormat 等方法格式化時才被套用。
- 如何把 Unix 時間戳轉換為 JavaScript Date?
- 向建構函式傳入毫秒:10 位秒值用 new Date(seconds * 1000),13 位毫秒值用 new Date(ms)。忘記 × 1000 就是 2023 年的時間戳可能算繪為 1970 的原因。