你会天真地期望这能工作:
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