如何在 python 中使用正确的时区将时间戳转换为日期时间



你会天真地期望这能工作:

import pytz
from datetime import datetime
def tz_datetime_from_timestamp(timestamp):
    """Convert a timestamp into a datetime """
    tz = pytz.timezone('Australia/Perth')
    server_time = datetime.utcnow()
    delta = tz.utcoffset(server_time)
    value = datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)
    return value + delta
print tz_datetime_from_timestamp(1416387060)

并将时间戳1416387060转换为 2014 年 11 月 19 日星期三 16:51:00 GMT+8:00。

。但事实并非如此。它打印:

2014-11-19 16:51:00+07:43

澳大利亚/珀斯时区不是GMT+7:43。

现在是格林威治标准时间+8:00。澳大利亚政府网站 http://www.australia.gov.au/about-australia/our-country/time 明确指出了这一点:

AWST is equal to Coordinated Universal Time plus 8 hours (UTC +8).

那么,皮茨到底从哪里拉出 7.43 呢?

好吧,事实证明pytz从 http://www.iana.org/time-zones 时区数据库中提取数据,并且该数据库指出:

# Western Australia
#
# Rule  NAME  FROM  TO  TYPE  IN  ON  AT  SAVE  LETTER/S
Rule  AW  1974  only  - Oct lastSun 2:00s 1:00  D
Rule  AW  1975  only  - Mar Sun>=1  2:00s 0 S
Rule  AW  1983  only  - Oct lastSun 2:00s 1:00  D
Rule  AW  1984  only  - Mar Sun>=1  2:00s 0 S
Rule  AW  1991  only  - Nov 17  2:00s 1:00  D
Rule  AW  1992  only  - Mar Sun>=1  2:00s 0 S
Rule  AW  2006  only  - Dec  3  2:00s 1:00  D
Rule  AW  2007  2009  - Mar lastSun 2:00s 0 S
Rule  AW  2007  2008  - Oct lastSun 2:00s 1:00  D
Zone Australia/Perth   7:43:24 -  LMT 1895 Dec
       8:00 Aus AW%sT 1943 Jul
       8:00 AW  AW%sT

井。那真是太好了...但这也是不正确的。

。不幸的是,Python也是如此。

olson 时间数据库充满了类似 like 的值(4 小时 15 分钟、5 小时 20 分钟等)。完全奇怪。

从技术上讲,我真的不在乎确切的时区是什么,只要它普遍一致; 不幸的是,事实并非如此。 例如,进行 API 调用并将时区传递给(正确)使用 GMT+8 时区的远程服务会导致在将时区转换为 UTC 进行处理时值之间略有差异。

即。需要绝对清楚的是,这两个值在转换为 UTC 时是不同的时间

  • 周三 11月 19 16:51:00 2014 GMT+8:00
  • 周三 11月 19 16:51:00 2014 GMT+7:43

令人恼火的是:

server_time = datetime.utcnow()
delta = tz.utcoffset(server_time)
print(delta)

收益 率:

8:00:00

很明显,pytz 内部确实知道正确的时区偏移量。它只是生成附加了错误值的输出。

最后:如何生成附加了正确时区的日期时间?

话短说,pytz 默认为不正确的时区,并且 datetime.replace() 不执行转换:

import pytz
from datetime import datetime
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
tz = pytz.timezone('Australia/Perth')
timestamp = 1416387060
print(tz)
# Correct way
utctime = pytz.utc.localize(datetime.utcfromtimestamp(timestamp))
print(utctime.strftime(fmt))
astimezone = utctime.astimezone(tz)
print(astimezone.strftime(fmt))
localtime = tz.normalize(astimezone)
print(localtime.strftime(fmt))
# Incorrect way
incorrect = datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)
print(incorrect.strftime(fmt))

您可以在讨论它的 pytz 中的各种错误中阅读有关此内容的更多信息:

  • https://bugs.launchpad.net/pytz/+bug/1394441
  • https://bugs.launchpad.net/pytz/+bug/1319939
  • https://bugs.launchpad.net/pytz/+bug/1389042

相关内容

  • 没有找到相关文章

最新更新