从时区偏移本地化日期时间(时区感知)

Posted

技术标签:

【中文标题】从时区偏移本地化日期时间(时区感知)【英文标题】:Localize datetime (timezone aware) from timezone offset 【发布时间】:2014-04-13 20:07:38 【问题描述】:

我有一个 UTC 时间戳和一个时区偏移时间戳(均以毫秒为单位):

utc_time = 1394452800000
timezoneoffset = -14400000

如果我想获得datetime,我会这样做:

print datetime.utcfromtimestamp(utc_time/1000)
>>>2014-03-10 12:00:00

我怎样才能本地化这个日期时间,但最终对象也能感知时区?

如果我除以timezoneoffset,-14400000/(3600*1000) = -4(小时)。所以最终的输出应该是:

>>>2014-03-10 08:00:00-04:00

我的尝试:

from pytz import timezone
from dateutil.tz import tzoffset

utc_time = 1394452800000
timezoneoffset = -14400000

tzinfooff = tzoffset(None, timezoneoffset/1000)

print timezone(tzinfooff).localize( datetime.utcfromtimestamp(utc_time/1000) )

>>>Traceback (most recent call last):
  File "/Users/dionysis_lorentzos/Desktop/cmdline copy.py", line 25, in <module>
    print timezone(tzinfo2).localize( datetime.utcfromtimestamp(time/1000) ).isoformat()
  File "/usr/local/lib/python2.7/site-packages/pytz/__init__.py", line 162, in timezone
    if zone.upper() == 'UTC':
AttributeError: 'tzoffset' object has no attribute 'upper'

【问题讨论】:

08:00:00-04:00?或12-4? timezone 没有偏移;我不确定是否有任何pytz 可以调用。 @zhangxaochen utc_time 时间戳在 UTC 时区而不是本地时区(如果我理解正确你的问题)。 @MartijnPieters 所以没有可能的解决方法? 我没这么说。 :-) 【参考方案1】:

您需要使用dateutil.tz.tzoffset() type; pytz.timezone 只接受 names,而不接受 dateutil.tz 对象。

.localize() 方法仅适用于pytz 提供的时区,因为它们也包含历史偏移量,并且需要将它们应用于datetime 对象,比.replace() 可以做的更小心.

如果时间戳是 UTC 中的 UNIX 纪元值,则使用 fromtimestap 和时区作为第二个参数:

>>> print datetime.fromtimestamp(utc_time/1000, tzinfooff)
2014-03-10 08:00:00-04:00

或者您可以翻译 UTC,使用datetime.astimezone()

>>> from dateutil.tz impor tzutc
>>> dt_utc = datetime.utcfromtimestamp(utc_time/1000).replace(tzinfo=tzutc())
>>> print dt_utc.astimezone(tzinfooff)
2014-03-10 08:00:00-04:00

【讨论】:

谢谢!我可以建议:print datetime.utcfromtimestamp((utc_time+timezoneoffset)/1000).replace(tzinfo=tzinfooff) &gt;&gt;&gt;2014-03-10 08:00:00-04:00。还是没有? @Diolor:在这种情况下,您没有附加时区,而是在转换到不同的时区。使用 UTC 时区进行设置,然后使用 datetime.astimezone() 进行翻译。 我会选择datetime.fromtimestamp(),谢谢 @Diolor:我非常同意。 :-) 使用local_dt = utcfromtimestamp(ts).replace(tzinfo=local_tz)不正确【参考方案2】:

要将 POSIX 时间戳转换为由其 utc 偏移指定的时区中的时区感知日期时间对象,您可以创建一个感知 utc 日期时间对象并将其转换为固定偏移时区:

from datetime import datetime

utc_dt = datetime.fromtimestamp(utc_time * 1e-3, utc)
dt = utc_dt.astimezone(FixedOffset(timezoneoffset * 1e-3 / 60, None))

print(dt.isoformat(' '))
# -> 2014-03-10 08:00:00-04:00

其中utcFixedOffsetdatetime docs 中定义:

from datetime import tzinfo, timedelta

class FixedOffset(tzinfo):
    """Fixed offset in minutes east from UTC."""

    def __init__(self, offset, name):
        self.__offset = timedelta(minutes = offset)
        self.__name = name

    def utcoffset(self, dt):
        return self.__offset

    def tzname(self, dt):
        return self.__name

    def dst(self, dt):
        return timedelta(0)

utc = FixedOffset(0, "UTC")

【讨论】:

以上是关于从时区偏移本地化日期时间(时区感知)的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 日期对象未正确调整时区偏移

javascript显示中的时区偏移

将时区偏移量(ISO 8601 格式)添加到原始日期时间

Python pytz 时区转换返回的值与不同日期的时区偏移量不同

从时区偏移或Angularjs中的日期获取时区[重复]

获取带有时区偏移的日期