[Python-Dev] Add aware local time support to datetime module
alexander.belopolsky at gmail.com
Wed Aug 4 19:46:52 CEST 2010
[I've got no response from python-ideas, so I am forwarding to python-dev.]
With addition of fixed offset timezone class and the timezone.utc
instance , it is easy to get UTC time as an aware datetime
datetime.datetime(2010, 8, 3, 14, 16, 10, 670308, tzinfo=datetime.timezone.utc)
However, if you want to keep time in your local timezone, getting an
aware datetime is almost a catch 22. If you know your timezone UTC
offset, you can do
>>> EDT = timezone(timedelta(hours=-4))
datetime.datetime(2010, 8, 3, 10, 20, 23, 769537,
but the problem is that there is no obvious or even correct way to
find local timezone UTC offset. 
In a comment on issue #5094 ("datetime lacks concrete tzinfo
implementation for UTC"), I proposed to address this problem in a
localtime([t]) function that would return current time (or time
corresponding to the optional datetime argument) as an aware datetime
object carrying local timezone information in a tzinfo set to an
appropriate timezone instance. This solution is attractive by its
simplicity, but there are several problems:
1. An aware datetime cannot carry all information that system
localtime() supplies in a time tuple. Specifically, the is_dst flag
is lost. This is not a problem for most applications as long as
timezone UTC offset and timezone name are available, but may be an
issue when interoperability with the time module is required.
2. Datetime's tzinfo interface was designed with the idea that
<2010-11-06 12:00 EDT> + <1 day> = <2010-11-07 12:00 EST>, not
<2010-11-07 12:00 EDT>. It other words, if I have lunch with someone
at noon (12:00 EDT) on Saturday the day before first Sunday in
November, and want to meet again "at the same time tomorrow", I mean
12:00 EST, not 24 hours later. With localtime() returning datetime
with tzinfo set to fixed offset timezone, however, localtime() +
timedelta(1) will mean exactly 24 hours later and the result will be
expressed in an unusual for the given location timezone.
An alternative approach is the one recommended in the python manual.
 One could implement a LocalTimezone class with utcoffset(),
tzname() and dst() extracting information from system mktime and
localtime calls. This approach has its own shortcomings:
1. While adding integral number of days to datetimes in business
setting, it is natural to expect automatic timezone adjustments, it is
not as clearcut when adding hours or minutes.
2. The tzinfo.utcoffset() interface that expects *standard* local time
as an argument is confusing to many users. Even the "official"
example in the python manual gets it wrong. 
3. datetime(..., tzinfo=LocalTimezone()) is ambiguous during the
"repeated hour" when local clock is set back in DST to standard time
As far as I can tell, the only way to resolve the last problem is to
add is_dst flag to the datetime object, which would also be the
only way to achieve full interoperability between datetime objects and
time tuples. 
The traditional answer to call for improvement of timezone support in
datetime module has been: "this is upto 3rd parties to implement."
Unfortunately, stdlib is asking 3rd parties to implement an impossible
interface without giving access to the necessary data. The
impossibility comes from the requirement that dst() method should find
out whether local time represents DST or standard time while there is
an hour each year when the same local time can be either. The missing
data is the system UTC offset when it changes historically. The time
module only gives access to the current UTC offset.
My preference is to implement the first alternative - localtime([t])
returning aware datetime with fixed offset timezone. This will solve
the problem of python's lack of access to the universally available
system facilities that are necessary to implement any kind of aware
local time support.
More information about the Python-Dev