如何根据日期将带时区本地时间转UTC,适配夏令时(DST)?
问题:带时区的本地时间转UTC时GMT夏令时处理失效
我有多个带时区信息的本地时间点:
import datetime from zoneinfo import ZoneInfo as zi wmr = datetime.time(hour=12, tzinfo=zi("GMT")) ecb = datetime.time(hour=14, minute=15, tzinfo=zi("CET")) jpx = datetime.time(hour=14, tzinfo=zi("Japan"))
需要根据指定日期将这些时间转换为UTC时间,预期结果如下:
local2utc(datetime.datetime(2024,1,1), wmr) ---> "2024-01-01 12:00:00" local2utc(datetime.datetime(2024,6,1), wmr) ---> "2024-06-01 11:00:00" (夏令时生效) local2utc(datetime.datetime(2024,1,1), ecb) ---> "2024-01-01 13:15:00" local2utc(datetime.datetime(2024,6,1), ecb) ---> "2024-06-01 12:15:00" (夏令时生效) local2utc(datetime.datetime(2024,1,1), jpx) ---> "2024-01-01 05:00:00" local2utc(datetime.datetime(2024,6,1), jpx) ---> "2024-06-01 05:00:00" (日本无夏令时)
现有实现代码:
def local2utc(date, time): local_dt = datetime.datetime.combine(date,time) tm = local_dt.utctimetuple() return datetime.datetime(*tm[:7])
这段代码对日本标准时间和CET有效,但对GMT/WET无效——因为伦敦夏季会采用BST/WEST夏令时,现有逻辑没正确处理这个情况。
问题根源
datetime.time对象的tzinfo如果直接用zi("GMT"),代表的是固定偏移的GMT时区,不会自动切换夏令时。而伦敦实际使用的是Europe/London时区,这个时区会根据日期自动切换GMT(冬季)和BST(夏季)。
修正方案
方案1:直接修正时区标识符
把代表伦敦时间的zi("GMT")替换为zi("Europe/London"),同时优化转换逻辑:
import datetime from zoneinfo import ZoneInfo as zi # 替换GMT为Europe/London,支持夏令时自动切换 wmr = datetime.time(hour=12, tzinfo=zi("Europe/London")) ecb = datetime.time(hour=14, minute=15, tzinfo=zi("CET")) jpx = datetime.time(hour=14, tzinfo=zi("Japan")) def local2utc(date, time): # 合并日期与带时区的时间,生成带时区的datetime对象 local_dt = datetime.datetime.combine(date, time) # 转换为UTC时区 utc_dt = local_dt.astimezone(zi("UTC")) # 返回格式化后的UTC时间字符串 return utc_dt.strftime("%Y-%m-%d %H:%M:%S")
方案2:在函数内部兼容GMT输入
如果必须保留GMT作为输入时区标识符,可以在转换函数内部自动替换为Europe/London:
import datetime from zoneinfo import ZoneInfo as zi wmr = datetime.time(hour=12, tzinfo=zi("GMT")) ecb = datetime.time(hour=14, minute=15, tzinfo=zi("CET")) jpx = datetime.time(hour=14, tzinfo=zi("Japan")) def local2utc(date, time): # 检测并替换GMT时区为Europe/London tz = time.tzinfo if tz and tz.key == "GMT": tz = zi("Europe/London") time = time.replace(tzinfo=tz) local_dt = datetime.datetime.combine(date, time) utc_dt = local_dt.astimezone(zi("UTC")) return utc_dt.strftime("%Y-%m-%d %H:%M:%S")
验证结果
调用修正后的函数,可得到符合预期的结果:
- 冬季调用
local2utc(datetime.datetime(2024,1,1), wmr)返回"2024-01-01 12:00:00" - 夏季调用
local2utc(datetime.datetime(2024,6,1), wmr)返回"2024-06-01 11:00:00"
内容的提问来源于stack exchange,提问作者sds
相关产品推荐
相关产品推荐

