Django timezone.make_aware raised an AmbiguousTimeError on 2014-10-26 1:45:00

I found some strange things. Here are some examples.

from django.utils import timezone value = u'2014-10-26 01:45:00' #I know that a variable has 'Europe / Moscow' timezone. Let 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 

And then the fun begins

 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 

So AmbiguousTimeError raised between 2014-10-26 00:59:00 and 2014-10-26 02:00:00

Why? And how to solve it?

+5
source share
2 answers

timezon.make_aware(d, TZ) equivalent to TZ.localize(d, is_dst=None) , which causes an error for ambiguous times: 2014-10-26 01:45:00 occurs twice in Europe / Moscow time zone:

 # 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 

Note: the utc offset changes from +0400 to +0300 at 2 am ( Federal Law of July 21, 2014 N 248- ).

To avoid an exception, you can call TZ.localize(d) (note: no is_dst=None ), which works fine for existing unambiguous times, but may not work (returning an incorrect answer) for non-existent or ambiguous times.

If pytz Error # 1378150: Improved support for indefinite time close to DST , then you can use TZ.localize(d, is_dst=True) , TZ.localize(d, is_dst=False) to get the time before and after the transition, respectively.

If the error is not fixed, you can use my answer from Analysis of ordered timestamps in local time (UTC) when observing daylight saving time to get the time after the transition:

 # `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 # ie, 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) 
+3
source

This is due to summer time.

At 2 a.m. on October 26, Muscovites will return the clock for an hour. This means that they saw, for example, 1:30 in the morning twice that day. So the times between 1:00 and 2:00 in the morning are ambiguous, and Python / pytz tells you this.

How you handle this will be application specific. You need to decide what time you are talking at 1:30 (i.e. what UTC time you are talking about).

(Apparently, this is the last year when most Russians will deal with DST. See this article for some interesting background.)

+1
source

Source: https://habr.com/ru/post/1205086/


All Articles