牛奶盒上寫著「週五前用完」,可週五不是一個天數。日期有自己的算術。日曆上的日期和時間上的某一刻,差在哪裡?
datetime 模組把日曆日期、時鐘時間和時間間隔分開。初學階段先掌握 date 和 timedelta。只有當資料確實表示不同地區共同觀察的某一瞬間時,才需要引入時區。 你還會區分日期與時刻、解析 ISO 文字,並避免把一個月當成 30 天。
建立一個日期
date(year, month, day) 會驗證參數,並回傳不可變的日期物件。isoformat() 生成可排序的 YYYY-MM-DD 形式。需要拆分年月日時,可以直接存取 year、month 和 day。
from datetime import date
start = date(2026, 1, 15)
print(start.isoformat())
print(start.year, start.month, start.day)一個日曆日期
加上 timedelta
timedelta 表示一段時長。把它加到日期上會回傳新日期,原物件不變。兩個日期相減會得到一個 timedelta,可以用 days 屬性讀取天數。
from datetime import date, timedelta
start = date(2026, 1, 30)
end = start + timedelta(days=3)
print(end.isoformat())
print((end - start).days)時長與日期差
格式化成讀者能看懂的形式
strftime 按格式模式生成字串。數字日期用 %Y、%m 和 %d。月份名和星期名依賴區域設定,輸出必須到處一致時優先使用數字格式。
from datetime import date
day = date(2026, 10, 27)
print(day.strftime("%Y/%m/%d"))
print(day.isoformat())穩定的數字格式
日期不是時刻
date 只儲存日曆上的一天,沒有時區。datetime 儲存時鐘讀數;只有帶時區的 datetime 才能表示不同地區共同觀察的某一瞬間。不要把無時區 datetime 和帶時區 datetime 相減;先判斷資料到底是日期還是時刻。
from datetime import date, datetime, timezone
day = date(2026, 10, 28)
moment = datetime(2026, 10, 28, 12, 0, tzinfo=timezone.utc)
print(day.isoformat())
print(moment.isoformat())
print(moment.tzinfo is not None)日曆日與帶時區的時刻
先解析 ISO 文字,再做運算
fromisoformat 接受 YYYY-MM-DD 形狀,拒絕含糊的日/月順序。不要從 28/10/2026 這樣的字串猜順序;向資料源確認格式並顯式解析。在邊界捕獲 ValueError,並報告壞值。
from datetime import date
for raw in ["2026-10-28", "28/10/2026"]:
try:
parsed = date.fromisoformat(raw)
print(parsed.year, parsed.month, parsed.day)
except ValueError:
print("not ISO:", raw)先驗證形狀,再使用日期
一個月不是 30 天
timedelta 計算的是固定天數,不是日曆月。1 月 31 日加 30 天會落到 3 月,而不是 2 月 28 日。如果規則是「一個日曆月」,要用顯式的月份計算或維護良好的日期庫,不要寫成 30 天。
from datetime import date, timedelta
start = date(2026, 1, 31)
print((start + timedelta(days=30)).isoformat())
print((start + timedelta(days=59)).isoformat())固定天數與日曆月
本課要點
- date(y, m, d) 建立一個經過驗證的日曆日期。
- timedelta(days=n) 表示一段時長。
- 日期加 timedelta 會回傳新的日期物件。
- 輸出不能依賴區域設定時,用數字形式的 strftime 模式。
- 運算前先選 date 或帶時區的 datetime;timedelta 表示固定時長。
常見錯誤
- 在儲存日期時使用含糊的日/月順序。
- 試圖原地修改日期;date 物件不可變。
- 還沒分清日期和時刻,就急著添加時區。
- 把無時區和帶時區的 datetime 相減,還期待有意義的結果。
建立 date(2026, 12, 31),加一天,並用 ISO 格式列印兩個日期。
動手試試
改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。
練習本課
12 道題,作答後立即看到解釋。