我发现了一些奇怪的事情。这里有一些例子。
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
之间提出了AmbiguousTimeError为什么?怎么解决呢?
答案 0 :(得分:3)
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
注意:凌晨2点(Федеральный закон от 21 июля 2014 г. N 248-ФЗ),utc偏移从+0400
更改为+0300
。
为了避免异常,你可以调用TZ.localize(d)
(注意:没有is_dst=None
),对于现有的非模糊时间可以正常工作,但对于不存在或不明确的时间可能会失败(返回错误的答案)
如果pytz Bug #1378150: Enhance support for end-of-DST-like ambiguous time已修复,那么您可以使用TZ.localize(d, is_dst=True)
,TZ.localize(d, is_dst=False)
来相应地转换前后的时间。
如果错误未得到解决,您可以使用Parsing of Ordered Timestamps in Local Time (to UTC) While Observing Daylight Saving Time的答案在过渡后获得的时间:
# `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)
答案 1 :(得分:1)
这是因为夏令时。
10月26日凌晨2点,莫斯科人将时钟缩短一小时。这意味着他们将在那天看到两次,例如,凌晨1:30。因此,凌晨1点到凌晨2点之间的时间不明确,Python / pytz告诉你。
如何处理这将是特定于应用程序的。您需要决定您正在谈论的是哪一个上午1:30(即您正在谈论的UTC时间)。
(显然这是大多数俄罗斯人去年处理夏令时的最后一年。请参阅this article了解一些有趣的背景。)