為什麼有兩個標準
Unix 時間最初以秒定義——對一個每個時鐘滴答遞增一次的系統來說,整數很自然。JavaScript 的 Date 物件於 1995 年引入,選擇毫秒以支援瀏覽器中次秒級的事件計時。許多資料庫與後端語言保留 Unix 秒為預設。如今兩種標準在每段跨越 JavaScript 與伺服器邊界的程式碼中並存,這就是為什麼一個值可能看起來有效卻表示數萬年之後的日期。
每種語言使用的單位
記住這種分裂最穩妥的方法是:瀏覽器 Date API 通常要毫秒,Unix 風格的伺服器 API 通常暴露秒,而較新的時間函式庫往往兩者都提供。閱讀第三方 API 文件時,不要僅憑語言推斷單位;查看欄位說明與範例。
- Milliseconds: JavaScript Date.now(), Java System.currentTimeMillis(), Java Instant.toEpochMilli(), .NET ToUnixTimeMilliseconds()
- Seconds: Python time.time() (float), PHP time(), Go time.Now().Unix(), Ruby Time.now.to_i, C time(NULL), PostgreSQL EXTRACT(EPOCH)
- Both: Rust — duration.as_secs() for seconds, duration.as_millis() for milliseconds
- Python note: time.time() returns a float, so milliseconds are available as int(time.time() * 1000)
從值自動辨識單位
對現代日期可靠的經驗法則:10 位數字是秒,13 位數字是毫秒。當前 Unix 秒約為 17–21 億(10 位),直到西元 33658 年才會達到 13 位。當前 Unix 毫秒已是 13 位。該法則在從 2000 年代到未來數千年間最為可靠;對歷史日期、負日期或精簡的測試夾具,請使用顯式單位而非猜測。
- 10 位的值 → 秒(如 1700000000 = 2023-11-14 UTC)
- 13 位的值 → 毫秒(如 1700000000000 = 2023-11-14 UTC)
- 16 位的值 → 微秒(除以 1,000,000 得到秒)
- 負值 → 1970 年 1 月 1 日之前的日期(秒或毫秒)
安全的轉換模式
轉換本身是簡單的算術;難點在於選擇在哪裡進行轉換。在系統邊界處轉換,為轉換後的值命名,避免把含糊的原始數字穿過多層傳遞。
- Seconds to milliseconds: seconds * 1000
- Milliseconds to whole seconds — JavaScript: Math.floor(ms / 1000)
- Milliseconds to whole seconds — Python: ms // 1000
- Milliseconds to whole seconds — Go: ms / 1000 (integer division)
- Universal guard in JavaScript: const toMs = ts => ts < 1e11 ? ts * 1000 : ts
單位 bug 在生產中如何顯現
秒對毫秒的 bug 常能通過驗證,因為兩個值都只是數字。它通常稍後表現為不可能的日期:把秒當作毫秒時 JavaScript 顯示 1970 年 1 月,後端把毫秒當作秒時顯示遙遠的未來年份。
- JavaScript UI 中出現 1970 年日期 → 把秒傳給 new Date() 而未乘以 1000
- Python、Go 或 PHP 中出現 50000 年以上 → 把毫秒傳給了期望秒的 API
- 永不過期的過期權杖 → 過期時間戳以錯誤單位儲存
- 立即消失的快取項 → 毫秒被除了兩次或秒被乘了兩次
- 範圍為空的分析圖表 → 查詢邊界使用了與已存事件時間戳不同的單位
API 與資料庫的命名慣例
一個很小的命名慣例就能避免大多數此類 bug。除非文件異常清晰,否則永遠不要發布名為 timestamp 的 API 欄位。優先使用同時包含含義與單位的欄位名。
- createdAtMs — Unix milliseconds, best for JavaScript clients
- createdAtSeconds — Unix seconds, common for backend services
- createdAtIso — ISO 8601 string, useful for human-readable API responses
- expiresAtUnixSeconds — explicit enough for auth tokens and signed URLs
- event_time TIMESTAMPTZ — native database time, with conversion handled by the database
毫秒 vs 秒常見問題
A tiny naming convention prevents most of these bugs. Never publish an API field called timestamp unless the documentation is unusually clear. Prefer field names that include both meaning and unit.
- createdAtMs — Unix milliseconds, best for JavaScript clients
- createdAtSeconds — Unix seconds, common for backend services
- createdAtIso — ISO 8601 string, useful for human-readable API responses
- expiresAtUnixSeconds — explicit enough for auth tokens and signed URLs
- event_time TIMESTAMPTZ — native database time, with conversion handled by the database
Microseconds (16 digits) and nanoseconds (19 digits)
Most production timestamps are seconds (10 digits) or milliseconds (13 digits), but two higher-precision formats also appear in real systems — microseconds and nanoseconds. The same digit-counting rule extends.
- 10 digits ≈ Unix seconds (~1.7×10⁹ today)
- 13 digits ≈ Unix milliseconds (~1.7×10¹²)
- 16 digits ≈ Unix microseconds (~1.7×10¹⁵) — Python time.time_ns()/1000, Postgres TIMESTAMP precision 6
- 19 digits ≈ Unix nanoseconds (~1.7×10¹⁸) — Java Instant.toEpochNano(), Go time.UnixNano(), Temporal.Instant.epochNanoseconds
- PostgreSQL to_timestamp() takes seconds with an optional fractional part; passing milliseconds yields a date around the year 55000
- Convert from any precision to milliseconds via integer arithmetic before doing further math
- Silent truncation: if a database column has millisecond precision but you store nanoseconds, the bottom 6 digits are dropped on insert
How many microseconds in a second? 1 second to milliseconds, microseconds to milliseconds
A quick reference for the unit math that drives every seconds/milliseconds/microseconds bug. The questions "how many microseconds in a second", "1 second to milliseconds", and "microseconds to milliseconds" are all powers of 1000 — but every order of magnitude is one place where production code goes wrong. Keep the table below within reach when writing high-resolution timestamp code.
- 1 second to milliseconds = 1,000 ms (10³)
- How many microseconds in a second? = 1,000,000 µs (10⁶)
- 1 second to nanoseconds = 1,000,000,000 ns (10⁹)
- Microseconds to milliseconds = µs ÷ 1,000 (10³ step down)
- Milliseconds to microseconds = ms × 1,000
- Nanoseconds to microseconds = ns ÷ 1,000
- Common precision: JavaScript Date.now() = ms, performance.now() = sub-ms float, Go time.UnixNano() = ns, Postgres TIMESTAMP precision 6 = µs
- Bug pattern: an API returns µs, code divides by 1000 once expecting seconds — actually got ms; result is 1000× off
Millisecond timer, time to ms, milliseconds to seconds conversion
Quick reference for the unit phrasings: "time to ms" (any time value scaled into milliseconds), "milliseconds to seconds conversion" (÷1000), and "millisecond timer" (a high-resolution timer for short intervals). For measuring elapsed time prefer a monotonic clock — wall-clock time can jump backwards on NTP correction or DST.
- Time to ms / time to milliseconds: seconds × 1000 = ms; microseconds ÷ 1000 = ms; nanoseconds ÷ 1,000,000 = ms
- Milliseconds to seconds conversion: ms ÷ 1000 = seconds; Math.floor(ms/1000) for integer seconds
- Millisecond timer (JavaScript): performance.now() returns sub-ms float since page load; Date.now() returns wall-clock ms
- Millisecond timer (Python): time.perf_counter() (monotonic float seconds); time.monotonic_ns() returns ns
- Millisecond timer (Java): System.nanoTime() for monotonic ns; Instant.now() for wall-clock ns precision
- Stopwatch rule: use monotonic clocks for elapsed time; wall-clock can jump backwards on NTP or DST
FAQ
- Is a 13-digit timestamp always milliseconds?
- For modern real-world Unix timestamps, yes: 13 digits usually means milliseconds. Very far-future seconds timestamps can also reach 13 digits, so critical systems should still carry explicit unit metadata.
- Should I store seconds or milliseconds?
- Store the unit your system naturally uses, but document it and keep it consistent. JavaScript-heavy systems often use milliseconds; Unix-style backends and many databases commonly use seconds or native datetime columns.
- Why use Math.floor(ms / 1000) instead of ms / 1000?
- Unix seconds are usually whole seconds. Math.floor removes the fractional part so APIs expecting integer seconds do not receive a decimal value.
- How do I convert milliseconds to seconds?
- Divide by 1000 and drop the fraction: Math.floor(ms / 1000) in JavaScript, ms // 1000 in Python, or ms / 1000 with integer division in Go. To go the other way, multiply seconds by 1000.