知識 · 日期與時間
Unix 時間戳記是什麼?
簡答
Unix 時間戳記是從 1970 年 1 月 1 日 00:00:00 UTC(稱為 Unix 紀元)到現在經過的秒數,不計入閏秒。它是一個不帶時區的整數,所以 1700000000 在世界各地都代表同一個時刻:2023 年 11 月 14 日 22:13:20 UTC。JavaScript 和許多 API 改用毫秒,數字會多出三位。
這個數字如何定義
POSIX 以固定公式定義「自紀元起的秒數」:每一天都剛好算 86,400 秒,從 1970-01-01T00:00:00Z 開始計算。紀元之前的時刻是負數,所以 -1 就是 1969-12-31T23:59:59Z。
因為這個值以 UTC 計算,所以不帶時區,也沒有日光節約時間。要轉成當地時間是另一個步驟,需要指定時區,例如 Asia/Tokyo 或 America/New_York。
| 時間戳記(秒) | UTC 日期與時間 | 備註 |
|---|---|---|
0 | 1970-01-01T00:00:00Z | Unix 紀元 |
1000000000 | 2001-09-09T01:46:40Z | 第一個 10 位數的值 |
1234567890 | 2009-02-13T23:31:30Z | 知名的里程碑 |
1700000000 | 2023-11-14T22:13:20Z | 最近的整數值 |
1791936000 | 2026-10-14T00:00:00Z | 2026 年 10 月 14 日 UTC 午夜 |
2147483647 | 2038-01-19T03:14:07Z | 有號 32 位元整數的最大值 |
秒、毫秒與其他單位
傳統的 Unix 時間戳記以秒為單位,但許多系統會存更細的單位。對目前的日期來說,看位數是最快的分辨方法:
| 單位 | 目前的位數 | 同一時刻的範例 | 常見於 |
|---|---|---|---|
| 秒 | 10 | 1700000000 | Unix 工具、PHP time()、Python time.time()(浮點數)、JWT exp 宣告 |
| 毫秒 | 13 | 1700000000000 | JavaScript Date.now()、Java System.currentTimeMillis() |
| 微秒 | 16 | 1700000000000000 | PostgreSQL 內部、部分記錄系統 |
| 奈秒 | 19 | 1700000000000000000 | Go time.UnixNano()、高精度追蹤 |
單位混用是最常見的時間戳記錯誤。把以秒為單位的值傳給 JavaScript 的 new Date(),會落在 1970 年 1 月;把毫秒值當成秒來讀,則會跑到幾萬年後。在 JavaScript 中,用 Math.floor(Date.now() / 1000) 取得秒數,再用 new Date(seconds * 1000) 轉回來。
不計入閏秒
UTC 偶爾會插入閏秒,以配合地球自轉;自 1972 年以來已加了 27 次。Unix 時間不理會閏秒:POSIX 公式假設每天都是 86,400 秒,所以閏秒會依系統不同,被重複一次或分攤到一段較長的時間。
實際上,這代表兩個時間戳記相減得到的經過時間,可能與實際相差其間的閏秒數。日常排程不受影響;科學或金融計時則會改用 TAI 或 GPS 時間。國際計時組織已於 2022 年表決,在 2035 年前停止加入閏秒。
2038 年問題
較舊的軟體以有號 32 位元整數儲存 Unix 時間,最大值是 2147483647,會在 2038-01-19T03:14:07Z 到達。再過一秒,計數器就會溢位成 -2147483648,被解讀為 1901-12-13T20:45:52Z。
- 現代 64 位元作業系統、程式語言和資料庫使用 64 位元的
time_t,可用約 2,920 億年。 - 風險仍存在於嵌入式裝置、舊檔案格式、MySQL
TIMESTAMP這類 32 位元資料庫欄位,以及只為時間保留四個位元組的二進位協定。 - 20 年期憑證、房貸、到期日等遠期數值早已跨過 2038 年,所以這個錯誤可能在那天之前就出現。
何時用時間戳記,何時用日期字串
時刻(事件何時發生、權杖何時到期)請存成 Unix 時間戳記或 UTC 日期字串。兩者都沒有歧義,也能正確排序。
在給人看的記錄檔、API 和檔案中,請使用 2026-10-14T09:30:00Z 這樣好讀的 ISO 8601 字串,因為 1791970200 一眼看不出意思。未來的在地活動,例如明年春天巴黎 09:00 的會議,請存成當地時間加 IANA 時區名稱:日光節約時間規則可能在那天到來前改變,預先算好的時間戳記到時就會出錯。
常見問題
Unix 時間戳記一定是 UTC 嗎?
是的。它從 1970 年 1 月 1 日 UTC 午夜起算,所以數字本身沒有時區。只有轉換成可讀的當地時間時才需要時區。
如何取得目前的 Unix 時間戳記?
在 Linux 或 macOS 終端機執行 date +%s,在 JavaScript 用 Math.floor(Date.now() / 1000),在 Python 用 int(time.time())。都會回傳自紀元起的秒數。
為什麼我的時間戳記轉出來是 1970 年?
這個值幾乎可以確定是秒,卻被當成毫秒讀取。傳給需要毫秒的函式(例如 JavaScript 的 new Date())之前,先乘以 1,000。
Unix 時間戳記可以是負數嗎?
可以。負值從紀元往回計算,所以 -86400 是 1969 年 12 月 31 日 00:00 UTC。有些舊系統不接受負值,用這種方式儲存 1970 年以前的日期前請先測試。