From 1a6a86df9375e9c884e60b6fd5c8d3ec92a40a71 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Tue, 11 Dec 2012 15:28:45 -0500 Subject: [PATCH] PEP 431: Time zone support improvements (By Lennart Regebro, with very minor formatting by Barry.) --- pep-0431.txt | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 pep-0431.txt diff --git a/pep-0431.txt b/pep-0431.txt new file mode 100644 index 000000000..ad422c809 --- /dev/null +++ b/pep-0431.txt @@ -0,0 +1,261 @@ +PEP: 431 +Title: Time zone support improvements +Version: $Revision$ +Last-Modified: $Date$ +Author: Lennart Regebro +BDFL-Delegate: Barry Warsaw +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 11-Dec-2012 +Post-History: 11-Dec-2012 + + +Abstract +======== + +This PEP proposes the implementation of concrete time zone support in the +Python standard library, and also improvements to the time zone API to deal +with ambiguous time specifications during DST changes. + + +Proposal +======== + +Concrete time zone support +-------------------------- + +The time zone support in Python has no concrete implementation in the +standard library, only a tzinfo baseclass, and since Python 3.2, one concrete +time zone: UTC. To properly support time zones you need to include a database +over all time zones, both current and historical, including daylight saving +changes. But such information changes frequently, so even if we include the +last information in a Python release, that information would be outdated just +a few months later. + +Timezone support has therefore only been available through two third-party +modules, ``pytz`` and ``dateutil``, both who include and wrap the "zoneinfo" +database. This database, also called "tz" or "The Olsen database", is the +de-facto standard time zone database over time zones, and it is included in +most variants of Unix operating systems, including OS X. + +This gives us the opportunity to include only the code that supports the +zoneinfo data in the standard library, but by default use the operating +systems copy of the data, which typically will be kept updated by the +updating mechanism of the operating system or distribution. + +For those who have an operating system that does not include the tz database, +for example Windows, a distribution containing the latest tz database should +also be available at the Python Package Index, so it can be easily installed +with the Python packaging tools such as ``easy_install`` or ``pip``. This +could also be done on Unices that are no longer recieving updates and +therefore has an outdated database. + +With such a mechanism Python would have full time zone support in the +standard library on most platforms, and a simple package installation would +provide time zone support on those platforms where the tz database isn't +included, such as Windows. + +The time zone support will be implemented by a new module called `timezone``, +based on Stuart Bishop's ``pytz`` module. + + +Getting the local time zone +--------------------------- + +On Unix there is no standard way of finding the name of the time zone that is +being used. All the information that is available is the time zone +abbreviations, such as ``EST`` and ``PDT``, but many of those abbreviations +are ambigious and therefore you can't rely on them to figure out which time +zone you are located in. + +There is however a standard for finding the compiled time zone information +since it's located in ``/etc/localtime``. Therefore it is possible to create +a local time zone object with the correct time zone information even though +you don't know the name of the time zone. A function in ``datetime`` should +be provided to return the local time zone. + +The support for this will be made by integrating Lennart Regebro's +``tzlocal`` module into the new ``timezone`` module. + + +Ambiguous times +--------------- + +When changing over from daylight savings time the clock is turned back one +hour. This means that the times during that hour happens twice, once without +DST and then once with DST. Similarily, when changing to daylight savings +time, one hour goes missing. + +The current time zone API can not differentiating between the two ambiguous +times during a change from DST. For example, in Stockholm the time of +2012-11-28 02:00:00 happens twice, both at UTC 2012-11-28 00:00:00 and also +at 2012-11-28 01:00:00. + +The current time zone API can not disambiguate this and therefore it's +unclear which time should be returned:: + + # This could be either 00:00 or 01:00 UTC: + >>> dt = datetime(2012, 11, 28, 2, 0, tzinfo=timezone('Europe/Stockholm')) + # But we can not specify which: + >>> dt.astimezone(timezone('UTC')) + datetime.datetime(2012, 11, 28, 1, 0, tzinfo=) + +``pytz`` solved this problem by adding ``is_dst`` parameters to several +methods of the tzinfo objects to make it possible to disambiguate times when +this is desired. + +This PEP proposes to add these ``is_dst`` parameters to the relevant methods +of the ``datetime`` API, and therefore add this functionality directly to +``datetime``. This is likely the hardest part of this PEP as this involves +updating the + + +Implementation API +================== + +The new ``timezone``-module +--------------------------- + +The public API of the new ``timezone``-module contains one new class, one new +function and one new exception. + +* New class: ``DstTzInfo`` + + This class provides a concrete implementation of the ``zoneinfo`` base + class that implements DST support. + + +* New function :``get_timezone(name=None, db=None)`` + + This function takes a name string that must be a string specifying a + valid zoneinfo timezone, ie "US/Eastern", "Europe/Warsaw" or "Etc/GMT+11". + If not given, the local timezone will be looked up. If an invalid zone name + are given, or the local timezone can not be retrieved, the function raises + `UnknownTimeZoneError`. + + The function also takes an optional path to the location of the zoneinfo + database which should be used. If not specified, the function will check if + the `timezonedata` module is installed, and then use that location or + otherwise use the database in ``/usr/share/zoneinfo``. + + If no database is found an ``UnknownTimeZoneError`` or subclass thereof will + be raised with a message explaining that no zoneinfo database can be found, + but that you can install one with the ``timezonedata`` package. + +* New Exception: ``UnknownTimeZoneError`` + + This exception is raised when giving a time zone specification that can't be + found:: + + >>> datetime.Timezone('Europe/New_York') + Traceback (most recent call last): + ... + UnknownTimeZoneError: There is no time zone called 'Europe/New_York' + + +Changes in the ``datetime``-module +-------------------------------------- + +A new ``is_dst`` parameter is added to several of the `tzinfo` methods to +handle time ambiguity during DST changeovers. + +* ``tzinfo.utcoffset(self, dt, is_dst=True)`` + +* ``tzinfo.dst(self, dt, is_dst=True)`` + +* ``tzinfo.tzname(self, dt, is_dst=True)`` + +The ``is_dst`` parameter can be ``True`` (default), ``False``, or ``None``. + +``True`` will specify that the given datetime should be interpreted as +happening during daylight savings time, ie that the time specified is before +the change from DST. + +``False`` will specify that the given datetime should be interpreted as not +happening during daylight savings time, ie that the time specified is after +the change from DST. + +``None`` will raise an ``AmbiguousTimeError`` exception if the time specified +was during a DST change over. It will also raise a ``NonExistentTimeError`` +if a time is specified during the "missing time" in a change to DST. + +There are also two new exceptions: + +* ``AmbiguousTimeError`` + + This exception is raised when giving a datetime specification that are + ambigious while setting ``is_dst`` to None:: + + >>> datetime(2012, 11, 28, 2, 0, tzinfo=timezone('Europe/Stockholm'), is_dst=None) + >>> + Traceback (most recent call last): + ... + AmbiguousTimeError: 2012-10-28 02:00:00 is ambiguous in time zone Europe/Stockholm + + +* ``NonExistentTimeError`` + + This exception is raised when giving a datetime specification that are + ambigious while setting ``is_dst`` to None:: + + >>> datetime(2012, 3, 25, 2, 0, tzinfo=timezone('Europe/Stockholm'), is_dst=None) + >>> + Traceback (most recent call last): + ... + NonExistentTimeError: 2012-03-25 02:00:00 does not exist in time zone Europe/Stockholm + + +The ``timezonedata``-package +----------------------------- + +The zoneinfo database will be packaged for easy installation with +``easy_install``/``pip``/``buildout``. This package will not install any +Python code, and will not contain any Python code except that which is needed +for installation. + + +Differences from the ``pytz`` API +================================= + +* ``pytz`` has the functions ``localize()`` and ``normalize()`` to work + around that ``tzinfo`` doesn't have is_dst. When ``is_dst`` is + implemented directly in ``datetime.tzinfo`` they are no longer needed. + +* The ``pytz`` method ``timezone()`` is instead called ``get_timezone()`` for + clarity. + +* ``get_timezone()`` will return the local time zone if called without + parameters. + +* The class ``pytz.StaticTzInfo`` is there to provide the ``is_dst`` support + for static timezones. When ``is_dst`` support is included in + ``datetime.tzinfo`` it is no longer needed. + + +Discussion +========== + +Should the windows installer include the data package? +------------------------------------------------------ + +It has been suggested that the Windows installer should include the data +package. This would mean that an explicit installation no longer would be +needed on Windows. On the other hand, that would mean that many using Windows +would not be aware that the database quickly becomes outdated and would not +keep it updated. + + +Resources +========= + +* http://pytz.sourceforge.net/ + +* http://pypi.python.org/pypi/tzlocal + +* http://pypi.python.org/pypi/python-dateutil + +Copyright +========= + +This document has been placed in the public domain.