UNIX 時間戳記在程式設計的應用:API 設計、資料庫儲存與跨語言時間處理完整指南

你有沒有看過 API 回傳這樣的欄位:"created_at": 1745913600?這個看似神秘的整數,其實是 UNIX 時間戳記(Unix Timestamp)——一種在程式世界中傳遞時間的標準格式。理解它為什麼存在、如何正確使用,是每位工程師都需要掌握的基礎技能。

一、什麼是 UNIX 時間戳記?為什麼程式要用它?

UNIX 時間戳記是指「從 1970 年 1 月 1 日 00:00:00 UTC(稱為 Unix Epoch)到某個時刻,所經過的秒數」。例如,1745913600 代表 2026 年 4 月 29 日 00:00:00 UTC。

程式選擇用這個整數而非人類可讀的字串,主要有三個理由:

  • 時區中立1745913600 在全球所有系統上代表同一個絕對時刻,不存在「台北時間」還是「紐約時間」的歧義
  • 易於計算:要計算兩個時間點相差幾秒、排序事件發生順序,直接比較整數即可
  • 格式統一:不同語言、不同資料庫系統都能毫無歧義地解讀同一個整數
立即轉換時間戳記:使用 Unix 時間戳記轉換工具,可以在時間戳記與人類可讀時間之間快速互換,支援秒級與毫秒級格式,並顯示各時區對應時間。

二、秒 vs 毫秒:最常見的混淆陷阱

UNIX 時間戳記本身定義為「秒數」,但現代系統(特別是 JavaScript 和許多 API)常用毫秒(milliseconds),在數字後面多加了三位數:

格式範例值說明
秒(seconds) 1745913600 10 位數,UNIX 標準,C/Python/PHP 常用
毫秒(milliseconds) 1745913600000 13 位數,JavaScript Date.now() 回傳此格式
微秒(microseconds) 1745913600000000 16 位數,部分資料庫與高精度系統使用

識別方式:看數字的位數。10 位數 → 秒;13 位數 → 毫秒。如果你收到一個 13 位的時間戳記,卻用秒的方式解讀,換算出來的時間會是 56000 年後——這是初學者最常踩的坑之一。

三、API 設計:時間欄位的最佳實踐

設計 REST API 時,時間欄位的格式選擇影響深遠。以下是主流方案的比較:

格式範例優點缺點
UNIX 時間戳記(秒) 1745913600 計算快、無時區歧義、資料量小 人類無法直接閱讀
ISO 8601 字串 2026-04-29T00:00:00Z 人類可讀、含時區資訊(Z 表示 UTC) 字串解析有語言差異
RFC 2822 字串 Wed, 29 Apr 2026 00:00:00 +0000 Email/HTTP 標準格式 較冗長,不適合 JSON API

業界建議

  • 內部系統間的 API:優先使用 UNIX 時間戳記(整數),避免時區解讀錯誤
  • 對外公開 API:使用 ISO 8601 格式(2026-04-29T00:00:00Z),方便開發者直接閱讀
  • 回傳兩者:部分 API 同時回傳 "created_at": "2026-04-29T00:00:00Z""created_at_unix": 1745913600,兼顧可讀性與計算便利
  • 統一使用 UTC:無論選哪種格式,儲存與傳遞都應使用 UTC,在前端才根據使用者時區顯示
API 回傳了帶時區的時間字串?使用 世界時鐘工具,可以快速查詢各時區的當前時間,幫助你驗證時區換算是否正確。

四、資料庫儲存:INT、DATETIME 還是 TIMESTAMP?

在資料庫中儲存時間,主要有三種欄位類型選擇:

類型範例值適用情境注意事項
INT UNSIGNED 1745913600 高效能查詢、跨資料庫移植 2038 年問題(32 位元);使用 BIGINT 避免
DATETIME 2026-04-29 00:00:00 需要人類可讀、不依賴時區設定 MySQL DATETIME 不儲存時區資訊,需應用層統一
TIMESTAMP 2026-04-29 00:00:00 MySQL 自動轉換時區,適合多時區系統 範圍限制到 2038 年;MySQL 8 已部分改善

