【问题标题】:The Trouble with Timezones - all timezones are local timezones?时区问题 - 所有时区都是本地时区?
【发布时间】:2014-10-04 11:02:43
【问题描述】:

我在 python 中遇到了时区问题,并且有一个奇怪的例子...... 我正在使用 Python 2.7.2

import time
import datetime
import pytz
utc = pytz.utc
est = pytz.timezone('US/Eastern')
mst = pytz.timezone('US/Mountain')
print 'UTC time',time.mktime(datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=utc).timetuple())/3600
print 'EST time',time.mktime(datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=est).timetuple())/3600
print 'MST time',time.mktime(datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=mst).timetuple())/3600

我认为对于三个示例(UTC、EST、MST)我应该得到 0.0、5.0 和 7.0 - 但是对于所有三种情况我都得到 5.0(我的计算机在 EST 中运行)。

另外

time.mktime(time.gmtime(0))

返回 18000.0(5 小时) - 所以 - 明确请求 gmtime 获取元组,然后转换为 epoch 返回 5 小时。我的 python 发行版有 time.time() 和 time.gmtime(),但没有 time.timegm()

那么,如果我从 MST 中的客户那里收到数据 - 并且想要以 UTC 生成一个纪元 - 我是否必须假装时间戳是 EST 然后加上五个小时?

这是 strptime 丢弃时区信息的结果吗?

【问题讨论】:

    标签: python python-2.7 datetime timezone python-datetime


    【解决方案1】:

    timetuple()(以及所有其他基于 struct-tm 的函数)丢弃时区信息;即,时间元组数据结构根本没有时区字段。它旨在将日期时间分解为其组件显示字段,因此它从未真正设计用于计算时间值。尽可能保持日期时间格式的值。

    >>> datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=utc)
    datetime.datetime(1970, 1, 1, 0, 0, tzinfo=<UTC>)
    >>> datetime.datetime(1970, 01, 01, 0, 0, 0, tzinfo=utc).timetuple()
    time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
    

    此外,您不应该只是将 tzinfo 直接插入到 datetime 构造函数中——它并不总是给出正确的结果,根据这个答案:dateutil and pytz give different results。改用 localize(),让 pytz 有机会根据任何适用的时区规则处理数据。

    以下代码将从 MST 转换为 EST:

    >>> now = mst.localize(datetime.datetime(1970, 01, 01, 0, 0, 0))
    >>> now
    datetime.datetime(1970, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Mountain' MST-1 day, 17:00:00 STD>)
    >>> now.astimezone(est)
    datetime.datetime(1970, 1, 1, 2, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
    

    我不知道这是否能处理所有极端情况。例如,您经常会在夏令时转换期间看到奇怪的事情发生。如果遇到问题,请开始搜索第三方时间库。

    【讨论】:

    • 我明白了——然后我可以导入日历并使用 calendar.timegm(now.astimezone(utc).timetuple()) 从 mst 日期获取 UTC 纪元
    • 是的,一旦您将日期时间设置为 UTC,timegm 就会起作用。您还可以使用 timedelta 算法来计算自纪元以来的秒数,如 stackoverflow.com/questions/8777753/… 中所建议的那样。 epoch=utc.localize(datetime.datetime(1970, 01, 01, 0, 0, 0)); timestamp=now-epoch
    • @eigenjohnson:(now - datetime(1970, 1, 1, tzinfo=utc)).total_seconds() 适用于时区感知日期时间对象 (now)。 utc 是一个特殊的时区,您可以直接将其传递给 tzinfo 参数。当地时间(以naive_dt 给出)可能不明确或不存在,您可以在这种情况下使用aware_dt = tz.localize(naive_dt, is_dst=None) 引发异常,而不是默默地返回错误答案(注意:is_dst=None 参数)。
    猜你喜欢
    • 2015-05-15
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 2020-09-18
    • 2017-04-23
    相关资源
    最近更新 更多