[Datetime-SIG] PEP-431/495
Akira Li
4kir4.1i at gmail.com
Thu Aug 27 16:38:33 CEST 2015
Stuart Bishop <stuart at stuartbishop.net> writes:
...
> the complexities and slowdowns of timeline arithmetic. While not
> changing the behaviour of datetime at all, we could get cats and dogs
> living together by just clarifying what it actually is.
An *observation*: the local timezone -- the only timezone with a variable
utc offset in _stdlib -- behaves like pytz_:
# start with the same utc time
utc_time = datetime(2015, 10, 25, 1, tzinfo=timezone.utc)
stdlib_time = utc_time.astimezone() # stdlib local time
pytz_time = utc_time.astimezone(tzlocal.get_localzone())
dateutil_time = utc_time.astimezone(dateutil.tz.tzlocal())
All times are consistent so far.
Perform the same operations:
>>> stdlib_time - timedelta(seconds=1)
datetime.datetime(2015, 10, 25, 1, 59, 59, tzinfo=datetime.timezone(datetime.timedelta(0, 3600), 'CET'))
>>> pytz_time - timedelta(seconds=1)
datetime.datetime(2015, 10, 25, 1, 59, 59, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
>>> dateutil_time - timedelta(seconds=1)
datetime.datetime(2015, 10, 25, 1, 59, 59, tzinfo=tzlocal())
Get different results. The times are the same but utc offset are different:
>>> (stdlib_time - timedelta(seconds=1)).utcoffset()
datetime.timedelta(0, 3600)
>>> (pytz_time - timedelta(seconds=1)).utcoffset()
datetime.timedelta(0, 3600)
>>> (dateutil_time - timedelta(seconds=1)).utcoffset() #XXX different
datetime.timedelta(0, 7200)
It is expected for arithmetic in the presense of DST transitions. Here's
the standard fix:
>>> (stdlib_time - timedelta(seconds=1)).astimezone()
datetime.datetime(2015, 10, 25, 2, 59, 59, tzinfo=datetime.timezone(datetime.timedelta(0, 7200), 'CEST'))
>>> (pytz_time - timedelta(seconds=1)).astimezone(tzlocal.get_localzone())
datetime.datetime(2015, 10, 25, 2, 59, 59, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)
>>> (dateutil_time - timedelta(seconds=1)).astimezone(dateutil.tz.tzlocal()) #XXX different
datetime.datetime(2015, 10, 25, 1, 59, 59, tzinfo=tzlocal())
>>> datetime(2015, 10, 25, 1, 59, 59, tzinfo=dateutil.tz.tzlocal()).strftime('%Z%z')
'CEST+0200'
Now the all timezones are the same but the times are different.
pytz recommends normalize() method instead of astimezone() here:
>>> tzlocal.get_localzone().normalize(pytz_time - timedelta(seconds=1))
datetime.datetime(2015, 10, 25, 2, 59, 59, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)
The result is the same in this case.
It is a _fact_. It is how python behaves now on my platform.
To try it yourself, add this at the top:
import os
import time
from datetime import datetime, timezone, timedelta
os.environ['TZ'] = 'Europe/Paris'
time.tzset()
import dateutil.tz
import tzlocal # get local timezone as pytz tzinfo
More information about the Datetime-SIG
mailing list