Improving support for timezones in Python (was: UTC timezone causing brain explosions)

2014-01-30 Thread Ben Finney
Ben Finney ben+pyt...@benfinney.id.au writes:

 Time zones are a hairy beast to manage, made all the more difficult
 because national politicians continually fiddle with them which means
 they can't just be a built-in part of the Python standard library.

PyCon 2013 had a good talk on calendaring and timezone issues
URL:http://www.pyvideo.org/video/1765/blame-it-on-caesar-what-you-need-to-know-about-d
(video at URL:https://www.youtube.com/watch?v=GBKqRhn0ekM).

The speaker, Lennart Regebro, maintains a library for getting the local
timezone URL:https://pypi.python.org/pypi/tzlocal, and is currently
working on a PEP to improve timezone support directly in the standard
library URL:http://www.python.org/dev/peps/pep-0431/.

He also reinforces the message that UTC is the canonical timezone for
storing and manipulating timestamp values, and we should be converting
to/from those canonical values as early/late as possible in our programs.

-- 
 \ “Reality must take precedence over public relations, for nature |
  `\cannot be fooled.” —Richard P. Feynman |
_o__)  |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Improving support for timezones in Python (was: UTC timezone causing brain explosions)

2014-01-30 Thread Chris Angelico
On Fri, Jan 31, 2014 at 1:26 PM, Ben Finney ben+pyt...@benfinney.id.au wrote:
 He also reinforces the message that UTC is the canonical timezone for
 storing and manipulating timestamp values, and we should be converting
 to/from those canonical values as early/late as possible in our programs.

Call it a UTC Sandwich, like Ned Batchelder's Unicode Sandwich.
It's a good idea for the same reason.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


UTC timezone causing brain explosions

2014-01-29 Thread Skip Montanaro
Following up on my earlier note about UTC v. GMT, I am having some
trouble grokking attempts to convert a datetime into UTC. Consider
these three values:

 import pytz
 UTC = pytz.timezone(UTC)
 UTC
UTC
 LOCAL_TZ = pytz.timezone(America/Chicago)
 LOCAL_TZ
DstTzInfo 'America/Chicago' CST-1 day, 18:00:00 STD
 now = datetime.datetime.now()
 now
datetime.datetime(2014, 1, 29, 15, 39, 35, 263666)

All well and good, right? The variable now is a naive datetime
object. I happen to be sitting in a chair in the city of Chicago, so
let's call it what it is, a datetime in the America/Chicago timezone:

 s = LOCAL_TZ.localize(now)
 s
datetime.datetime(2014, 1, 29, 15, 39, 35, 263666, tzinfo=DstTzInfo
'America/Chicago' CST-1 day, 18:00:00 STD)

That looks good to me. Now, let's normalize it to UTC:

 t = UTC.normalize(s)
 t
datetime.datetime(2014, 1, 29, 15, 39, 35, 263666, tzinfo=UTC)
 t.hour
15

WTF? Why isn't the t.hour == 21?

Okay, let's see what GMT does for us:

 GMT = pytz.timezone(GMT)
 u = GMT.normalize(s)
 u
datetime.datetime(2014, 1, 29, 21, 39, 35, 263666, tzinfo=StaticTzInfo 'GMT')
 u.hour
21

That looks correct, but I don't understand why I don't get hour==21
out of the UTC.normalize call. It's like it's a no-op.

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: UTC timezone causing brain explosions

2014-01-29 Thread Ethan Furman

On 01/29/2014 01:52 PM, Skip Montanaro wrote:

Following up on my earlier note about UTC v. GMT, I am having some
trouble grokking attempts to convert a datetime into UTC.

Okay, let's see what GMT does for us:


GMT = pytz.timezone(GMT)
u = GMT.normalize(s)
u

datetime.datetime(2014, 1, 29, 21, 39, 35, 263666, tzinfo=StaticTzInfo 'GMT')

u.hour

21

That looks correct, but I don't understand why I don't get hour==21
out of the UTC.normalize call. It's like it's a no-op.


Having not examined the code, I can't tell you why UTC is different.  I can say 
that .astimezone seems to work in all cases:

-- GMT
StaticTzInfo 'GMT'

-- UTC
UTC

-- LOCAL_TZ = pytz.timezone(America/Los_Angeles)

-- now = datetime.datetime.now()

-- s = LOCAL_TZ.localize(now)
-- s
datetime.datetime(2014, 1, 29, 14, 9, 56, 494967, tzinfo=DstTzInfo 
'America/Los_Angeles' PST-1 day, 16:00:00 STD)

-- s.astimezone(UTC)
datetime.datetime(2014, 1, 29, 22, 9, 56, 494967, tzinfo=UTC)

-- s.astimezone(GMT)
datetime.datetime(2014, 1, 29, 22, 9, 56, 494967, tzinfo=StaticTzInfo 'GMT')

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: UTC timezone causing brain explosions

2014-01-29 Thread Ben Finney
Skip Montanaro s...@pobox.com writes:

 Following up on my earlier note about UTC v. GMT, I am having some
 trouble grokking attempts to convert a datetime into UTC.

For what it's worth, you're not alone. Time zones are a hairy beast to
manage, made all the more difficult because national politicians
continually fiddle with them which means they can't just be a built-in
part of the Python standard library.

 Consider these three values:

  import pytz
  UTC = pytz.timezone(UTC)
  UTC
 UTC
  LOCAL_TZ = pytz.timezone(America/Chicago)
  LOCAL_TZ
 DstTzInfo 'America/Chicago' CST-1 day, 18:00:00 STD
  now = datetime.datetime.now()
  now
 datetime.datetime(2014, 1, 29, 15, 39, 35, 263666)

 All well and good, right?

Not really :-) You avoid the pain if you never create naive datetime
values in the first place.

Instead, specify the timezone for the value you're creating::

 now = datetime.datetime.now(tz=LOCAL_TZ)
 now
datetime.datetime(2014, 1, 29, 16, 35, 7, 900526, tzinfo=DstTzInfo 
'America/Chicago' CST-1 day, 18:00:00 STD)

That way the value will respond correctly to requests to convert it to
whatever timezone you specify::

 MELBOURNE = pytz.timezone(Australia/Melbourne)
 now.astimezone(MELBOURNE)
datetime.datetime(2014, 1, 30, 9, 35, 7, 900526, tzinfo=DstTzInfo 
'Australia/Melbourne' EST+11:00:00 DST)
 now.astimezone(UTC)
datetime.datetime(2014, 1, 29, 22, 35, 7, 900526, tzinfo=UTC)
 now.astimezone(LOCAL_TZ)
datetime.datetime(2014, 1, 29, 16, 35, 7, 900526, tzinfo=DstTzInfo 
'America/Chicago' CST-1 day, 18:00:00 STD)

-- 
 \  “We tend to scoff at the beliefs of the ancients. But we can't |
  `\scoff at them personally, to their faces, and this is what |
_o__) annoys me.” —Jack Handey |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: UTC timezone causing brain explosions

