python-peps/pep-0495.txt

216 lines
6.5 KiB
Plaintext

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.
.. sidebar:: US public service advertisement
.. image:: pep-0495-daylightsavings.png
:align: right
:width: 15%
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!
* Bob: Should I presume initially that summer time (for example, Daylight
Saving Time) is or is not (respectively) in effect for the specified time?
* 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"?
* Rejections:
**second**
rejected because "second" is already there.
**later**
rejected because "later" is confusable with "latter".
**earlier**
rejected because "earlier" has the same issue as "first" (requires
default to be True) but is two characters longer.
* Remaining possibilities:
**repeated**
this is a strong candidate
**is_first**
arguably more grammatically correct than "first"
**ltdf**
(Local Time Disambiguation Flag) - short and no-one will
attempt to guess what it means without reading the docs.
Implementation
==============
* Github fork: https://github.com/abalkin/cpython
* Tracker issue: http://bugs.python.org/issue24773
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.