本文 AI 產出,尚未審核
Python 日期與時間(Datetime)——UNIX Timestamp 完全指南
簡介
在現代程式開發中,時間的表示與處理是不可或缺的需求。無論是日誌紀錄、資料庫儲存、API 互通,或是排程系統,都必須以一致且精確的方式描述「什麼時候」發生了什麼事。
最常見且跨平台的時間表示方式之一,就是 UNIX Timestamp(亦稱 Epoch 時間),它以「自 1970 年 1 月 1 日 00:00:00(UTC)以來的秒數」作為基礎,簡潔、易於比較與傳輸。
對於 Python 開發者而言,熟練掌握 datetime 模組與 UNIX Timestamp 之間的相互轉換,能讓你在處理時區、格式化、以及跨語言的時間交換時更加得心應手。本篇文章將從概念說明、實作範例、常見陷阱、最佳實踐,一路帶你深入了解並活用 UNIX Timestamp。
核心概念
1. 什麼是 UNIX Timestamp?
- 定義:自 1970‑01‑01 00:00:00 UTC 起算的「秒」數(或毫秒、微秒)。
- 特性:
- 單一整數值,方便儲存與比較。
- 與時區無關,所有系統皆以 UTC 為基準。
- 常見於資料庫(如 MySQL 的
TIMESTAMP)、JSON API、日志檔等。
2. Python datetime 與 timestamp() / fromtimestamp()
Python 的 datetime 物件提供兩個重要方法:
| 方法 | 功能 | 範例 |
|---|---|---|
datetime.timestamp() |
將 aware(具時區)或 naive(無時區)datetime 轉為 UNIX Timestamp(float) |
dt.timestamp() |
datetime.fromtimestamp(ts, tz=None) |
依據 Timestamp 建立 datetime,tz 為可選的時區資訊 |
datetime.fromtimestamp(1697040000, tz=timezone.utc) |
注意:若
datetime為 naive,timestamp()會以本機(系統)時區為基準,可能導致不預期的結果;建議在進行轉換前先將其 本地化(localize)為 aware 物件。
3. 時區(Timezone)概念
- UTC(Coordinated Universal Time)是唯一的全球標準時間。
- 本地時區(如
Asia/Taipei)是相對於 UTC 的偏移量。 - 在 Python 中,可使用
datetime.timezone(固定偏移)或第三方套件pytz、zoneinfo(Python 3.9+)處理 IANA 時區資料。
程式碼範例
以下示範 5 個實用範例,涵蓋從 Timestamp 取得 datetime、時區轉換、毫秒與微秒的處理、以及常見的 JSON 序列化需求。
1️⃣ 取得當前 UNIX Timestamp(秒)
from datetime import datetime, timezone
# 取得 UTC 時間的 datetime 物件
now_utc = datetime.now(timezone.utc)
# 直接轉為 Timestamp(float,單位:秒)
timestamp_sec = now_utc.timestamp()
print(f"Current UNIX timestamp (seconds): {timestamp_sec}")
重點:使用
timezone.utc產生 aware datetime,避免本機時區影響。
2️⃣ 從 Timestamp 轉回本地時間(含時區資訊)
from datetime import datetime, timezone, timedelta
# 假設已知的 Timestamp(秒)
ts = 1697040000 # 2023-10-11 00:00:00 UTC
# 轉為 UTC datetime
dt_utc = datetime.fromtimestamp(ts, tz=timezone.utc)
# 轉為台北時區 (UTC+8)
taipei_tz = timezone(timedelta(hours=8))
dt_taipei = dt_utc.astimezone(taipei_tz)
print(f"UTC time : {dt_utc.isoformat()}")
print(f"Taipei time: {dt_taipei.isoformat()}")
3️⃣ 處理毫秒或微秒的 Timestamp
from datetime import datetime, timezone
# 以毫秒為單位的 Timestamp(常見於 JavaScript)
ms_ts = 1697040000123
# 先除以 1000 取得秒數(float),再轉換
dt = datetime.fromtimestamp(ms_ts / 1000, tz=timezone.utc)
print(f"Timestamp (ms) -> datetime: {dt.isoformat()}")
# 若要取得微秒(Python float 支援),直接使用除以 1_000_000
us_ts = 1697040000123456
dt_us = datetime.fromtimestamp(us_ts / 1_000_000, tz=timezone.utc)
print(f"Timestamp (µs) -> datetime: {dt_us.isoformat()}")
4️⃣ 使用 zoneinfo(Python 3.9+)管理 IANA 時區
from datetime import datetime
from zoneinfo import ZoneInfo # Python 3.9 之後內建
# 取得台北時區的現在時間
now_taipei = datetime.now(ZoneInfo("Asia/Taipei"))
print(f"Now in Taipei: {now_taipei.isoformat()}")
# 轉為 UTC Timestamp
ts = now_taipei.timestamp()
print(f"Corresponding UTC timestamp: {ts}")
提醒:
zoneinfo直接讀取系統的時區資料庫,無需額外安裝套件。
5️⃣ JSON 序列化與反序列化(Timestamp 為數字)
import json
from datetime import datetime, timezone
def datetime_to_timestamp(dt: datetime) -> float:
"""將 aware datetime 轉成 UNIX timestamp(秒)"""
return dt.timestamp()
def timestamp_to_datetime(ts: float) -> datetime:
"""將 timestamp 轉回 UTC aware datetime"""
return datetime.fromtimestamp(ts, tz=timezone.utc)
# 範例資料
payload = {
"event": "user_login",
"time": datetime_to_timestamp(datetime.now(timezone.utc))
}
# 序列化為 JSON(timestamp 以數字形式保存)
json_str = json.dumps(payload)
print(f"JSON payload: {json_str}")
# 讀回時轉回 datetime
data = json.loads(json_str)
event_time = timestamp_to_datetime(data["time"])
print(f"Event time (UTC): {event_time.isoformat()}")
常見陷阱與最佳實踐
| 陷阱 | 可能的結果 | 解決方案 |
|---|---|---|
使用 naive datetime 直接呼叫 .timestamp() |
依本機時區產生錯誤的秒數 | 先將 datetime 本地化(replace(tzinfo=timezone.utc) 或使用 pytz/zoneinfo) |
| 忘記考慮閏秒 | 某些極端情況下時間差錯誤 1 秒 | 大多數應用可忽略;若需精確時間同步,使用 NTP/datetime 的 fold 參數 |
| 毫秒/微秒混用 | 產生非預期的日期(少了 3~6 位數) | 統一單位:在程式內部固定使用秒(float),或明確除以 1000/1_000_000 |
| 時區資料庫過期 | 時區偏移錯誤(如夏令時間變更) | 定期更新系統時區資料,或使用 tzdata 套件(pip install tzdata) |
| JSON 序列化時遺失時區資訊 | 只留下本地時間字串,無法還原 | 使用 timestamp(數字)或 ISO 8601 帶時區的字串(datetime.isoformat()) |
推薦的最佳實踐
- 全程使用 aware datetime:在產生、傳遞、儲存時間時,都保留時區資訊。
- 統一使用 UTC:除非前端或使用者介面需要本地時間,否則在後端以 UTC 為唯一基準。
- 避免硬編碼時區偏移:使用
zoneinfo/pytz取得 IANA 時區,確保夏令時間自動調整。 - 在序列化時選擇數字 Timestamp:JSON、MessagePack、Protobuf 等二進位協議皆支援。
- 單元測試時間相關功能:使用
freezegun或datetime.mock固定時間,驗證轉換邏輯。
實際應用場景
| 場景 | 為何需要 UNIX Timestamp | 示例程式碼摘要 |
|---|---|---|
| 日誌系統 | 便於跨機器、跨語言的時間排序 | log_time = datetime.now(timezone.utc).timestamp() |
| 資料庫儲存 | BIGINT 可直接存儲秒數,索引效能佳 |
INSERT INTO events (ts) VALUES (%s) |
| API 互通(前端 JavaScript) | 前端使用 Date.now()(毫秒),後端直接接受秒/毫秒 |
前端 fetch('/api', {body: JSON.stringify({ts: Date.now()})}) |
| 排程系統(Celery、Airflow) | 以 Timestamp 計算延遲、重試時間 | eta = datetime.fromtimestamp(ts, tz=timezone.utc) |
| 金融交易 | 高頻交易需毫秒甚至微秒級別的時間戳 | trade_ts = time.time()(返回 float 秒) |
總結
- UNIX Timestamp 是跨平台、跨語言的時間基礎,適合儲存、比較與傳輸。
- 在 Python 中,
datetime.timestamp()與datetime.fromtimestamp()是核心 API,配合 aware datetime 與 zoneinfo(或pytz)即可安全處理時區。 - 常見陷阱多與 naive datetime、單位不一致、時區資料過期 有關,遵守 全程使用 UTC、保留時區資訊 的原則,可大幅降低錯誤。
- 透過本文的 5 個範例,你已能從取得當前 Timestamp、進行毫秒/微秒處理、到 JSON 序列化完整掌握實務需求。
掌握了 UNIX Timestamp 的使用,你的 Python 應用將在時間管理上更加精準、可靠且易於維護。祝你在未來的專案中玩轉時間,寫出更穩定的程式碼!