【问题标题】:Conversion from aware datetime to timestamp and back is gaining one hour?从感知日期时间到时间戳并返回的转换正在增加一小时?
【发布时间】:2014-10-15 07:45:27
【问题描述】:

我总是对 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 生成的时间戳增加了一小时。正如我所提到的,我几乎可以肯定这与不了解夏令时有关,因为如果我尝试使用不使用夏令时的日期(例如 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

所以问题是:如何正确处理这种转换?这个问题与夏令时有关吗?

提前谢谢你。

【问题讨论】:

    标签: python datetime timestamp epoch date-conversion


    【解决方案1】:

    这不应该是 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)。

    【讨论】:

      猜你喜欢
      • 2014-08-23
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      • 2011-10-20
      • 2018-05-11
      • 1970-01-01
      • 1970-01-01
      • 2013-08-13
      相关资源
      最近更新 更多