为什么这段代码依赖于我的本地机器时区?
Why is this code dependant on my local machine timezone?
为什么这个代码:
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')
returns 一个不同的值取决于运行所在机器的时区?
在我的理解中,解析器 returns 一个没有时区的日期时间,然后它分配一个 tz,不改变任何其他东西,最后它被转换成一个时间戳。我本地的tz 哪里都用不了。
dateutil.parser
将附加一个时区当且仅当它找到一个时区,这 可能 取决于您本地机器的时区设置,因为如果它检测到一个缩写像 "EST" 这样的时区在您当地时区的缩写列表中,它会假设这就是您的意思。
也就是说,这不是本例中发生的情况。即使 parser
附加了时区,datetime.replace
也会对时区进行批量替换,而不是转换。我认为您的问题中没有足够的信息来完全诊断此问题,但如果 timezone()
是 pytz.timezone()
,至少您的问题之一是 pytz
时区不能使用 replace
附加到 datetime
个对象。您需要改为使用 datetime_obj = pytz.timezone(tz_code).localize(datetime_obj)
.
请注意,localize
方法假定您有一个时区初始对象,因此如果 datetutil
的解析器 returns 时区感知 datetime
,因此您应该将 ignoretz=True
传递给解析器以防止出现这种情况。
也就是说,即使您这样做了,真正的问题还是在于您对 time.mktime
的使用。见,完全一样的问题。总结一下这个答案,最好的办法是使用 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())
为什么这个代码:
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')
returns 一个不同的值取决于运行所在机器的时区?
在我的理解中,解析器 returns 一个没有时区的日期时间,然后它分配一个 tz,不改变任何其他东西,最后它被转换成一个时间戳。我本地的tz 哪里都用不了。
dateutil.parser
将附加一个时区当且仅当它找到一个时区,这 可能 取决于您本地机器的时区设置,因为如果它检测到一个缩写像 "EST" 这样的时区在您当地时区的缩写列表中,它会假设这就是您的意思。
也就是说,这不是本例中发生的情况。即使 parser
附加了时区,datetime.replace
也会对时区进行批量替换,而不是转换。我认为您的问题中没有足够的信息来完全诊断此问题,但如果 timezone()
是 pytz.timezone()
,至少您的问题之一是 pytz
时区不能使用 replace
附加到 datetime
个对象。您需要改为使用 datetime_obj = pytz.timezone(tz_code).localize(datetime_obj)
.
请注意,localize
方法假定您有一个时区初始对象,因此如果 datetutil
的解析器 returns 时区感知 datetime
,因此您应该将 ignoretz=True
传递给解析器以防止出现这种情况。
也就是说,即使您这样做了,真正的问题还是在于您对 time.mktime
的使用。见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())