Python 日期與時間(Datetime)——時間格式化(strftime、strptime)
簡介
在日常開發中,日期與時間的呈現與解析是最常見的需求之一。無論是產生報表、寫入檔名、或是與外部系統交換資料,都必須把 datetime 物件轉成特定字串格式,或把字串重新轉回 datetime。Python 提供的 strftime(格式化)與 strptime(解析)正是為此而設計的兩個核心函式。掌握它們不僅能讓程式碼更易讀,也能避免因時區、字串不符而產生的錯誤。
本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,最後帶出實務應用,幫助 初學者到中階開發者 快速上手並寫出可靠的時間格式化程式碼。
核心概念
1. datetime.strftime – 把 datetime 物件格式化成字串
strftime 會根據提供的 格式字串(format string)輸出對應的日期時間文字。格式字串由一組「指令」組成,每個指令以 % 開頭,例如:
| 指令 | 說明 | 範例 |
|---|---|---|
%Y |
四位數年份 | 2025 |
%m |
兩位數月份(01‑12) | 07 |
%d |
兩位數日期(01‑31) | 09 |
%H |
24 小時制小時(00‑23) | 14 |
%M |
分鐘(00‑59) | 35 |
%S |
秒數(00‑59) | 07 |
%a |
簡寫星期(Mon) | Tue |
%A |
完整星期(Monday) | Tuesday |
%b |
簡寫月份(Jan) | Jul |
%B |
完整月份(January) | July |
%p |
AM/PM 標記(Locale 依賴) | PM |
小技巧:在 Jupyter Notebook 或 REPL 中,
datetime.datetime.now().strftime("%c")能直接顯示系統預設的完整日期時間字串,快速測試格式。
2. datetime.strptime – 把符合格式的字串解析回 datetime 物件
strptime 的使用方式與 strftime 相反:先給定字串,再給定相同的格式字串,Python 會依照格式把字串轉成 datetime。若字串與格式不符,會拋出 ValueError。
注意:
strptime只接受 完整 的日期時間資訊;如果格式中缺少某個欄位,會以預設值(如1900-01-01)填補。
程式碼範例
以下示範 5 個實用情境,皆以 datetime 標準庫為例,程式碼使用 python 語法標記。
範例 1:基本的日期時間格式化
from datetime import datetime
now = datetime.now()
# 2025-07-09 14:35:07
formatted = now.strftime("%Y-%m-%d %H:%M:%S")
print(formatted)
說明:
%Y-%m-%d %H:%M:%S為常見的「ISO‑like」格式,適合寫入資料庫或日誌檔。
範例 2:自訂檔名中的時間戳記
from datetime import datetime
log_file = f"log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
print(log_file) # 例如:log_20250709_143507.txt
說明:使用
strftime產生不含分隔符的字串,讓檔名在檔案系統中保持排序性。
範例 3:解析使用者輸入的日期字串
from datetime import datetime
user_input = "2025/07/09 14:35"
# 注意:格式必須與字串完全對應
dt = datetime.strptime(user_input, "%Y/%m/%d %H:%M")
print(dt) # 2025-07-09 14:35:00
說明:
strptime會自動把缺少的秒數補成0,但若字串缺少分鐘或小時,會拋出錯誤。
範例 4:處理不同語系的月份名稱
import locale
from datetime import datetime
# 設定為台灣中文
locale.setlocale(locale.LC_TIME, "zh_TW.UTF-8")
s = "2025年七月09日"
dt = datetime.strptime(s, "%Y年%B%d日")
print(dt) # 2025-07-09 00:00:00
說明:
%B代表完整月份名稱,必須配合正確的 locale 才能正確解析。
範例 5:將 UTC 時間字串轉成本地時間
from datetime import datetime, timezone, timedelta
utc_str = "2025-07-09T06:35:07Z"
utc_dt = datetime.strptime(utc_str, "%Y-%m-%dT%H:%M:%SZ")
utc_dt = utc_dt.replace(tzinfo=timezone.utc)
# 以台北時區 (+08:00) 轉換
taipei = timezone(timedelta(hours=8))
local_dt = utc_dt.astimezone(taipei)
print(local_dt.strftime("%Y-%m-%d %H:%M:%S %Z"))
# 2025-07-09 14:35:07 UTC+08:00
說明:先用
strptime解析成「沒有時區」的datetime,再手動加上timezone.utc,最後使用astimezone轉換至本地時區。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 最佳實踐 |
|---|---|---|
| 格式不匹配 | strptime 的格式字串必須完全對應輸入字串,少一個 % 或空格都會拋 ValueError。 |
在接受使用者輸入前,先 正規表達式 檢查或使用 try/except 捕捉錯誤。 |
| 時區遺失 | datetime 物件若未設定 tzinfo,會被視為「本地時間」或「天真時間」,在跨時區運算時容易出錯。 |
儘量使用 aware datetime(帶時區)或 pytz/zoneinfo 處理時區。 |
| 平台差異的 locale | 不同作業系統的 locale 名稱可能不同,導致 %b、%B 解析失敗。 |
在程式啟動時 檢查 locale 是否成功設定,必要時提供 fallback。 |
%y 與 1900 年的衝突 |
%y 只接受兩位數年份,Python 會根據 1969‑2068 的範圍自動推算。 |
若需要明確的世紀資訊,使用 %Y(四位數),避免歧義。 |
| 字串長度與空白 | strftime 會把空白字元原樣輸出,解析時若字串多餘空白會失敗。 |
使用 .strip() 清理輸入,或在格式字串中明確加入空白。 |
最佳實踐小結:
- 統一使用 ISO 8601(
%Y-%m-%dT%H:%M:%S%z)作為跨系統的交換格式。 - 建立常用格式常數,如
RFC_2822 = "%a, %d %b %Y %H:%M:%S %z",減少硬編碼。 - 使用
try/except捕捉ValueError,並回傳友善的錯誤訊息給使用者。 - 在需要時明確指定時區,避免「天真」時間造成的錯誤。
實際應用場景
- 日誌檔(Log)標記
- 產生
log_20250709_143507.txt,讓檔案自動依時間排序。
- 產生
- 資料庫時間欄位
- 使用
strftime("%Y-%m-%d %H:%M:%S")產生 MySQLDATETIME格式字串。
- 使用
- API 日期參數
- 多數 RESTful API 規範要求 ISO 8601,故需
datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")。
- 多數 RESTful API 規範要求 ISO 8601,故需
- 報表產出
- 把
datetime轉成「民國年」或「中文月份」供 PDF、Excel 使用,需配合locale與自訂格式。
- 把
- 排程系統
- 讀取使用者輸入的「2025/07/09 14:35」字串,透過
strptime轉成datetime,再交給APScheduler或cron排程。
- 讀取使用者輸入的「2025/07/09 14:35」字串,透過
總結
strftime與strptime是 Python 處理 日期時間字串 的兩把關鍵工具。- 了解 格式指令、時區概念、以及 locale 影響,才能寫出正確且跨平台的程式。
- 常見的陷阱包括格式不匹配、時區遺失與 locale 差異,透過 例外處理、統一使用 ISO 8601 與 明確設定時區 可大幅降低錯誤風險。
- 在日誌、資料庫、API、報表與排程等實務場景中,適時使用
strftime/strptime能提升程式可讀性與維護性。
掌握了這些概念與技巧後,你就能自信地在任何 Python 專案中處理時間格式化,讓日期時間不再是開發的絆腳石,而是提升系統可靠性的利器。祝你寫程式愉快!