Python Django timezone.make_aware提出了2014-10-26 1:45:00的模糊性错误

Python Django timezone.make_aware提出了2014-10-26 1:45:00的模糊性错误,python,django,timezone,pytz,Python,Django,Timezone,Pytz,我发现了一些奇怪的东西。这里有一些例子 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(valu

我发现了一些奇怪的东西。这里有一些例子

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之间出现了模糊性错误


为什么??怎么解决呢?

这是因为夏令时

10月26日凌晨2点,莫斯科人将把他们的时钟拨慢一小时。这意味着他们将看到,例如,在那天凌晨1:30两次。因此,凌晨1:00到凌晨2:00之间的时间是不明确的,Python/pytz告诉您这一点

如何处理这一问题将取决于具体的应用程序。您需要决定您正在谈论的是哪一个凌晨1:30(即您正在谈论的UTC时间)

(显然,这是大多数俄罗斯人最后一年将处理DST。请参阅一些有趣的背景。)

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

为了避免异常,您可以调用
TZ.localize(d)
(注意:no
is_dst=None
),该函数在现有的非模糊时间内工作正常,但在不存在或模糊时间内可能会失败(返回错误答案)

如果是固定的,那么您可以使用
TZ.localize(d,is u dst=True)
TZ.localize(d,is u dst=False)
相应地获取转换前后的时间

如果错误未修复,您可以使用我的答案来获取转换后的时间:

#`naive`是本地(欧洲/莫斯科)时间的naive datetime对象
如果tz.localize(朴素,is_dst=False)=tz.localize(朴素,is_dst=True):
#示例:2014/10/26欧洲/莫斯科时区
#不明确的时间,但is_dst=假/真产生相同的结果
#例如,tz.localize()无法帮助,请手动查找UTC时间
#注意:假设今天UTC偏移量没有其他变化(local.day)
new_offset=tz.localize(naive+timedelta(1),is_dst=None).utcoffset()
assert tz.localize(naive).utcoffset()!=新偏移量
utc=(原始-新偏移量)。替换(tzinfo=pytz.utc)
本地=utc.astimezone(tz)

它不是DST。欧洲/莫斯科全年都有UTC+0400偏移量。该抵消在2014年10月26日更改为UTC+0300(通过特定政府命令)。虽然效果与DST转换结束(“后退”)相同,例如,请参见——这意味着即使是显式的
TZ.localize(naive,is_-DST=True)
(或
is_-DST=False
)也不会给出所需的时间,直到错误得到修复。