Unix 時間戳格式詳解
一份所有 Unix 時間戳格式的完整參考 —— 秒、毫秒、微秒、ISO 8601 和 RFC 2822 —— 配有範例顯示每種語言和資料庫使用哪種格式,以及如何一眼區分它們。
一眼看盡每種 Unix 時間戳格式
Unix 時間戳只是一個數字,而它的格式其實只是它的單位 —— 它從 1970 年 1 月 1 日 UTC 起數得有多細。單位幾乎總能從位數讀出:10 位是秒,13 是毫秒,16 是微秒,19 是奈秒。兩種字串格式 ISO 8601 和 RFC 2822 則是自描述的。下表是全貌;其後的各節講解每種格式以及如何區分它們。
| 格式 | 位數 | 範例 | 使用者 |
|---|---|---|---|
| 秒 | 10 | 1700000000 | Python, PHP, Go, Ruby, C, SQL |
| 毫秒 | 13 | 1700000000000 | JavaScript, Java, .NET |
| 微秒 | 16 | 1700000000000000 | PostgreSQL, Rust |
| 奈秒 | 19 | 1700000000000000000 | Go UnixNano, 追蹤系統 |
| ISO 8601 | 字串 | 2023-11-15T06:13:20Z | API、日誌(自描述) |
| RFC 2822 | 字串 | Wed, 15 Nov 2023 06:13:20 GMT | 郵件、HTTP 標頭 |
秒級 Unix 時間 —— 通用格式
最常見的格式:一個 32 位或 64 位整數,計自 1970 年 1 月 1 日 00:00:00 UTC 起的整秒數。目前是約 17 億的 10 位數字。
- 範例:1700000000 = 2023-11-15 06:13:20 UTC
- 使用者:Python time.time(), PHP time(), Go time.Now().Unix(), Ruby Time.now.to_i, C time(NULL)
- 儲存為:32 位 int(舊式,最大年份 2038)、64 位 int(現代,數十億年內安全)
- 資料庫:MySQL UNIX_TIMESTAMP(), PostgreSQL EXTRACT(EPOCH FROM NOW())::BIGINT
毫秒級 Unix 時間 —— JavaScript 的格式
自 Unix 紀元起的毫秒:一個提供毫秒精度的 13 位整數。這是 JavaScript 的 Date 物件內部使用的格式。
- 範例:1700000000000 = 2023-11-15 06:13:20.000 UTC
- 使用者:JavaScript Date.now(), Java System.currentTimeMillis(), .NET DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
- 轉換為秒:Math.floor(ms / 1000)
- 從秒轉換:seconds * 1000
ISO 8601 —— 可讀的標準
ISO 8601 是把日期和時間表示為字串的國際標準。與 Unix 時間戳不同,它是自描述的:格式同時編碼了日期/時間和時區偏移。
- 2023-11-15T06:13:20Z —— UTC(Z 後綴表示 UTC)
- 2023-11-15T01:13:20-05:00 —— 帶明確 UTC 偏移(EST)
- 2023-11-15T06:13:20.000Z —— 帶毫秒
- JavaScript:date.toISOString() 總是回傳帶 Z 後綴的 UTC
- Python:datetime.isoformat(),Go:time.Format(time.RFC3339)
RFC 2822 —— 郵件與 HTTP 日期格式
RFC 2822(郵件由 RFC 5322 更新,HTTP 由 RFC 9110 沿用)是郵件標頭和 HTTP 回應中使用的可讀日期格式。JavaScript 的 Date.toUTCString() 回傳這種格式。
- 範例:Wed, 15 Nov 2023 06:13:20 GMT
- 用於:HTTP 回應標頭(Last-Modified, Date, Expires)、郵件標頭(Date:)
- JavaScript:date.toUTCString()
- 在現代 API 中較少見,但在 Web 基礎設施中仍廣泛遇到
如何偵測時間戳格式
當你收到一個未知的時間戳值時,這些規則能識別它的格式。位數決定每一種數值情形;兩種字串格式一看便知。
| 線索 | 格式 |
|---|---|
| 10 位 | Unix 秒 |
| 13 位 | Unix 毫秒 |
| 16 位 | 微秒 |
| 19 位 | 奈秒 |
| 含 T 或 Z | ISO 8601 |
| 逗號或星期名 | RFC 2822 |
| 負整數 | 1970 年之前的秒或毫秒 |
- 常識檢查:任何數值都應解碼為目前時代的可信日期(10 位秒大致是 2001—2038 年)
- 靠近 1970 年或數千年之外的日期意味著單位讀錯了
微秒與奈秒
一些高精度系統使用比毫秒更小的單位。它們在應用層程式碼中很少見,但出現在底層系統、資料庫內部和可觀測性工具裡。
- 微秒(µs):16 位整數 —— Rust SystemTime as_micros(), PostgreSQL clock_gettime()
- 奈秒(ns):19 位整數 —— Go time.Now().UnixNano(), Rust SystemTime as_nanos()
- PostgreSQL EXTRACT(EPOCH) 回傳一個以微秒為小數部分的浮點數
- 把奈秒轉換為秒:除以 1,000,000,000(1e9)
解析度與次秒精度
上面每種格式承載不同的時間解析度。選擇一種格式就是選擇你能多精細地區分兩個時刻 —— 從一秒到一奈秒。
- 1 秒解析度:Unix 秒(10 位)、傳統 POSIX time_t
- 1 毫秒:JavaScript Date, MongoDB BSON Date, Java Instant.toEpochMilli()
- 1 微秒:Chrome/WebKit 時間戳, Python datetime.timestamp(), PostgreSQL timestamp precision 6
- 100 奈秒:Windows FILETIME, .NET DateTime.Ticks
- 1 奈秒:Java Instant(完整精度), Go time.UnixNano(), JS Temporal.Instant.epochNanoseconds(BigInt)
- 皮秒及以下:PTP/IEEE 1588 線路格式(一秒的 1/2^32)、NTP 小數欄位
- 選擇滿足你需求的最粗解析度 —— 次秒精度常在 JSON 序列化或字串往返時遺失
- 在格式間轉換時,經由 Unix 毫秒或奈秒(透過 BigInt)—— 那是保留精度的最小公分母
時間戳格式轉換器
在 Unix 時間與你在實務中遇到的平台專用時間戳格式之間轉換:
FAQ
- Unix 時間戳是多少位?
- 現代的秒級 Unix 時間戳是 10 位(約 17 億);毫秒級是 13 位。微秒是 16 位,奈秒是 19 位。
- JavaScript 使用哪種時間戳格式?
- JavaScript 的 Date 以毫秒運作 —— Date.now() 回傳一個 13 位的毫秒時間戳,new Date(ms) 預期毫秒。把 Unix 秒乘以 1000 再傳給 Date。
- Unix 時間和 ISO 8601 有什麼區別?
- Unix 時間是自 1970 年 UTC 起的單個秒數或毫秒數,不帶時區。ISO 8601 是一個自描述字串,如 2023-11-15T06:13:20Z,它編碼了日期、時間和偏移。
- RFC 2822 日期格式是什麼?
- RFC 2822(由 RFC 5322 更新)是郵件和 HTTP 標頭中使用的可讀日期格式,如 "Wed, 15 Nov 2023 06:13:20 GMT"。JavaScript 用 date.toUTCString() 產生它。
- 我怎麼偵測一個時間戳是秒還是毫秒?
- 數位數:10 位的值是秒,13 位的值是毫秒。如果一個值轉換出靠近 1970 年或遠在未來的日期,就是單位讀錯了。