[egenix-users] mx.DateTime gmtoffset gmtime DST messup

François Meyer fmeyer at obs-besancon.fr
Tue Nov 6 16:09:10 CET 2012


On Tue, 6 Nov 2012, M.-A. Lemburg wrote:

> Hi François,
>
> thanks for reporting this. I've opened a ticket for it.
>
> Could you please let me know, whether the system is running
> in POSIX mode, e.g.
>
>>>> import mx.DateTime
>>>> mx.DateTime.POSIX
> 1

Yep. Both the production system (debian 4.0) and the 
test system (ubuntu 12.04) report 1.

> The calculation of the offset relies on the correctness
> of the mktime() C lib API in most parts, but since DST
> switching is always tricky, it's also possible that we made
> a mistake somewhere that only shows up during switching
> times.
>
> Looking at the code, I think I know why this is happening:
> mxDateTime checks the GMT offset by interpreting the
> given time as local time and using mktime() to calculate
> the offset at the given time.
>
> Now, when moving from DST to normal time, the hour 02:00-02:59
> exists twice. mktime() appears to map that hour to the
> first run (still in DST timezone), which is why the offset
> is wrong during the second run through of that hour in local
> time.
>
> I'm not exactly sure how this could be fixed, since the time
> where the problem occurs is indeed ambiguous and mxDateTime
> has no way of knowing which hour the local time value is
> referring to.

Yes. I had to clarify that in my head : clearly, you can allways 
unambiguously go from UTC to whatever timezone and DST status is, 
but the opposite is not true. This is an intrinsec ambiguity and in fact 
in my case, the proper way of dealing with it would be :

1. get system UTC time
2. deduce DST status and local CET time

This is sound, but what I did is :

1. get local time
2. deduce UTC time and offset

and this cannot be done unambiguously at least during DST switch.

I checked that the python datetime package deals with 
that by distinguishing between "aware" and "naive" objects:

http://docs.python.org/2/library/datetime.html

Basically, if "naive", a datetime.utcoffset() will return None,
and it would in my case.

So the bottom line is that probably gmtoffset and gmtime 
should return an error or None in such situation.


