cv.cm

知識 · 日期與時間

Unix 時間戳記是什麼?

閱讀約 6 分鐘

簡答

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 日期與時間備註
01970-01-01T00:00:00ZUnix 紀元
10000000002001-09-09T01:46:40Z第一個 10 位數的值
12345678902009-02-13T23:31:30Z知名的里程碑
17000000002023-11-14T22:13:20Z最近的整數值
17919360002026-10-14T00:00:00Z2026 年 10 月 14 日 UTC 午夜
21474836472038-01-19T03:14:07Z有號 32 位元整數的最大值

秒、毫秒與其他單位

傳統的 Unix 時間戳記以秒為單位,但許多系統會存更細的單位。對目前的日期來說,看位數是最快的分辨方法:

單位目前的位數同一時刻的範例常見於
秒101700000000Unix 工具、PHP time()、Python time.time()(浮點數)、JWT exp 宣告
毫秒131700000000000JavaScript Date.now()、Java System.currentTimeMillis()
微秒161700000000000000PostgreSQL 內部、部分記錄系統
奈秒191700000000000000000Go 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 年以前的日期前請先測試。

所有知識文章