Python 从aware datetime到timestamp再到timestamp的转换将增加一个小时?

Python 从aware datetime到timestamp再到timestamp的转换将增加一个小时?,python,datetime,timestamp,epoch,date-conversion,Python,Datetime,Timestamp,Epoch,Date Conversion,我总是对Python中的datetimes和时区转换感到困惑,但现在我遇到了一个相当奇怪的行为。我(强烈地)怀疑这与夏令时有关,但我不确定,也不知道如何正确处理 下面是发生的情况:如果我让一个datetime实例知道它的时区,我将从它创建一个epochUTC时间戳,然后从该时间戳重新创建一个datetime实例,我似乎可以获得一个小时: >>> import pytz >>> import datetime >>> import time &

我总是对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
我已经使用验证了时间,并且我非常确定从
utctimetuple
生成的时间戳增加了一个小时。正如我所提到的,我几乎可以肯定这与夏令时的不了解有关,因为如果我尝试使用夏令时未使用的日期(例如,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
我正在使用:

  • Mac Os X 10.9.4
  • Python 2.7
  • pytz 2012j
所以问题是:我如何正确处理这种转换?这个问题与DST有关吗

先谢谢你

这不应该是isdst=1吗

否。您要求aware datetime对象提供UTC时间元组。UTC没有DST,因此
tm_isdst
始终为零

now_eastern.astimezone(pytz.utc)
now_eastern.utctimetuple()
产生相同的时间。如果
now\u eastern
正确,则它们是正确的

time.mktime(现在东部utc时间组)
不正确,因为
mktime()
需要本地时间,但
现在东部utc时间组
是utc时间。您可以使用
calendar.timegm(现在是东部时间组)
,或者更好的
now\u东部时间戳()
,请参阅

我会使用:
now_eastern=eastern_tz.localize(naive,is_dst=None)
(假设
naive
表示时间在
'US/eastern'
中,即假设您的本地时区是
'US/eastern'
,您可以使用
tzlocal.get_localzone()
自动获取本地时区)