On Thu, Apr 16, 2015 at 1:14 AM, Alexander Belopolsky <
alex...@gmail.com> wrote:
>> On Wed, Apr 15, 2015 at 4:46 PM, Akira Li <4kir...@gmail.com> wrote:>>> > 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.>> >>>>> It looks incorrect. Here's the corresponding pytz code:>>>> from datetime import datetime>> import pytz>>>> tz = pytz.timezone('Europe/Kiev')>> print(tz.localize(datetime(1990, 7, 1, 1, 30),>> is_dst=False).strftime('%c %z %Z'))>> # -> Sun Jul 1 01:30:00 1990 +0300 EEST>> print(tz.localize(datetime(1990, 7, 1, 1, 30),>> is_dst=True).strftime('%c %z %Z'))>> # -> Sun Jul 1 01:30:00 1990 +0400 MSD>>>> See also "Enhance support for end-of-DST-like ambiguous time" [1]>>>> [1] https://bugs.launchpad.net/pytz/+bug/1378150>>>> `email.utils.localtime()` is broken:>>>> If you think there is a bug in email.utils.localtime - please open an> issue at <bugs.python.org>.>>
Your question below suggests that you believe it is not a bug i.e.,
`email.utils.localtime()` is broken *by design* unless you think it is ok
to ignore `+0400 MSD`.
pytz works for me (I can get both `+0300 EEST` and `+0400 MSD`). I don't
think `localtime()` can be fixed without the tz database. I don't know
whether it should be fixed, let somebody else who can't use pytz to pioneer
the issue. The purpose of the code example is to **inform** that
`email.utils.localtime()` fails (it returns only +0300 EEST) in this case:
>> from datetime import datetime>> from email.utils import localtime>>>> print(localtime(datetime(1990, 7, 1, 1, 30)).strftime('%c %z %Z'))>> # -> Sun Jul 1 01:30:00 1990 +0300 EEST>> print(localtime(datetime(1990, 7, 1, 1, 30), isdst=0).strftime('%c %z>> %Z'))>> # -> Sun Jul 1 01:30:00 1990 +0300 EEST>> print(localtime(datetime(1990, 7, 1, 1, 30), isdst=1).strftime('%c %z>> %Z'))>> # -> Sun Jul 1 01:30:00 1990 +0300 EEST>> print(localtime(datetime(1990, 7, 1, 1, 30), isdst=-1).strftime('%c %z>> %Z'))>> # -> Sun Jul 1 01:30:00 1990 +0300 EEST>>>>>> Versions:>>>> $ ./python -V>> Python 3.5.0a3+>> $ dpkg -s tzdata | grep -i version>> Version: 2015b-0ubuntu0.14.04>>>> > 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.>>>> "repeated hour" (time jumps back) can be treated like a end-of-DST>> transition, to resolve ambiguities [1].>>> I don't understand what you are complaining about. It is quite possible> that pytz uses is_dst flag differently from the way email.utils.localtime> uses isdst.>> I was not able to find a good description of what is_dst means in pytz,> but localtime's isdst is documented as follows:>> a positive or zero value for *isdst* causes localtime to> presume initially that summer time (for example, Daylight Saving Time)> is or is not (respectively) in effect for the specified time.>> Can you demonstrate that email.utils.localtime does not behave as> documented?>
No need to be so defensive about it. *""repeated hour" (time jumps back)
can be treated like a end-of-DST transition, to resolve ambiguities [1]."*
is just a *an example* on how to fix the problem in the same way how it is
done in pytz:
>>> from datetime import datetime>>> import pytz>>> tz = pytz.timezone('Europe/Kiev')>>> after = tz.localize(datetime(1990, 7, 1, 1, 30), is_dst=False)>>> before = tz.localize(datetime(1990, 7, 1, 1, 30), is_dst=True)>>> before < after
True
>>> before
datetime.datetime(1990, 7, 1, 1, 30, tzinfo=<DstTzInfo 'Europe/Kiev'
MSD+4:00:00 DST>)
>>> after
datetime.datetime(1990, 7, 1, 1, 30, tzinfo=<DstTzInfo 'Europe/Kiev'
EEST+3:00:00 DST>)
>>> before.astimezone(pytz.utc)
datetime.datetime(1990, 6, 30, 21, 30, tzinfo=<UTC>)
>>> after.astimezone(pytz.utc)
datetime.datetime(1990, 6, 30, 22, 30, tzinfo=<UTC>)
>>> before.dst()
datetime.timedelta(0, 3600)
>>> after.dst()
datetime.timedelta(0, 3600)
>>> pytz.OLSON_VERSION
'2015b'
Here's "summer time" in both cases i.e., it is not *true* end-of-DST
transition (that is why I've used the word *"like"* above).
If we ignore ambiguous time that may occur more than twice then a boolean
flag such as pytz's is_dst is *always* enough to resolve the ambiguity
assuming we have access to the tz database.
And yes, the example demonstrates that the behavior of pytz's is_dst and
localtime()'s isdst is different. The example just shows that the current
behavior of localtime() doesn't allow to get `+0400 DST` (on my system, see
the software versions above) and how to get it (*adopt* the pytz behavior
-- you need zoneinfo for that) i.e., the message is a problem and a
possible solution -- no complains.
[1] https://bugs.launchpad.net/pytz/+bug/1378150
--
Akira.
_______________________________________________
Python-Dev mailing list
Pyth...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/python-dev-ml%40activestate.com