2014-01-29 Thread Chris Rebert
On Wed, Jan 29, 2014 at 1:52 PM, Skip Montanaro s...@pobox.com wrote:
 Following up on my earlier note about UTC v. GMT, I am having some
 trouble grokking attempts to convert a datetime into UTC. Consider
 these three values:

 import pytz
 UTC = pytz.timezone(UTC)
 LOCAL_TZ = pytz.timezone(America/Chicago)
 LOCAL_TZ
 DstTzInfo 'America/Chicago' CST-1 day, 18:00:00 STD
 now = datetime.datetime.now()
 now
 datetime.datetime(2014, 1, 29, 15, 39, 35, 263666)

 All well and good, right? The variable now is a naive datetime
 object. I happen to be sitting in a chair in the city of Chicago, so
 let's call it what it is, a datetime in the America/Chicago timezone:

 s = LOCAL_TZ.localize(now)
 s
 datetime.datetime(2014, 1, 29, 15, 39, 35, 263666, tzinfo=DstTzInfo
 'America/Chicago' CST-1 day, 18:00:00 STD)

 That looks good to me. Now, let's normalize it to UTC:

I don't think .normalize() doesn't do what you think it does; it's
related to timezones with DST.
I believe you want datetime.astimezone() instead.

 t = UTC.normalize(s)
 t
 datetime.datetime(2014, 1, 29, 15, 39, 35, 263666, tzinfo=UTC)
 t.hour
 15

 WTF? Why isn't the t.hour == 21?

Because you didn't actually perform a proper timezone conversion:
 t = s.astimezone(UTC)
 t
datetime.datetime(2014, 1, 29, 21, 39, 35, 263666, tzinfo=UTC)
 t.hour == 21
True

snip
 That looks correct, but I don't understand why I don't get hour==21
 out of the UTC.normalize call. It's like it's a no-op.

It is indeed a no-op:
You can take shortcuts when dealing with the UTC side of timezone
conversions. normalize() and localize() are not really necessary when
there are no daylight savings time transitions to deal with.
-- http://pytz.sourceforge.net

Cheers,
Chris
-- 
https://mail.python.org/mailman/listinfo/python-list