
zoneinfo: เก็บเวลาแบบ DST-safe โดยไม่เดาออฟเซ็ตเอง
น้องกายEngineering
เคยบวกชั่วโมงในโซนที่มี DST แล้วได้เวลาติดผนังผิดไหม ผมเคย จนเลิกเดาออฟเซ็ตเอง
ตามเอกสาร zoneinfo คลาส ZoneInfo อ่านฐานข้อมูล IANA เช่น America/New_York ส่วนเอกสาร datetime อธิบายว่าแอตทริบิวต์ fold ใช้แยกเวลาที่ซ้ำกันตอนนาฬิกาถอยหลัง
กติกาที่ผมใช้
- เก็บช่วงเวลาสำคัญเป็น UTC แล้วค่อย
astimezoneไปโซนท้องถิ่นตอนแสดงผล - อย่าบวก
timedeltaแล้วคาดหวังว่านาฬิกาติดผนังจะข้ามช่องว่าง DST ให้เองเสมอ - ตอนนาฬิกาถอยหลัง ใช้
fold=0/fold=1ให้ชัดว่าหมายถึงออฟเซ็ตไหน
from datetime import datetime
from zoneinfo import ZoneInfo
ny = ZoneInfo("America/New_York")
utc = ZoneInfo("UTC")
# Spring-forward 2026-03-08: 02:00 local is skipped.
local_before = datetime(2026, 3, 8, 6, 30, tzinfo=utc).astimezone(ny)
local_after = datetime(2026, 3, 8, 7, 30, tzinfo=utc).astimezone(ny)
assert local_before.hour == 1 and local_before.minute == 30
assert local_after.hour == 3 and local_after.minute == 30
assert local_before.utcoffset() != local_after.utcoffset()
# Fall-back 2026-11-01: 01:30 occurs twice; fold picks which offset.
first = datetime(2026, 11, 1, 1, 30, tzinfo=ny, fold=0)
second = datetime(2026, 11, 1, 1, 30, tzinfo=ny, fold=1)
assert first.utcoffset() != second.utcoffset()
assert (second.astimezone(utc) - first.astimezone(utc)).total_seconds() == 3600
print("ok")
Recap
- ใช้
ZoneInfo("Area/City")จาก IANA ไม่ฮาร์ดโค้ด+07แบบตายตัวถ้าโซนมี DST - เก็บแกนเวลาเป็น UTC แล้วแปลงตอนแสดง
- ใช้
foldเมื่อเวลาติดผนังเกิดซ้ำตอนนาฬิกาถอย - เขียนเทสต์ข้ามวันเปลี่ยนฤดูในโซนที่ทีมคุณสนใจจริง