python-peps/pep-0431.txt

263 lines
9.4 KiB
Plaintext
Raw Normal View History

PEP: 431
Title: Time zone support improvements
Version: $Revision$
Last-Modified: $Date$
Author: Lennart Regebro <regebro@gmail.com>
BDFL-Delegate: Barry Warsaw <barry@python.org>
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
2013-01-01 20:10:54 -05:00
could also be done on Unices that are no longer receiving updates and
therefore have 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
2013-01-01 20:10:54 -05:00
are ambiguous 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 (DST) the clock is turned back one
hour. This means that the times during that hour happens twice, once without
2013-01-01 20:10:54 -05:00
DST and then once with DST. Similarly, when changing to daylight savings
time, one hour goes missing.
The current time zone API can not differentiate 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=<UTC>)
``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
2013-01-01 20:10:54 -05:00
valid zoneinfo timezone, i.e. "US/Eastern", "Europe/Warsaw" or "Etc/GMT+11".
If not given, the local timezone will be looked up. If an invalid zone name
is 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
2013-01-01 20:10:54 -05:00
happening during daylight savings time, i.e. that the time specified is before
the change from DST.
``False`` will specify that the given datetime should be interpreted as not
2013-01-01 20:10:54 -05:00
happening during daylight savings time, i.e. 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 is
2013-01-01 20:10:54 -05:00
ambiguous 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 is
non-existent 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
arguments.
* 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 would no longer 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.