[Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones (original) (raw)
Alexander Belopolsky alexander.belopolsky at gmail.com
Fri Apr 10 05:14:10 CEST 2015
- Previous message (by thread): [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones
- Next message (by thread): [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Sorry for a truncated message. Please scroll past the quoted portion.
On Thu, Apr 9, 2015 at 10:21 PM, Alexander Belopolsky < alexander.belopolsky at gmail.com> wrote:
On Thu, Apr 9, 2015 at 4:51 PM, Isaac Schwabacher <ischwabacher at wisc.edu> wrote:
> > > Well, you are right, but at least we do have a localtime utility hidden in the email package: > > > > > > >>> from datetime import * > > > >>> from email.utils import localtime > > > >>> print(localtime(datetime.now())) > > > 2015-04-09 15:19:12.840000-04:00 > > > > > > You can read <http://bugs.python.org/issue9527> for the reasons it did not make into datetime. > > > > But that's restricted to the system time zone. Nothing good ever comes from the system time zone... > > Let's solve one problem at a time. ...
PEP 431 proposes to import zoneinfo into the stdlib, ... I am changing the subject so that we can focus on one question without diverting to PEP-size issues that are better suited for python ideas. I would like to add a functionality to the datetime module that would solve a seemingly simple problem: given a naive datetime instance assumed to be in local time, construct the corresponding aware datetime object with tzinfo set to an appropriate fixed offset datetime.timezone instance. Python 3 has this functionality implemented in the email package since version 3.3, and it appears to work well even in the ambiguous hour >>> from email.utils import localtime >>> from datetime import datetime >>> localtime(datetime(2014,11,2,1,30)).strftime('%c %z %Z') 'Sun Nov 2 01:30:00 2014 -0400 EDT' >>> localtime(datetime(2014,11,2,1,30), isdst=0).strftime('%c %z %Z') 'Sun Nov 2 01:30:00 2014 -0500 EST' However, in a location with a more interesting history, you can get a situation that
would look like this in the zoneinfo database:
$ zdump -v -c 1992 Europe/Kiev ... Europe/Kiev Sat Mar 24 22:59:59 1990 UTC = Sun Mar 25 01:59:59 1990 MSK isdst=0 Europe/Kiev Sat Mar 24 23:00:00 1990 UTC = Sun Mar 25 03:00:00 1990 MSD isdst=1 Europe/Kiev Sat Jun 30 21:59:59 1990 UTC = Sun Jul 1 01:59:59 1990 MSD isdst=1 Europe/Kiev Sat Jun 30 22:00:00 1990 UTC = Sun Jul 1 01:00:00 1990 EEST isdst=1 Europe/Kiev Sat Sep 28 23:59:59 1991 UTC = Sun Sep 29 02:59:59 1991 EEST isdst=1 Europe/Kiev Sun Sep 29 00:00:00 1991 UTC = Sun Sep 29 02:00:00 1991 EET isdst=0 ...
Look what happened on July 1, 1990. At 2 AM, the clocks in Ukraine were moved back one hour. So times like 01:30 AM happened twice there on that day. Let's see how Python handles this situation
$ TZ=Europe/Kiev python3
from email.utils import localtime from datetime import datetime localtime(datetime(1990,7,1,1,30)).strftime('%c %z %Z') 'Sun Jul 1 01:30:00 1990 +0400 MSD'
So far so good, I've got the first of the two 01:30AM's. But what if I want the other 01:30AM? Well,
localtime(datetime(1990,7,1,1,30), isdst=0).strftime('%c %z %Z') 'Sun Jul 1 01:30:00 1990 +0300 EEST'
gives me "the other 01:30AM", but it is counter-intuitive: I have to ask for the standard (winter) time to get the daylight savings (summer) time.
The uncertainty about how to deal with the repeated hour was the reason why email.utils.localtime-like interface did not make it to the datetime module.
The main objection to the isdst flag was that in most situations, determining whether DST is in effect is as hard as finding the UTC offset, so reducing the problem of finding the UTC offset to the one of finding the value for isdst does not solve much.
I now realize that the problem is simply in the name for the flag. While we cannot often tell what isdst should be and in some situations the actual DST status does not differentiate between the two possible times, we can always say whether we want to get the first or the second time.
In other words, instead of localtime(dt, isdst=-1), we may want localtime(dt, which=0) where "which" is used to resolve the ambiguity: "which=0" means return the first (in UTC order) of the two times and "which=1" means return the second. (In the non-ambiguous cases "which" is ignored.)
An alternative solution would be make localtime(dt) return a list of 0, 1 or 2 instances, but this will probably make a common usage (the case when the user does not care which time she gets) more cumbersome. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20150409/a1d3b69f/attachment.html>
- Previous message (by thread): [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones
- Next message (by thread): [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]