> I'll have a closer look at the problem later this week.
>
> On 30.10.2012 11:09, François Meyer wrote:
>> Hi,
>>
>> I ran through a weird problem with mx.DateTime
>> during last DST switch on CET on sunday 2012-10-28 01:00 UTC.
>>
>> CET is on DST at UTC+2 up to 2012-10-18 01:00 UTC, then switches to UTC+1.
>>
>> In fact, for one hour past the switch, gmtoffset remained
>> stuck at +2 instead of +1.
>>
>> The machine monitors a timing system, the monitoring is driven by a python script, and it needs TZ
>> info. I ran through the problem looking at the logs during the night of the switch from DST.
>>
>> The logs are a bit verbose so I reproduce a simplified version of what happenned on another machine
>> ; this tiny script is ran on a Ubuntu 12.04.1, system time is UTC.
>>
>>   #!/usr/bin/python
>>   from mx import DateTime
>>   from time import sleep
>>   t=DateTime.now()
>>   while 1:
>>       print "------------------------------------------------"
>>       print "t = DateTime.now() : ", t
>>       print "t.gmtoffset ", t.gmtoffset()
>>       print "t.gmtime ", t.gmtime()
>>       sleep(5)
>>
>> I will set time on the machine, run this script on CET timezone
>> and see what happens around the switch date (20121028 01:00 UTC).
>>
>> 1st test, close to what really happened :
>>
>> I first set system (UTC) time at 2012-10-27 23:59, and check, I get that :
>>
>>   root at ganymede:~# date -s"20121027 23:59"; date; TZ=CET date;
>>   Sat Oct 27 23:59:00 UTC 2012
>>   Sat Oct 27 23:59:00 UTC 2012
>>   Sun Oct 28 01:59:00 CEST 2012
>>
>> then I run the script, in CET timezone :
>>
>>   fm at ganymede:~$ TZ=CET ./test_tz.py
>>   t = DateTime.now() :  2012-10-28 01:59:00.04
>>   t.gmtoffset  02:00:00.00
>>   t.gmtime  2012-10-27 23:59:00.04
>>
>> There all is ok. Two minutes later :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-10-28 02:01:08.90
>>   t.gmtoffset  02:00:00.00
>>   t.gmtime  2012-10-28 00:01:08.90
>>
>> still ok (but see further ref [1] in the text)
>>
>> One hour later, one minute before the switch :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-10-28 02:59:01.80
>>   t.gmtoffset  02:00:00.00
>>   t.gmtime  2012-10-28 00:59:01.80
>>
>> Still ok
>>
>> One minute later, after the switch :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-10-28 02:00:01.86
>>   t.gmtoffset  02:00:00.00
>>   t.gmtime  2012-10-28 00:00:01.86
>>
>> t is ok,
>> gmtoffset is bogus
>> gmtime is bogus, one hour back
>>
>> that situation lasts one hour :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-10-28 02:59:59.65
>>   t.gmtoffset  02:00:00.00
>>   t.gmtime  2012-10-28 00:59:59.65
>>
>> still bogus.
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-10-28 03:00:04.66
>>   t.gmtoffset  01:00:00.00
>>   t.gmtime  2012-10-28 02:00:04.66
>>
>> back to normal. This is exactly the behaviour I observed in my logs.
>>
>> 2nd test : I first set the date 1 hour before the switch and check :
>>
>>   root at ganymede:~# date -s"20121028 00:00"; date; TZ=CET date
>>   Sun Oct 28 00:00:00 UTC 2012
>>   Sun Oct 28 00:00:04 UTC 2012
>>   Sun Oct 28 02:00:12 CEST 2012
>>
>> Then I run the script, after setting TZ :
>>
>>   fm at ganymede:~$ TZ=CET ./test_tz.py
>>   t = DateTime.now() :  2012-10-28 02:01:31.54
>>   t.gmtoffset  01:00:00.00
>>   t.gmtime  2012-10-28 01:01:31.54
>>
>> t is ok, but gmtoffset is wrong, and so does gmtime.
>>
>> So at the same system (UTC) time 20121028 00:01, DateTime gives two different
>> answers (in one case, the script has been launched on UTC 20121027,
>> DateTime gives correct result ref [1];  if the script is launched on UTC 20121028 00:00,
>> DateTime gives bogus results for gmtime and gmtoffset.
>>
>> This is not specific to CET, I tested with TZ=EST5DST :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-11-04 01:59:59.25
>>   t.gmtoffset  -04:00:00.00
>>   t.gmtime  2012-11-04 05:59:59.25
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-11-04 01:00:04.26
>>   t.gmtoffset  -04:00:00.00
>>   t.gmtime  2012-11-04 05:00:04.26
>>
>> bogus, gmtime jumped backward, gmtoffset is wrong.
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-11-04 01:00:09.26
>>   t.gmtoffset  -04:00:00.00
>>   t.gmtime  2012-11-04 05:00:09.26
>>
>> and one hour later :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-11-04 01:59:58.81
>>   t.gmtoffset  -04:00:00.00
>>   t.gmtime  2012-11-04 05:59:58.81
>>
>> Stil bogus and finally :
>>
>>   ------------------------------------------------
>>   t = DateTime.now() :  2012-11-04 02:00:03.81
>>   t.gmtoffset  -05:00:00.00
>>   t.gmtime  2012-11-04 07:00:03.81
>>
>> back to normal, gmtime jumping one hour forward.
>>
>> (By the way, gmtime and gmtoffset two should read utctime and utcoffset).
>>
>> Any idea on what's going on ?
>>
>> Thank you in advance.
>>
>> Regards,
>>
>>
>>
>> _______________________________________________________________________
>> eGenix.com User Mailing List                     http://www.egenix.com/
>> https://www.egenix.com/mailman/listinfo/egenix-users
>>
>
> -- 
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Source  (#1, Nov 06 2012)
>>>> Python Projects, Consulting and Support ...   http://www.egenix.com/
>>>> mxODBC.Zope/Plone.Database.Adapter ...       http://zope.egenix.com/
>>>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/
> ________________________________________________________________________
>
> ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::
>
>   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
>    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>           Registered at Amtsgericht Duesseldorf: HRB 46611
>               http://www.egenix.com/company/contact/
>

-- 
François Meyer    Tel : (+33) 3 81 66 69 27   Mob : 6 27 28 56 83
Observatoire de Besancon - BP1615 - 25010 Besancon cedex - FRANCE
Institut UTINAM * Universite de Franche-Comte * CNRS UMR 6213 ***


More information about the egenix-users mailing list