时区问题 - 所有时区都是地方时区?

3 投票
1 回答
1193 浏览
提问于 2025-04-18 16:50

我在使用Python处理时区时遇到了一些麻烦,还有一个有趣的例子...

我用的是Python 2.7.2

import time
import datetime
import pytz
utc = pytz.utc
est = pytz.timezone('US/Eastern')
mst = pytz.timezone('US/Mountain')
print 'UTC time',time.mktime(datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=utc).timetuple())/3600
print 'EST time',time.mktime(datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=est).timetuple())/3600
print 'MST time',time.mktime(datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=mst).timetuple())/3600

我原本以为对于这三个例子(UTC、EST、MST),我应该得到0.0、5.0和7.0的结果,但实际上我在这三种情况下都得到了5.0(因为我的电脑是设置在东部标准时间EST)。

另外,

time.mktime(time.gmtime(0))

返回的结果是18000.0(5小时)——所以,明确请求gmtime来处理一个元组,然后转换为纪元时间(epoch)时,结果是5小时。我的Python版本有time.time()和time.gmtime(),但没有time.timegm()这个函数。

那么,如果我从客户那里收到的是MST(山地标准时间)的数据,想要生成一个UTC的纪元时间,我是不是只能假装这些时间戳是EST,然后加上五个小时呢?

这是不是因为strptime在处理时区信息时把它丢掉了?

1 个回答

3

timetuple()(还有其他基于struct-tm的函数)会忽略时区信息,也就是说,时间元组这种数据结构根本没有时区的字段。它的设计目的是把一个日期时间拆分成可以显示的各个部分,所以它其实并不适合用来进行时间计算。尽量保持你的时间值使用datetime格式。

>>> datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=utc)
datetime.datetime(1970, 1, 1, 0, 0, tzinfo=<UTC>)
>>> datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=utc).timetuple()
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)

另外,你不应该直接把tzinfo放进datetime构造函数里,因为这样不一定能得到正确的结果,具体可以参考这个回答:dateutil和pytz给出的结果不同。应该使用localize(),这样可以让pytz根据相关的时区规则来处理数据。

下面的代码可以把时间从山地标准时间(MST)转换为东部标准时间(EST):

>>> now = mst.localize(datetime.datetime(1970, 01, 01, 0, 0, 0))
>>> now
datetime.datetime(1970, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Mountain' MST-1 day, 17:00:00 STD>)
>>> now.astimezone(est)
datetime.datetime(1970, 1, 1, 2, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)

我不确定这个方法是否能处理所有特殊情况。例如,在夏令时转换的时候,常常会出现一些奇怪的情况。如果你遇到问题,可以开始寻找一些第三方的时间库来帮助解决。

撰写回答