Unix Timestamp 是什麼?一次搞懂時間戳記的原理與應用

當你在資料庫裡看到 1711699200 這串數字,或是在 API 回應中見到 "created_at": 1711699200,你看到的就是 Unix timestamp(又稱 Unix 時間戳記)。它是電腦世界中最通用的時間表示法,幾乎所有程式語言、作業系統、資料庫都支援它。本文將從頭說清楚 Unix timestamp 是什麼、為什麼要用它,以及你在開發中會遇到的各種場景。

1. Unix Timestamp 的定義

Unix timestamp 是一個整數,代表從 Unix Epoch(紀元) ——即 1970 年 1 月 1 日 00:00:00 UTC——到某個特定時刻之間所經過的秒數

例如:

人類可讀時間(UTC)Unix Timestamp
1970-01-01 00:00:000
2000-01-01 00:00:00946684800
2024-03-29 00:00:001711670400
2038-01-19 03:14:072147483647(32 位元上限)

需要留意的是:Unix timestamp 以 UTC(協調世界時) 為基準,本身不含時區資訊。同一個 timestamp 在台北(UTC+8)、倫敦(UTC+0)、紐約(UTC-5)代表的是同一個絕對時刻,只是顯示出來的本地時間不同。

2. 為什麼從 1970 年開始?

這個「0 點」並沒有什麼天文或曆法上的特別意義,純粹是歷史因素。Unix 作業系統大約在 1969 到 1970 年間開發,設計者需要選一個「時間原點」,就選了 1970 年 1 月 1 日 00:00:00 UTC。此後所有與 Unix 相容的系統都沿用了這個慣例,最終成為事實標準(de facto standard)。

你也許見過其他時間原點:Windows NT Epoch 是 1601 年 1 月 1 日,NTP 時間是 1900 年 1 月 1 日,Apple Core Data 是 2001 年 1 月 1 日。彼此之間換算時需要特別注意。

3. Unix Timestamp 的核心優勢

Unix timestamp 之所以在工程領域廣泛使用,原因在於幾個無可取代的特性:

  • 時區無關:timestamp 是絕對秒數,不依附任何時區。跨國系統只要傳遞 timestamp,接收端再根據本地時區轉換顯示,不會產生「我說 8 點你說哪個時區的 8 點」的歧義。
  • 純整數、易比較:要判斷事件 A 是否在事件 B 之前,只需比較兩個整數大小,不需要解析日期字串,更不需要考慮閏年、月份天數等曆法規則。
  • 易於儲存與傳輸:一個 64 位元整數,幾乎沒有空間開銷。資料庫欄位、JSON 欄位、HTTP Header 都能輕鬆放進去。
  • 計算簡單:「這篇文章是 3 天前發布的嗎?」只需拿現在的 timestamp 減去文章的 timestamp,再除以 86400(一天的秒數)即可判斷,無需解析日期物件。

4. 毫秒級 Timestamp

隨著應用對精度要求提高,許多現代系統採用毫秒(millisecond)timestamp——即 Unix Epoch 以來的毫秒數,是秒數 × 1000。例如 JavaScript 的 Date.now() 返回的就是毫秒 timestamp。

這也是常見的混淆來源。1711670400(10 位數)是秒,1711670400000(13 位數)是毫秒;把毫秒 timestamp 當秒數處理,會得到公元 5 萬年左右的輸出,反過來也一樣荒謬。判斷方式:10 位數 = 秒,13 位數 = 毫秒(在 2001 至 2286 年間適用)。

5. 各語言取得 Unix Timestamp 的方式

# PHP
time()                          // 秒
round(microtime(true) * 1000)  // 毫秒

# Python
import time
int(time.time())               // 秒
int(time.time() * 1000)        // 毫秒

# JavaScript
Math.floor(Date.now() / 1000)  // 秒
Date.now()                     // 毫秒

# Java
System.currentTimeMillis() / 1000  // 秒
System.currentTimeMillis()         // 毫秒

# Go
time.Now().Unix()              // 秒
time.Now().UnixMilli()         // 毫秒

# Bash / Shell
date +%s                       // 秒

6. 如何把 Unix Timestamp 轉換成人類可讀格式?

各語言都提供了標準函式,下面以 PHP 為例:

// timestamp → 日期字串
$ts = 1711670400;
echo date('Y-m-d H:i:s', $ts);        // 2024-03-29 00:00:00(本機時區)
echo gmdate('Y-m-d H:i:s', $ts);      // 2024-03-29 00:00:00(強制 UTC)

// 日期字串 → timestamp
$ts = strtotime('2024-03-29 00:00:00 UTC'); // 1711670400

若不想手動撰寫程式,也可以直接使用本站的 Unix 時間戳轉換工具,在瀏覽器中直接輸入 timestamp 或日期互轉,非常方便。

7. 2038 年問題(Y2K38)

當 Unix timestamp 以 32 位元有號整數(signed int32) 儲存時,最大值是 2147483647,對應到 2038 年 1 月 19 日 03:14:07 UTC。超過這個時刻,32 位元整數溢位後會變成負數,導致系統誤判時間回到 1901 年——這就是俗稱的「2038 年問題(Y2038 problem)」,類似當年的千禧蟲問題(Y2K)。

現代作業系統(Linux kernel 5.6+)與大多數 64 位元程式語言已將 timestamp 改用 64 位元整數,可以表示到約西元 2920 億年之後,完全不是我們這個時代需要擔心的數字。但若你維護的系統仍使用舊版 32 位元 C 函式庫或資料庫的 INT(11) 欄位儲存 timestamp,就需要評估升級計畫。

開發注意
資料庫的 INT UNSIGNED 可以存到 2106 年,BIGINT 則幾乎沒有上限。建議新系統一律使用 BIGINT 或資料庫原生的 DATETIME/TIMESTAMP 型別(通常內部已採用 64 位元)。

8. 常見應用場景

Unix timestamp 幾乎無所不在,以下是你最常遇到的幾個場景:

  • 資料庫紀錄時間created_atupdated_atdeleted_at 欄位經常以 timestamp 存放,節省空間且查詢效率高。
  • API 回應:REST API 傳遞時間時,timestamp 比 ISO 8601 字串(2024-03-29T00:00:00Z)更容易做數值比較與排序,許多 API 兩者都提供。
  • JWT 與認證 token:JSON Web Token 的 exp(過期時間)與 iat(簽發時間)就是 Unix timestamp,方便各語言驗證而不需解析時區。
  • 快取與 CDN:HTTP Header 中的 If-Modified-SinceLast-Modified 雖然使用 RFC 1123 格式字串,底層邏輯仍是秒數比較。
  • 日誌系統:大量日誌以 timestamp 記錄事件,方便依時間範圍過濾(例如「取出最近 10 分鐘的錯誤」只需 WHERE ts >= NOW() - 600)。
  • 前端相對時間顯示:「3 分鐘前」、「昨天」這類相對時間,通常由前端拿 Date.now() 減去後端傳來的 timestamp 計算得出。

結語

Unix timestamp 看起來只是一串數字,卻是整個現代軟體生態賴以運作的時間語言。理解它的原理——從 1970 年起算的秒數、無時區偏移、純整數操作——能幫助你在開發中讀懂 API 文件、除錯時間相關問題,以及設計出更健壯的系統架構。下次再看到 10 位數字,你就知道那是秒,13 位數字是毫秒,而且兩者背後指的都是那個安靜等待著的 Unix Epoch:1970 年 1 月 1 日的零時零分零秒。