Re: Daylight savings time question

2015-03-25 Thread Chris Angelico
On Wed, Mar 25, 2015 at 10:18 AM, Carl Meyer c...@oddbird.net wrote:
 US/Pacific is an alias for America/Los_Angeles, and is also part of the
 Olson database (though I guess it's considered an old name for the
 timezone): https://github.com/eggert/tz/blob/master/backward

Ah, okay. No problem then. If it works, it works.

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


Re: Daylight savings time question

2015-03-25 Thread Carl Meyer
Hi Dan,

On 03/24/2015 04:24 PM, Dan Stromberg wrote:
 Is there a way of adding 4 hours and getting a jump of 5 hours on
 March 8th, 2015 (due to Daylight Savings Time), without hardcoding
 when to spring forward and when to fall back?  I'd love it if there's
 some library that'll do this for me.
 
 #!/usr/bin/python
 
 import pytz
 import datetime
 
 def main():
 # On 2015-03-08, 2:00 AM to 2:59AM Pacific time does not exist -
 the clock jumps forward an hour.
 weird_naive_datetime = datetime.datetime(2015, 3, 8, 1, 0,
 0).replace(tzinfo=pytz.timezone('US/Pacific'))
 weird_tz_aware_datetime =
 weird_naive_datetime.replace(tzinfo=pytz.timezone('US/Pacific'))
 print(weird_tz_aware_datetime)
 four_hours=datetime.timedelta(hours=4)
 print('Four hours later is:')
 print(weird_tz_aware_datetime + four_hours)
 print('...but I want numerically 5 hours later, because of
 Daylight Savings Time')
 
 main()

Much like the best advice for handling character encodings is do all
your internal work in unicode, and decode/encode at your input/output
boundaries, the best advice for working with datetimes is do all your
internal work in UTC; convert to UTC from the input timezone and
localize to the output timezone at your input/output boundaries. UTC
has no daylight savings time, so these issues disappear when you do your
calculations in UTC, and then the resulting dates are appropriately
handled by pytz when converting to local timezone at output.

So in this case, the following code gives the correct answer:

naive_dt = datetime.datetime(2015, 3, 8, 1)
tz = pytz.timezone('US/Pacific')
local_dt = tz.localize(naive_dt)
utc_dt = pytz.utc.normalize(local_dt)
four_hours = datetime.timedelta(hours=4)
new_utc_dt = utc_dt + four_hours
new_local_dt = tz.normalize(new_utc_dt)

Someone may point out that you can actually just use pytz.normalize() to
solve this particular problem more directly, without the conversion to
UTC and back:

naive_dt = datetime.datetime(2015, 3, 8, 1)
tz = pytz.timezone('US/Pacific')
local_dt = tz.localize(naive_dt)
four_hours = datetime.timedelta(hours=4)
new_local_dt = tz.normalize(utc_dt + four_hours)

(On the last line here, tz.normalize() is able to see that it's been
given a datetime which claims to be PST, but is after the spring
transition so should actually be PDT, and fixes it for you, correctly
bumping it by an hour in the process.)

While it's true that for this specific case the non-UTC method is more
direct, if you're writing any kind of sizable system that needs to
handle timezones correctly, you'll still be doing yourself a favor by
handling all datetimes in UTC internally.

Also, unless you really know what you're doing, you should generally use

a_pytz_timezone_obj.localize(naive_dt)

to turn a naive datetime into a timezone-aware one, instead of

naive_dt.replace(tzinfo=a_pytz_timezone_obj).

The latter just blindly uses the exact timezone object you give it,
without regard for when the datetime actually is (thus fails to respect
whether the timezone should be in DST or not, or any other historical
local-time transitions), whereas the `localize` method ensures that the
resulting aware datetime actually has the correct version of the
timezone applied to it, given when it is.

You can easily observe this difference, because the default version of
a timezone in pytz is the first one listed in the timezone database,
which for many timezones is LMT (local mean time), a historical timezone
offset abandoned in the late 1800s most places, which is often offset
from modern timezones by odd amounts like seven or eight minutes. For
example:

 import pytz, datetime
 dt = datetime.datetime(2015, 3, 8, 1)
 tz = pytz.timezone('US/Pacific')
 tz
DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD
 bad = dt.replace(tzinfo=tz)
 bad
datetime.datetime(2015, 3, 8, 1, 0, tzinfo=DstTzInfo 'US/Pacific'
LMT-1 day, 16:07:00 STD)
 in_utc = pytz.utc.normalize(bad)
 in_utc
datetime.datetime(2015, 3, 8, 8, 53, tzinfo=UTC)

Note that the timezone assigned to the `bad` datetime is US/Pacific LMT,
which hasn't been in use since Nov 1883 [1] and which is 7 minutes
offset from modern timezones, resulting in a very surprising result when
you then convert that to UTC. In contrast, localize() does the right
thing, using PST instead of LMT because it knows that's the correct
offset for US/Pacific at 1am on March 8, 2015:

 good = tz.localize(dt)
 good
datetime.datetime(2015, 3, 8, 1, 0, tzinfo=DstTzInfo 'US/Pacific'
PST-1 day, 16:00:00 STD)
 in_utc = pytz.utc.normalize(good)
 in_utc
datetime.datetime(2015, 3, 8, 9, 0, tzinfo=UTC)


Carl

 [1] https://github.com/eggert/tz/blob/master/northamerica#L409



signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Daylight savings time question

2015-03-25 Thread Carl Meyer
On 03/24/2015 04:56 PM, Chris Angelico wrote:
 On Wed, Mar 25, 2015 at 9:24 AM, Dan Stromberg drsali...@gmail.com wrote:
 Is there a way of adding 4 hours and getting a jump of 5 hours on
 March 8th, 2015 (due to Daylight Savings Time), without hardcoding
 when to spring forward and when to fall back?  I'd love it if there's
 some library that'll do this for me.
 
 Fundamentally, this requires knowledge of timezone data. That means
 you have to select a political time zone, which basically means you
 want the Olsen database (tzdata)

Yes, which is made available in Python via the pytz package.

 which primarily works with city
 names. I'm not sure whether US/Pacific is suitable; I usually use
 America/Los_Angeles for Pacific US time.

US/Pacific is an alias for America/Los_Angeles, and is also part of the
Olson database (though I guess it's considered an old name for the
timezone): https://github.com/eggert/tz/blob/master/backward

Carl



signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Daylight savings time question

2015-03-25 Thread random832
On Tue, Mar 24, 2015, at 18:24, Dan Stromberg wrote:
 Is there a way of adding 4 hours and getting a jump of 5 hours on
 March 8th, 2015 (due to Daylight Savings Time), without hardcoding
 when to spring forward and when to fall back?  I'd love it if there's
 some library that'll do this for me.

If you're adding an extra four hours to your local time, then your new
offset is going to be -3 hours instead of -7: to do this properly you
would have to define a new timezone.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Daylight savings time question

2015-03-24 Thread Chris Angelico
On Wed, Mar 25, 2015 at 9:24 AM, Dan Stromberg drsali...@gmail.com wrote:
 Is there a way of adding 4 hours and getting a jump of 5 hours on
 March 8th, 2015 (due to Daylight Savings Time), without hardcoding
 when to spring forward and when to fall back?  I'd love it if there's
 some library that'll do this for me.

Fundamentally, this requires knowledge of timezone data. That means
you have to select a political time zone, which basically means you
want the Olsen database (tzdata) which primarily works with city
names. I'm not sure whether US/Pacific is suitable; I usually use
America/Los_Angeles for Pacific US time.

But that aside, what Gary said is what I would recommend.

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


Re: Daylight savings time question

2015-03-24 Thread Gary Herron

On 03/24/2015 03:24 PM, Dan Stromberg wrote:

Is there a way of adding 4 hours and getting a jump of 5 hours on
March 8th, 2015 (due to Daylight Savings Time), without hardcoding
when to spring forward and when to fall back?  I'd love it if there's
some library that'll do this for me.

#!/usr/bin/python

import pytz
import datetime

def main():
 # On 2015-03-08, 2:00 AM to 2:59AM Pacific time does not exist -
the clock jumps forward an hour.
 weird_naive_datetime = datetime.datetime(2015, 3, 8, 1, 0,
0).replace(tzinfo=pytz.timezone('US/Pacific'))
 weird_tz_aware_datetime =
weird_naive_datetime.replace(tzinfo=pytz.timezone('US/Pacific'))
 print(weird_tz_aware_datetime)
 four_hours=datetime.timedelta(hours=4)
 print('Four hours later is:')
 print(weird_tz_aware_datetime + four_hours)
 print('...but I want numerically 5 hours later, because of
Daylight Savings Time')

main()


Thanks!


The pyzt module (which you've imported) has lots to say about this. Look 
at its procedures localize' and 'normalize' and all the rest of the 
pyzt documentation.




--
Dr. Gary Herron
Department of Computer Science
DigiPen Institute of Technology
(425) 895-4418

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


Re: Daylight savings time question

2015-03-24 Thread Dan Stromberg
This appears to do what I wanted:

#!/usr/bin/python

from __future__ import print_function

import pytz
import datetime

# Is there a good way of jumping ahead 5 hours instead of 4 on 2015-03-08?

def main():
# On 2015-03-08, 2:00 AM to 2:59AM Pacific time does not exist -
the clock jumps forward an hour.
us_pacific = pytz.timezone('US/Pacific')

weird_naive_datetime = datetime.datetime(2015, 3, 8, 1, 0, 0)
print('weird_naive_datetime:  ', weird_naive_datetime)

weird_tz_aware_datetime = us_pacific.localize(weird_naive_datetime)
print('weird_tz_aware_datetime', weird_tz_aware_datetime)

four_hours=datetime.timedelta(hours=4)
print('Four hours later is:   ',
us_pacific.normalize(weird_tz_aware_datetime + four_hours))

print('...we want numerically 5 hours later (so 6AM), because of
Daylight Savings Time')

main()


On Tue, Mar 24, 2015 at 3:24 PM, Dan Stromberg drsali...@gmail.com wrote:
 Is there a way of adding 4 hours and getting a jump of 5 hours on
 March 8th, 2015 (due to Daylight Savings Time), without hardcoding
 when to spring forward and when to fall back?  I'd love it if there's
 some library that'll do this for me.

 #!/usr/bin/python

 import pytz
 import datetime

 def main():
 # On 2015-03-08, 2:00 AM to 2:59AM Pacific time does not exist -
 the clock jumps forward an hour.
 weird_naive_datetime = datetime.datetime(2015, 3, 8, 1, 0,
 0).replace(tzinfo=pytz.timezone('US/Pacific'))
 weird_tz_aware_datetime =
 weird_naive_datetime.replace(tzinfo=pytz.timezone('US/Pacific'))
 print(weird_tz_aware_datetime)
 four_hours=datetime.timedelta(hours=4)
 print('Four hours later is:')
 print(weird_tz_aware_datetime + four_hours)
 print('...but I want numerically 5 hours later, because of
 Daylight Savings Time')

 main()


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