2

也许这是一个凌晨 4 点的错误,但我认为我做的一切都是正确的,但似乎 DST 并未从 UTC 时间戳转换为本地化日期时间。

>>> from datetime import datetime
>>> import pytz
>>> eastern = pytz.timezone("US/Eastern")
>>> utc = pytz.utc
>>> local_now = eastern.localize(datetime.now())
>>> utc_now = local_now.astimezone(utc)
>>> seconds = int(utc_now.strftime("%s"))
>>> utc_then = utc.localize(datetime.fromtimestamp(seconds))
>>> local_then = utc_then.astimezone(eastern)
>>> print utc_now, utc_then
2013-06-16 10:05:27.893005+00:00 2013-06-16 11:05:27+00:00
>>> print local_now, local_then
2013-06-16 06:05:27.893005-04:00 2013-06-16 07:05:27-04:00
4

3 回答 3

4
             o------------o
             |            |  DT.datetime.utcfromtimestamp (*)
             |            |<-----------------------------------o
             |            |                                    |
             |  datetime  |                                    |
             |            |  DT.datetime.fromtimestamp         |
             |            |<----------------------------o      |
             |            |                             |      |
             o------------o                             |      |
                |   ^                                   |      |
     .timetuple |   |                                   |      |
  .utctimetuple |   | DT.datetime(*tup[:6])             |      |
                v   |                                   |      |
             o------------o                          o------------o
             |            |-- calendar.timegm (*) -->|            |
             |            |                          |            |
             |            |---------- time.mktime -->|            |
             |  timetuple |                          |  timestamp |
             |            |<-- time.localtime -------|            |
             |            |                          |            |
             |            |<-- time.gmtime (*)-------|            |
             o------------o                          o------------o

(*) Interprets its input as being in UTC and returns output in UTC

如图所示,当您在 UTC 中有一个日期时间时,如utc_now要获取其时间戳,请使用

seconds = calendar.timegm(utc_date.utctimetuple())

当您有时间戳时,要获取 UTC 的日期时间,请使用

DT.datetime.utcfromtimestamp(seconds)

import datetime as DT
import pytz
import calendar
eastern = pytz.timezone("US/Eastern")
utc = pytz.utc
now = DT.datetime(2013, 6, 16, 10, 0, 0)
local_now = eastern.localize(now)
utc_now = local_now.astimezone(utc)
seconds = calendar.timegm(utc_now.utctimetuple())

print(seconds)
# 1371391200

utc_then = utc.localize(DT.datetime.utcfromtimestamp(seconds))
local_then = utc_then.astimezone(eastern)

print utc_now, utc_then
# 2013-06-16 14:00:00+00:00 2013-06-16 14:00:00+00:00
print local_now, local_then
# 2013-06-16 10:00:00-04:00 2013-06-16 10:00:00-04:00

PS。请注意,timetuple()andutctimetuple()方法会减少日期时间的微秒。要以保留微秒的方式将日期时间转换为时间戳,请使用mata 的解决方案

于 2013-06-16T10:38:15.110 回答
4

datetime.now如果要编写可移植代码,则应避免使用,因为它始终使用本地时区,因此local_now = eastern.localize(datetime.now())仅在本地计算机上的时区东部时才有效。总是尝试使用utcnow,并且出于同样的原因utcfromtimestamp

此外,strftime("%s")用于将日期时间转换为时间戳也不起作用。

from datetime import datetime
import pytz

utc_now = pytz.utc.localize(datetime.utcnow())
eastern = pytz.timezone("US/Eastern")
local_now = utc_now.astimezone(eastern)

# seconds = utc_now.timestamp()  python3
seconds = (utc_now - pytz.utc.localize(datetime.utcfromtimestamp(0))).total_seconds()
utc_then = pytz.utc.localize(datetime.utcfromtimestamp(seconds))

local_then = utc_then.astimezone(eastern)

print("%s - %s" % (utc_now, utc_then))
print("%s - %s" % (local_now, local_then))
于 2013-06-16T10:48:09.787 回答
0

要将您的本地时区作为pytz.timezone对象,您可以使用tzlocal模块:

#!/usr/bin/env python
from datetime import datetime
import pytz # pip install pytz
from tzlocal import get_localzone # pip install tzlocal

local_tz = get_localzone()
local_now = datetime.now(local_tz)
utc_now = local_now.astimezone(pytz.utc)
seconds = (utc_now - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()

utc_then = datetime.fromtimestamp(seconds, pytz.utc)
local_then = utc_then.astimezone(local_tz)
print("%s %s" % (utc_now, utc_then))
print("%s %s" % (local_now, local_then))
  • 不要使用datetime.now()——它可能是模棱两可的,例如,在 DST 更改期间。要么像我的例子那样明确传递 tzinfo 要么使用datetime.utcnow()
  • 不要使用utc_now.strftime('%s')—— 它会忽略时区信息(它使用当前的本地时区)并且它是不可移植的。改用datetime.timestamp()方法或其类似物
  • 不要使用utc.localize(datetime.fromtimestamp(seconds))--.fromtimestamp()返回本地时区中可能与 UTC 不同的天真日期时间对象。要么像我的示例中那样显式传递 tzinfo,要么datetime.utcfromtimestamp()用于获取表示 UTC 时间的天真日期时间对象
  • 不要datetime.utctimetuple()与天真的日期时间对象一起使用——它不会将它们转换为 UTC。如果对象已经是 UTC:utc_now.timetuple()返回相同的时间。

要为不明确的当地时间引发异常,请使用localize(is_dst=None)

aware_dt = tz.localize(naive_dt, is_dst=None)

如果没有is_dst=None,则在 DST 更改期间有 50% 的机会tz.localize()返回错误结果。如果在您的特定情况下最好得到一个可能错误的结果而不是异常,那么您可以通过显式is_dst=False来提醒自己。

通常,如果源时区和目标时区都不是 UTC,则pytz文档建议tz.normalize()在通话后进行。.astimezone()

于 2014-08-20T07:58:45.633 回答