我总是对Python中的datetimes
和时区转换感到困惑,但现在我遇到了一种奇怪的行为。我(强烈地)怀疑这与夏令时有关,但我不确定,我肯定不知道如何正确处理它。
以下是发生的情况:如果我让datetime
实例知道其时区,我会从中创建epoch
UTC时间戳,然后从中重新创建一个datetime
实例时间戳,我似乎要增加一个小时:
>>> import pytz
>>> import datetime
>>> import time
>>>
>>> naive = datetime.datetime.now()
>>> print "Naive 'now' %s" % naive
Naive 'now' 2014-08-21 11:19:13.019046
>>> eastern_tz = pytz.timezone('US/Eastern')
>>> now_eastern = eastern_tz.localize(naive)
>>> print "Now (eastern) is %s" % now_eastern
Now (eastern) is 2014-08-21 11:19:13.019046-04:00
>>> print "Now (utc) is %s" % now_eastern.astimezone(pytz.utc)
Now (utc) is 2014-08-21 15:19:13.019046+00:00
# This one is correct
>>> now_eastern_utc_timetuple = now_eastern.utctimetuple()
>>> print "Now (eastern) as timetuple %s" % now_eastern_utc_timetuple
Now (eastern) as timetuple time.struct_time(tm_year=2014, tm_mon=8, tm_mday=21, \
tm_hour=15, tm_min=19, tm_sec=13, tm_wday=3, \
tm_yday=233, tm_isdst=0)
# Shouldn't this be isdst=1 ? ----------^^^
>>> now_epoch = time.mktime(now_eastern_utc_timetuple)
>>> print "now epoch (UTC) %s" % now_epoch
now epoch (UTC) 1408652353.0
# I'm pretty sure this is +3600 in advance
>>> print "Converted back: %s" % datetime.datetime.fromtimestamp(now_epoch)
Converted back: 2014-08-21 16:19:13
我已使用epochconverter.com验证了时间,我非常确定utctimetuple
生成的时间戳增加了一小时。正如我所提到的,我几乎可以肯定这与Daylight Time Saving无意识有关,因为如果我尝试使用没有使用白天时间节省的日期(例如12月),它就能正常工作。
>>> naive = datetime.datetime.strptime('2012/12/12 10:00', '%Y/%m/%d %H:%M')
>>> print "Naive 'now' %s" % naive
Naive 'now' 2012-12-12 10:00:00
>>> eastern_tz = pytz.timezone('US/Eastern')
>>> now_eastern = eastern_tz.localize(naive)
>>> print "Now (eastern) is %s" % now_eastern
Now (eastern) is 2012-12-12 10:00:00-05:00
>>> print "Now (utc) is %s" % now_eastern.astimezone(pytz.utc)
Now (utc) is 2012-12-12 15:00:00+00:00
>>> now_eastern_utc_timetuple = now_eastern.utctimetuple()
>>> print "Now (eastern) as timetuple %s" % now_eastern_utc_timetuple
Now (eastern) as timetuple time.struct_time(tm_year=2012, tm_mon=12, tm_mday=12,\
tm_hour=15, tm_min=0, tm_sec=0, tm_wday=2, \
tm_yday=347, tm_isdst=0)
>>> now_epoch = time.mktime(now_eastern_utc_timetuple)
>>> print "now epoch (UTC) %s" % now_epoch
now epoch (UTC) 1355342400.0
>>> print "Converted back: %s" % datetime.datetime.fromtimestamp(now_epoch)
Converted back: 2012-12-12 15:00:00
我正在使用:
所以问题是:我如何才能正确处理这种转换?这个问题与DST有关吗?
提前谢谢你。
答案 0 :(得分:0)
这不应该是isdst = 1吗?
没有。您要求知道日期时间对象为您提供UTC时间元组。 UTC没有DST因此tm_isdst
总是零。
now_eastern.astimezone(pytz.utc)
和now_eastern.utctimetuple()
产生同一时间。如果now_eastern
正确,则它们是正确的。
time.mktime(now_eastern_utc_timetuple)
不正确,因为mktime()
需要本地时间,但now_eastern_utc_timetuple
为UTC。您可以使用calendar.timegm(now_eastern_utc_timetuple)
代替更好now_eastern.timestamp()
,请参阅Converting datetime.date to UTC timestamp in Python。
我会使用:now_eastern = eastern_tz.localize(naive, is_dst=None)
(假设naive
表示'US/Eastern'
中的时间,即假设您的本地时区为'US/Eastern'
,则可以使用tzlocal.get_localzone()
自动获取本地时区< - 引发异常而不是返回错误答案或更好:now_eastern = datetime.now(eastern)
。