我发现了一些奇怪的东西。这里有一些例子。
from django.utils import timezone
value = u'2014-10-26 01:45:00'
#I know that a variable has 'Europe / Moscow' timezone. Let's tell Django about it.
TZ = timezone.pytz.timezone('Europe/Moscow')
d = timezone.datetime.strptime(value,'%Y-%m-%d %H:%M:%S')
print timezone.make_aware(d,TZ)
#raised AmbiguousTimeError: 2014-10-26 01:45:00
然后有趣的开始
print timezone.make_aware(d+timezone.timedelta(minutes=15),TZ)
#out: 2014-10-26 02:00:00+03:00
print timezone.make_aware(d+timezone.timedelta(minutes=14),TZ)
#raised AmbiguousTimeError
print timezone.make_aware(d-timezone.timedelta(minutes=46),TZ)
#out: 2014-10-26 00:59:00+04:00
print timezone.make_aware(d-timezone.timedelta(minutes=45),TZ)
#raised AmbiguousTimeError
因此在2014-10-26 00:59:00和2014-10-26 02:00:00 之间出现模糊时间错误
为什么?如何解决?
timezon.make_aware(d, TZ)
相当于TZ.localize(d, is_dst=None)
,它会在不明确的时间引发错误:2014-10-26 01:45:00
在欧洲/莫斯科时区发生两次:
# Europe/Moscow UTC timestamp
2014-10-26 00:45:00 MSK+0400; 2014-10-25 20:45:00 UTC+0000; 1414269900
2014-10-26 01:00:00 MSK+0400; 2014-10-25 21:00:00 UTC+0000; 1414270800
2014-10-26 01:15:00 MSK+0400; 2014-10-25 21:15:00 UTC+0000; 1414271700
2014-10-26 01:30:00 MSK+0400; 2014-10-25 21:30:00 UTC+0000; 1414272600
2014-10-26 01:45:00 MSK+0400; 2014-10-25 21:45:00 UTC+0000; 1414273500
2014-10-26 01:15:00 MSK+0300; 2014-10-25 22:15:00 UTC+0000; 1414275300
2014-10-26 01:30:00 MSK+0300; 2014-10-25 22:30:00 UTC+0000; 1414276200
2014-10-26 01:45:00 MSK+0300; 2014-10-25 22:45:00 UTC+0000; 1414277100
2014-10-26 02:00:00 MSK+0300; 2014-10-25 23:00:00 UTC+0000; 1414278000
注意:utc偏移量在凌晨2点从+0400
更改为+0300
(Федераланыйзаконор21иля2014Γ.N 248-ФЗ)。
为了避免出现异常,您可以调用TZ.localize(d)
(注意:没有is_dst=None
),它对现有的不明确时间运行良好,但对不存在或不明确的时间可能会失败(返回错误答案)。
如果pytz Bug#1378150:增强对DST结束的支持,比如不明确的时间是固定的,那么你可以使用TZ.localize(d, is_dst=True)
、TZ.localize(d, is_dst=False)
来相应地获取转换前后的时间。
如果这个错误没有修复,你可以使用我在观察夏令时时解析当地时间(到UTC)的有序时间戳来获得转换后的时间:
# `naive` is a naive datetime object in local (Europe/Moscow) time
if tz.localize(naive, is_dst=False) == tz.localize(naive, is_dst=True):
# Example: 2014/10/26 in Europe/Moscow timezone
# ambiguous time but is_dst=False/True yield the same result
# i.e., tz.localize() can't help, find UTC time manually
#NOTE: assume there is no other changes to UTC offset today (local.day)
new_offset = tz.localize(naive + timedelta(1), is_dst=None).utcoffset()
assert tz.localize(naive).utcoffset() != new_offset
utc = (naive - new_offset).replace(tzinfo=pytz.utc)
local = utc.astimezone(tz)
10月26日凌晨2点,莫斯科人将把时钟拨慢一小时。这意味着他们将看到,例如,当天凌晨1:30两次。因此,凌晨1点到2点之间的时间是模糊的,Python/pytz告诉你这一点。
如何处理这一问题将取决于应用程序。你需要决定你说的是哪一个凌晨1:30(即你说的UTC时间)。
(显然,这是大多数俄罗斯人处理DST的最后一年。有关一些有趣的背景信息,请参阅本文。)