为什么此代码依赖于我的本地计算机时区?

时间:2016-10-16 13:24:15

标签: python timezone python-dateutil

为什么这段代码:

def parse_date(datetime_string, tz_code):
    tz = timezone(tz_code)
    datetime_obj = parser.parse(datetime_string)
    datetime_obj_localized = datetime_obj.replace(tzinfo=tz)
    return time.mktime(datetime_obj_localized.timetuple())


def test_parse_date(self):
   self.assertEquals(1482951600, parse_date('2016-12-28 14:00', 'US/Eastern')

根据运行它的机器的时区返回不同的值?

根据我的理解,解析器返回没有时区的日期时间,然后分配tz,而不更改任何其他内容,最后将其转换为时间戳。我的本地tz不应该在任何地方使用。

1 个答案:

答案 0 :(得分:2)

dateutil.parser会附加一个时区,当且仅当它找到一个时区时,可能依赖于您的本地计算机时区设置,因为如果它检测到缩写的时区如“EST” “这是您当地时区的缩写列表,它将假设您的意思是。

那就是说,这不是这种情况下发生的事情。即使parser附加了时区,datetime.replace也会批量替换时区,而非转换。我不认为您的问题中有足够的信息可以完全诊断此问题,但如果timezone()pytz.timezone(),则至少有一个问题是pytz个时区不能使用datetime附加到replace个对象。您需要使用datetime_obj = pytz.timezone(tz_code).localize(datetime_obj)

请注意,localize方法假定您有一个时区初始对象,因此如果datetutil的解析器返回时区感知datetime,它将引发错误,因此您应该将ignoretz=True传递给解析器以防止这种情况。

尽管如此,即使你这样做,真正的问题在于你使用time.mktime。请参阅this answer,这是完全相同的问题。总结一下这个答案,最好的办法是使用calendar.timegm代替mktime,并在调用之前转换为UTC。结合我的建议,这里是您的代码的更新版本:

import calendar
from dateutil.tz import tzutc

def parse_date(datetime_string, tz_code):
    tz = timezone(tz_code)
    datetime_obj = parser.parse(datetime_string, ignoretz=True)
    datetime_obj_localized = tz.localize(datetime_obj)

    datetime_obj_utc = datetime_obj_localized.astimezone(tzutc())
    return calendar.timegm(datetime_obj_utc.timetuple())