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

时间:2014-11-19 09:11:34

标签: python datetime

你会天真地期望这样做:

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转换为Wed Nov 19 16:51:00 GMT + 8:00。

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

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

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

GMT + 8:00。澳大利亚政府网站http://www.australia.gov.au/about-australia/our-country/time明确说明了这一点:

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

那么,哪里是pytz从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时间数据库充满了类似的值(4小时15分钟,5小时20分钟等)。非常奇怪。

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

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

  • Wed Nov 19 16:51:00 2014 GMT + 8:00
  • Wed Nov 19 16:51:00 2014 GMT + 7:43

不快:

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

收率:

8:00:00

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

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

1 个答案:

答案 0 :(得分:0)

长话短说,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中讨论的各种错误中阅读更多相关内容: