2015-08-02 16:58:27 -04:00
|
|
|
PEP: 495
|
|
|
|
Title: Local Time Disambiguation
|
|
|
|
Version: $Revision$
|
|
|
|
Last-Modified: $Date$
|
|
|
|
Author: Alexander Belopolsky <alexander.belopolsky@gmail.com>
|
|
|
|
Discussions-To: Datetime-SIG <datetime-sig@python.org>
|
|
|
|
Status: Draft
|
|
|
|
Type: Standards Track
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
Created: 02-Aug-2015
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
========
|
|
|
|
|
|
|
|
This PEP adds a boolean member to the instances of ``datetime.time``
|
|
|
|
and ``datetime.datetime`` classes that can be used to differentiate
|
|
|
|
between two moments in time for which local times are the same.
|
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
.. sidebar:: US public service advertisement
|
|
|
|
|
|
|
|
.. image:: pep-0495-daylightsavings.png
|
|
|
|
:align: right
|
|
|
|
:width: 15%
|
|
|
|
|
|
|
|
|
2015-08-02 16:58:27 -04:00
|
|
|
Rationale
|
|
|
|
=========
|
|
|
|
|
|
|
|
In the most world locations there have been and will be times when
|
|
|
|
local clocks are moved back. In those times intervals are introduced
|
|
|
|
in which local clocks show the same time twice in the same day. In
|
|
|
|
these situations, the information displayed on a local clock (or
|
|
|
|
stored in a Python datetime instance) is insufficient to identify a
|
|
|
|
particular moment in time. The proposed solution is to add a boolean
|
|
|
|
flag to the ``datetime`` instances that will distinguish between the
|
|
|
|
two ambiguous times.
|
|
|
|
|
|
|
|
Proposal
|
|
|
|
========
|
|
|
|
|
|
|
|
The "first" flag
|
|
|
|
----------------
|
|
|
|
|
|
|
|
We propose adding a boolean member called ``first`` to the instances
|
|
|
|
of ``datetime.time`` and ``datetime.datetime`` classes. This member
|
|
|
|
should have the value True for all instances except those that
|
|
|
|
represent the second (chronologically) moment in time in an ambiguous
|
|
|
|
case.
|
|
|
|
|
|
|
|
Affected APIs
|
|
|
|
-------------
|
|
|
|
|
|
|
|
Attributes
|
|
|
|
..........
|
|
|
|
|
|
|
|
Instances of ``datetime.time`` and ``datetime.datetime`` will get a
|
|
|
|
new boolean attribute called "first."
|
|
|
|
|
|
|
|
Constructors
|
|
|
|
............
|
|
|
|
|
|
|
|
The ``__new__`` methods of the ``datetime.time`` and
|
|
|
|
``datetime.datetime`` classes will get a new keyword-only argument
|
|
|
|
called ``first`` with the default value ``True``. The value of the
|
|
|
|
``first`` argument will be used to initialize the value of the
|
|
|
|
``first`` attribute in the returned instance.
|
|
|
|
|
|
|
|
Methods
|
|
|
|
.......
|
|
|
|
|
|
|
|
The ``replace()`` methods of the ``datetime.time`` and
|
|
|
|
``datetime.datetime`` classes will get a new keyword-only argument
|
|
|
|
called ``first`` with the default value ``True``. The value of the
|
|
|
|
``first`` argument will be used to set the value of the ``first``
|
|
|
|
attribute in the returned instance.
|
|
|
|
|
|
|
|
Affected Behaviors
|
|
|
|
------------------
|
|
|
|
|
|
|
|
The ``timestamp()`` method of ``datetime.datetime`` will return value
|
|
|
|
advanced by 3600 if ``self`` represents an ambiguous hour and
|
|
|
|
``first`` is False.
|
|
|
|
|
|
|
|
The ``fromtimestamp()`` static method of ``datetime.datetime`` will
|
|
|
|
set the ``first`` attribute appropriately in the returned object.
|
|
|
|
|
|
|
|
|
|
|
|
Implementations of tzinfo
|
|
|
|
.........................
|
|
|
|
|
|
|
|
Subclasses of ``datetime.tzinfo`` will read the values of ``first`` in
|
|
|
|
``utcoffset()`` and ``dst()`` methods and set it appropriately in the
|
|
|
|
instances returned by the ``fromutc()`` method. No change to the
|
|
|
|
signatures of these methods is proposed.
|
|
|
|
|
|
|
|
Pickle size
|
|
|
|
-----------
|
|
|
|
|
|
|
|
Pickle sizes for the ``datetime.datetime`` and ``datetime.time``
|
|
|
|
objects will not change. The ``first`` flag will be encoded in the
|
|
|
|
first bit of the 5th byte of the ``datetime.datetime`` pickle payload
|
|
|
|
or the 2nd byte of the datetime.time. In the `current implementation`_
|
|
|
|
these bytes are used to store minute value (0-59) and the first bit is
|
|
|
|
always 0. Note that ``first=True`` will be encoded as 0 in the first
|
|
|
|
bit and ``first=False`` as 1. (This change only affects pickle
|
|
|
|
format. In C implementation, the "first" member will get a full byte
|
|
|
|
to store the actual boolean value.)
|
|
|
|
|
|
|
|
We chose the minute byte to store the the "first" bit because this
|
|
|
|
choice preserves the natural ordering.
|
|
|
|
|
|
|
|
.. _current implementation: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17
|
|
|
|
|
|
|
|
Temporal Arithmetics
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
The value of "first" will be ignored in all operations except those
|
|
|
|
that involve conversion between timezones.
|
|
|
|
|
|
|
|
The result of addition (subtraction) of a timedelta to (from) a
|
|
|
|
datetime will always have ``first`` set to ``True`` even if the
|
|
|
|
original datetime instance had ``first=False``.
|
|
|
|
|
|
|
|
(The only methods that will be able to produce non-default value of
|
|
|
|
"first" are ``__new__``, and ``replace()`` methods of the
|
|
|
|
``datetime.datetime`` and ``datetime.time`` classes ``now()`` and
|
|
|
|
``fromtimestamp()`` methods of the ``datetime.datetime`` class, and
|
|
|
|
``fromutc()`` method of some tzinfo implementations.)
|
|
|
|
|
|
|
|
Comparison
|
|
|
|
----------
|
|
|
|
|
|
|
|
Instances of ``datetime.time`` and ``datetime.datetime`` classes that
|
|
|
|
differ only by the value of their ``first`` attribute will compare as
|
|
|
|
equal.
|
|
|
|
|
|
|
|
|
|
|
|
Backward and Forward Compatibility
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
This proposal will have no effect on the programs that do not set the
|
|
|
|
``first`` flag explicitly or use tzinfo implementations that do.
|
|
|
|
Pickles produced by older programs will remain fully forward
|
|
|
|
compatible. Only datetime/time instances with ``first=False`` pickled
|
|
|
|
in the new versions will become unreadable by the older Python
|
|
|
|
versions. Pickles of instances with ``first=True`` (which is the
|
|
|
|
default) will remain unchanged.
|
|
|
|
|
|
|
|
Questions and Answers
|
|
|
|
=====================
|
|
|
|
|
|
|
|
1. Why not call the new flag "isdst"?
|
|
|
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
* Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow!
|
2015-08-02 23:44:22 -04:00
|
|
|
* Bob: Should I presume initially that summer time (for example, Daylight
|
|
|
|
Saving Time) is or is not (respectively) in effect for the specified time?
|
2015-08-02 16:58:27 -04:00
|
|
|
* Alice: Huh?
|
|
|
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
* Bob: Alice - let's have a stargazing party at 01:30 AM tomorrow!
|
|
|
|
* Alice: You know, Bob, 01:30 AM will happen twice tomorrow. Which time do you have in mind?
|
|
|
|
* Bob: I did not think about it, but let's pick the first.
|
|
|
|
|
|
|
|
|
|
|
|
2. Why "first"?
|
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
* Rejections:
|
|
|
|
|
|
|
|
**second**
|
|
|
|
rejected because "second" is already there.
|
2015-08-02 16:58:27 -04:00
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
**later**
|
|
|
|
rejected because "later" is confusable with "latter".
|
2015-08-02 16:58:27 -04:00
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
**earlier**
|
|
|
|
rejected because "earlier" has the same issue as "first" (requires
|
|
|
|
default to be True) but is two characters longer.
|
2015-08-02 16:58:27 -04:00
|
|
|
|
2015-08-02 23:44:22 -04:00
|
|
|
* Remaining possibilities:
|
2015-08-02 16:58:27 -04:00
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
**repeated**
|
|
|
|
this is a strong candidate
|
2015-08-02 16:58:27 -04:00
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
**is_first**
|
|
|
|
arguably more grammatically correct than "first"
|
2015-08-02 16:58:27 -04:00
|
|
|
|
2015-08-04 10:10:01 -04:00
|
|
|
**ltdf**
|
|
|
|
(Local Time Disambiguation Flag) - short and no-one will
|
|
|
|
attempt to guess what it means without reading the docs.
|
2015-08-02 16:58:27 -04:00
|
|
|
|
|
|
|
Implementation
|
|
|
|
==============
|
|
|
|
|
2015-08-02 23:44:22 -04:00
|
|
|
* Github fork: https://github.com/abalkin/cpython
|
|
|
|
* Tracker issue: http://bugs.python.org/issue24773
|
2015-08-02 16:58:27 -04:00
|
|
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
=========
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
Picture Credit
|
|
|
|
==============
|
|
|
|
|
|
|
|
This image is a work of a U.S. military or Department of Defense
|
|
|
|
employee, taken or made as part of that person's official duties. As a
|
|
|
|
work of the U.S. federal government, the image is in the public
|
|
|
|
domain.
|