2038 年問題是什麼?

UNIX 時間戳記最初設計為 32 位元有號整數,最大值為 2147483647,對應 2038 年 1 月 19 日 03:14:07 UTC。超過這個時間,32 位元整數會溢位歸零。解決方法是改用 64 位元整數(BIGINT)儲存,可以安全使用到西元 292 億年後。

五、跨語言時間戳記操作速查

JavaScript

// 取得當前時間戳記(毫秒)
const ms = Date.now();               // 1745913600000

// 轉為秒
const sec = Math.floor(Date.now() / 1000);  // 1745913600

// 時間戳記轉 Date 物件
const date = new Date(1745913600 * 1000);

// Date 物件轉時間戳記(秒)
const ts = Math.floor(date.getTime() / 1000);

Python

import time, datetime, timezone

# 取得當前時間戳記(秒,浮點數)
ts = time.time()               # 1745913600.123

# 轉為 datetime(UTC)
dt = datetime.datetime.fromtimestamp(1745913600, tz=timezone.utc)

# datetime 轉時間戳記
ts = dt.timestamp()            # 1745913600.0

PHP

// 取得當前時間戳記(秒)
$ts = time();                  // 1745913600

// 格式化輸出
echo date('Y-m-d H:i:s', $ts);  // 2026-04-29 00:00:00

// 字串轉時間戳記
$ts = strtotime('2026-04-29 00:00:00 UTC');  // 1745913600

Go

// 取得當前時間戳記(秒)
ts := time.Now().Unix()        // 1745913600

// 取得毫秒
ms := time.Now().UnixMilli()   // 1745913600000

// 時間戳記轉 Time
t := time.Unix(1745913600, 0).UTC()

六、JSON API 中的時間欄位

當 API 回傳 JSON 並包含時間欄位時,常見的結構如下:

{
  "id": "post_123",
  "title": "Hello World",
  "created_at": "2026-04-29T00:00:00Z",
  "updated_at": 1745913600
}

這份 JSON 混合了兩種時間格式——ISO 8601 字串與 UNIX 時間戳記整數。在實際專案中,同一 API 應統一格式,避免消費端需要同時處理兩種解析邏輯。

驗證 API 回傳的 JSON 結構?使用 JSON 格式化工具,貼入 API 回傳的原始 JSON,即可美化排版、驗證語法,快速找出時間欄位的格式與結構問題。

七、常見錯誤整理

錯誤情境症狀解決方式
毫秒當秒處理 時間顯示為西元 56000 年 除以 1000 或確認欄位單位
忘記時區,本地時間存入 UTC 欄位 時間差 8 小時(台灣 UTC+8) 統一在 UTC 儲存,顯示時轉換
32 位元整數儲存 2038 年後溢位歸零 使用 BIGINT 或 64 位元整數
日光節約時間(DST)未處理 部分國家時間差一小時 使用時區資料庫(如 IANA tzdata)換算
字串時間未指定時區 不同伺服器解讀不一致 ISO 8601 結尾加 Z+08:00

總結

UNIX 時間戳記的設計邏輯很簡單:用一個絕對的整數代表時間,讓所有系統有共同語言。掌握它,能讓你的 API 設計更穩健、資料庫欄位更合理,也能在除錯時快速識別時區錯誤。

  • 時間戳記是「從 1970-01-01 00:00:00 UTC 起的秒數」,與時區無關
  • 10 位數 = 秒;13 位數 = 毫秒,混淆是最常見的 bug
  • API 設計:內部用整數,對外用 ISO 8601,統一使用 UTC
  • 資料庫:用 BIGINT 儲存時間戳記,避免 2038 年問題
  • 所有語言都有標準函式庫處理時間戳記轉換,不需要手動計算