Re: [Datetime-SIG] how does PEP-495 help improve dateutil, pytz timezone packages?
Alexander Belopolsky
On Tue, Aug 25, 2015 at 7:19 PM, Akira Li <4kir4.1i@gmail.com> wrote:
Here's a distilled example:
from datetime import datetime, timezone datetime(2013, 10, 28, tzinfo=timezone.utc).astimezone().strftime('%Z%z')
If you *disable tm_gmtoff attribute* then it produces UTC+04:00+0400. That differs from the expected output MSK+0400, like the same code demonstrates if you enable the attribute. Notice (direct quote): "if tm_gmtoff or tm_zone are not available" above.
Of course! That's why we exposed tm_gmtoff attribute in time.time_struct on *all platfoms* IIRC. It's been a long time, by I recall that we went to some great lengths to emulate tm_gmtoff by comparing the results of localtime calls to those of gmtime. Could it be that we missed some corner cases? Sure. But your "if tm_gmtoff or tm_zone are not available" sounds like complaining that after
del datetime.timezone
the datetime module does not support even the UTC timezone!
Whether or not tm_gmtoff is available depends on C library. The time module documentation says [1]: .. versionchanged:: 3.3 :attr:`tm_gmtoff` and :attr:`tm_zone` attributes are available on platforms with C library supporting the corresponding fields in ``struct tm``. i.e., tm_gmtoff, tm_zone may be absent on some platforms. How is it similar to *del datetime.timezone* if whether or not the attributes are available depends on platform? I don't see how any system without a historical timezone database may support the attributes and as far as I know C library that is used by python.exe does not use the tz database on Windows. [1] https://docs.python.org/3.4/library/time.html#time.struct_time To make sure that we are talking about the same thing. Here's how I've temporarily disabled the attributes to perform the test. It *emulates* platforms with one or both attributes missing: diff --git a/Lib/datetime.py b/Lib/datetime.py --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -1507,6 +1507,7 @@ local = datetime(*localtm[:6]) try: # Extract TZ data if available + raise AttributeError gmtoff = localtm.tm_gmtoff zone = localtm.tm_zone except AttributeError: @@ -2129,7 +2130,7 @@ # pretty bizarre, and a tzinfo subclass can override fromutc() if it is. try: - from _datetime import * + from __datetime import * except ImportError: pass else: 1st line forces AttributeError exception handler to execute. 2nd line disables C code that looks identical to the pure Python code. And here's the code from the except AttributeError clause above that I've shown in earlier messages [2] (C code does the same [3]): # 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) note: as the example with datetime(2013, 10, 28, tzinfo=timezone.utc).astimezone().strftime('%Z%z') in TZ=Europe/Moscow demonstrates, this code [4] does not find the correct tz.tzname() and therefore it is not an appropriate replacement for *tm_zone*. The code [4] can't be fixed without data from the tz database. [2] https://mail.python.org/pipermail/datetime-sig/2015-August/000471.html [3] https://github.com/python/cpython/blob/fced0e12fc510e4a6158628695774ccfd0239... [4] https://github.com/python/cpython/blob/fced0e12fc510e4a6158628695774ccfd0239...
On Aug 25, 2015, at 9:20 PM, Akira Li <4kir4.1i@gmail.com> wrote:
The code [4] can't be fixed without data from the tz database.
.. or a working tm_zone/tm_gmtoff extension. Ok, I'll give you that even thought I thought we had some good enough work-around at least for the offset part. What does this all have to do with PEP 495? If you are just saying that it does not solve all problems related to dealing with time zones in Python - I will be first to agree with you. It solves only one problem: it enables tzinfo providers to achieve lossless conversion between time zones with varying utcoffset. That's all. If you are saying that PEP 495 is not needed if all your time zones have fixed utcoffset - again no disagreement here. If you say that lossless conversion between varying utcoffset timezones should not be supported at all - I think you will find yourself in a small minority.
Alexander Belopolsky
On Aug 25, 2015, at 9:20 PM, Akira Li <4kir4.1i@gmail.com> wrote:
The code [4] can't be fixed without data from the tz database.
.. or a working tm_zone/tm_gmtoff extension. Ok, I'll give you that even thought I thought we had some good enough work-around at least for the offset part.
What does this all have to do with PEP 495? If you are just saying that it does not solve all problems related to dealing with time zones in Python - I will be first to agree with you. It solves only one problem: it enables tzinfo providers to achieve lossless conversion between time zones with varying utcoffset. That's all.
I've described _in detail_ [1] what the connection between the datetime.astimezone() failure and PEP-495 is. Here are some takeaways: - History shows that the current datetime API is at least partially responsible [for] that the only working solution (pytz) has more complicated [then necessary] API. *It works but it might have been simpler and less error-prone* - The important part is that PEP-495 should not make it even more difficult to use the packages [pytz, dateutil] correctly - Ideally, PEP-495 should evolve with the corresponding experimental implementations [of the packages] that adapt the new flag.
If you are saying that PEP 495 is not needed if all your time zones have fixed utcoffset - again no disagreement here.
If you say that lossless conversion between varying utcoffset timezones should not be supported at all - I think you will find yourself in a small minority.
I don't understand what you mean but If we are choosing minorities then I'm in this one [2]: This database (often called zoneinfo or tz) is used by several implementations, including the GNU C Library (used in GNU/Linux), Android, Firefox OS, FreeBSD, NetBSD, OpenBSD, Cygwin, DJGPP, MINIX, webOS, AIX, BlackBerry 10, iOS, Microsoft Windows, OpenVMS, Oracle Database, Oracle Solaris, and OS X. Do you mean "varying utcoffset timezones" like dateutil's tzinfo object? I've explicitly mentioned dateutil in "What are examples of timezone-related issues that PEP-495 could solve?" section [1]. It is one of those cases where it is very easy to support 98.9%. The difference and the vast majority of the work is in 1.1%. Until the PEP-495 disambiguation flag is fully integrated in pytz, dateutil; it is hard to tell whether it is worth it or it is even harmful in the end. It seems you use timezone to mean a tzinfo instance. When we are discussing the implementation of packages that provide access to the tz database, let's use the term _time zone_ as it is understood there [3,5]: Within the tz database, a time zone is any national region where local clocks have all agreed since 1970 The typical timezone id is AREA/LOCATION such as America/New_York. It is worth keeping an eye on the necessary enhancements mentioned by Tim Peters [6] and how they may interact with PEP-495. [1] https://mail.python.org/pipermail/datetime-sig/2015-August/000506.html [2] https://www.iana.org/time-zones/repository/tz-link.html [3] https://en.wikipedia.org/wiki/Tz_database [4] https://github.com/python/cpython/blob/fced0e12fc510e4a6158628695774ccfd0239... [5] https://github.com/eggert/tz/blob/2fba5e1535bfada66d99a44c558c4d0dc3371135/T... [6] https://mail.python.org/pipermail/datetime-sig/2015-August/000411.html
participants (2)
-
Akira Li
-
Alexander Belopolsky