com*_*ugs 28 python datetime pytz
我尝试使用datetime和pytz在python中创建一个datetime对象,显示的偏移是错误的.
import datetime
from pytz import timezone
start = datetime.datetime(2011, 6, 20, 0, 0, 0, 0, timezone('Asia/Kolkata'))
print start
Run Code Online (Sandbox Code Playgroud)
显示的输出是
datetime.datetime(2011, 6, 20, 0, 0, tzinfo=<DstTzInfo 'Asia/Kolkata' HMT+5:53:00 STD>)
Run Code Online (Sandbox Code Playgroud)
请注意,'Asia/Kolkata'是IST,GMT + 5:30,而不是HMT + 5:53.这是一个标准的linux时区,为什么我会弄错,我该如何解决呢?
Fer*_*yer 50
请参阅:http://bytes.com/topic/python/answers/676275-pytz-giving-incorrect-offset-timezone
在评论中,有人建议使用tzinfo.localize()而不是datetime构造函数,这可以解决问题.
>>> tz = timezone('Asia/Kolkata')
>>> dt = tz.localize(datetime.datetime(2011, 6, 20, 0, 0, 0, 0))
>>> dt
datetime.datetime(2011, 6, 20, 0, 0, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
Run Code Online (Sandbox Code Playgroud)
更新:实际上,官方的pytz网站声明你应该总是使用localize或astimezone代替传递时区对象datetime.datetime.
这个问题已在 python >=3.9 中由标准库中的zoneinfo模块修复。>= 3.9 中的解决方案可能是停止使用 pytz。
In [1]: import datetime
In [2]: from zoneinfo import ZoneInfo
In [3]: start = datetime.datetime(2011, 6, 20, 0, 0, 0, 0, ZoneInfo('Asia/Kolkata'))
In [4]: print(start)
2011-06-20 00:00:00+05:30
Run Code Online (Sandbox Code Playgroud)
这种极其令人困惑的行为的原因是,时区过去没有以 :30 或 :00 偏移量进行标准化。在 20 世纪初,大多数都采用了标准胶印。在 OP 的示例中,时区切换于 1906 年。对于美国/中部地区,这发生在 1901 年。
from datetime import datetime, timedelta, date
from pytz import timezone
d = datetime.combine(date.today(), time.min)
for tz in ('Asia/Kolkata', "US/Central"):
while d > datetime(1800, 1, 1):
localized = timezone(tz).localize(d)
if localized.isoformat()[-2:] not in ("00", "30"):
print(tz)
print(localized.isoformat())
print(timezone(tz).localize(d + timedelta(days=1)).isoformat())
break
d -= timedelta(days=1)
Run Code Online (Sandbox Code Playgroud)
输出:
Asia/Kolkata
1906-01-01T00:00:00+05:21
1906-01-02T00:00:00+05:30
US/Central
1901-12-13T00:00:00-05:51
1901-12-14T00:00:00-06:00
Run Code Online (Sandbox Code Playgroud)
当 Pytz 没有日期信息时,它似乎只使用最旧的偏移量,即使它是很久以前的事。在一些非常自然的构造中,例如将 tzinfo 传递给日期时间构造函数,时区对象不会获得该数据。