Re: Daylight savings time question
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
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
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
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
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
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
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