Django timezone.make_aware为2014-10-26 1:45:00引发歧义时间错误



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

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的最后一年。有关一些有趣的背景信息,请参阅本文。)

相关内容

  • 没有找到相关文章

最新更新