[Datetime-SIG] time module issues Was: PEP-431/495

Alexander Belopolsky alexander.belopolsky at gmail.com
Tue Aug 25 19:08:44 CEST 2015

I am changing the subject line because neither of the PEPs mentioned in the
original subject propose any changes to the time module.  It is also likely
that this discussion is off-topic on the Datetime-SIG mailing list and we
should continue it on the relevant bug tracker issues.

On Tue, Aug 25, 2015 at 11:47 AM, Akira Li <4kir4.1i at gmail.com> wrote:
> Alexander Belopolsky <alexander.belopolsky at gmail.com> writes:
> >> On Aug 25, 2015, at 7:44 AM, Akira Li <4kir4.1i at gmail.com> wrote:
> >>
> >> note: stdlib variant datetime.now(timezone.utc).astimezone() may fail
if it
> >> uses time.timezone, time.tzname internally [3,4,5] when tm_gmtoff
> >> tm_zone are not available on a given platform.
> >
> > If this actually happens on any supported platform - please file a bug
> > report.  What we do in this case is not as simplistic as you describe.
> Bug-driven development is probably not the best strategy for a datetime
> library ;) Tests can't catch all bugs. I've found out that astimezone()
> may fail by *reading* its source and trying to *understand* what it does.

I agree, but once you've read the code and see any logical errors, you
should be able to construct a test case demonstrating wrong behavior.

> Here's the part from datetime.py [1] that computes the local timezone if
> tm_gmtoff or tm_zone are not available:
>   # Compute UTC offset and compare with the value implied
>   # by tm_isdst.  If the values match, use the zone name
>   # implied by tm_isdst.
>   delta = local - datetime(*_time.gmtime(ts)[:6])
>   dst = _time.daylight and localtm.tm_isdst > 0
>   gmtoff = -(_time.altzone if dst else _time.timezone)
>   if delta == timedelta(seconds=gmtoff):
>       tz = timezone(delta, _time.tzname[dst])
>   else:
>       tz = timezone(delta)
> Here's its C equivalent [2].
> Python issues that I've linked in the previous message [3,4,5] demonstrate
> that time.timezone and time.tzname may have wrong values and therefore
> the result *tz* may have a wrong tzname.

To summarize for those who  will not follow the links: [3] Is a closed "No
obvious and correct way to get the time zone offset" issue.  It was
superseded by <http://bugs.python.org/issue9527> which in turn was closed
by implementing the argument-less .astimezone() method.  [4] and [5] are
time module issues.

> Here's an example inspired by
> "incorrect time.timezone value" Python issue [4]:
>   >>> from datetime import datetime, timezone
>   >>> from email.utils import parsedate_to_datetime
>   >>> import tzlocal # to get local timezone as pytz timezone
>   >>> d = parsedate_to_datetime("Tue, 28 Oct 2013 14:27:54 +0000")
>   >>> # expected (TZ=Europe/Moscow)
>   ...
>   >>> d.astimezone(tzlocal.get_localzone()).strftime('%Z%z')
>   'MSK+0400'
>   >>> # got
>   ...
>   >>> d.astimezone().strftime('%Z%z')
>   'UTC+04:00+0400'

I don't understand why you keep presenting a mix of pytz, email.utils and
something called "tzlocal" and then claim that the unexpected behavior
indicates a problem in the datetime module?  It could as well be in any of
the three other modules that you use or in the way you combine them.

If you want to parse the string "Tue, 28 Oct 2013 14:27:54 +0000" and
convert it to Moscow time, here is how you do it using the datetime module:

>>> import os; os.environ['TZ'] = 'Europe/Moscow'
>>> from datetime import datetime
>>> d = datetime.strptime("Tue, 28 Oct 2013 14:27:54 +0000", "%a, %d %b %Y
%H:%M:%S %z")
>>> d.astimezone().strftime("%F %T %Z%z")
'2013-10-28 18:27:54 MSK+0400'

Does this code behave differently on your system?  If it does - please file
a bug report.

> 'UTC+04:00' instead of 'MSK' is not a major issue. I don't consider it a
> bug because without access to the tz database stdlib can't do much
> better, there always be cases when it breaks.

It is quite possible that that such cases exist, but you have not
demonstrated one.

> I just use pytz instead which does provide access to the tz database.

This will always be your option as it is your option to use just the
datetime module.  In both cases you can write correct code if you follow
the reference manual or buggy code if you don't.  An almost sure way to
write buggy code is to use one library manual to write code using another.

> [1]
> [2]
> [3] http://bugs.python.org/issue1647654
> [4] http://bugs.python.org/issue22752
> [5] http://bugs.python.org/issue22798
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/datetime-sig/attachments/20150825/a24c6799/attachment.html>

More information about the Datetime-SIG mailing list