In the previous entry, we talked about the difficultly in finding out the delta from UTC for a timezone returned from the pytz module. In particular, consider the offset for St. John’s, Newfoundland which should be at -3:30.
dt_now = datetime.datetime.now()
tz = pytz.timezone('America/St_Johns')
offset = tz.utcoffset(dt_now)
Log(
"using datetime.utcoffset",
offset = format(offset),
)
With the unexpected result:
message: using datetime.utcoffset offset: -4:29 (-12660)
I did a fair bit of Google searching for an answer without finding a satisfactory result, so I did further research on my own. To find the correct offset value, I found that this works:
dt_sj = tz.localize(dt_now)
offset = dt_sj - pytz.UTC.localize(dt_now)
Log(
"using delta to UTC",
offset = format(offset),
)
Which yields the correct:
message: using delta to UTC offset: 03:30 (12600)
Note that if you’re going to use the above method for finding deltas, you’re going to have to take Daylight Savings Time into consideration also. I have not done this here, as I’m a little pressed for time and just want to illustrate the problem.
The issue seems to be with the way that pytz uses the Olson database entry (from here) for St. John’s – and all other locations. It appears that pytz is using the first rule it sees, from 1884, rather than the rule for the date that was passed in. I think this is a bug.
#
# St John's has an apostrophe, but Posix file names can't have apostrophes.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/St_Johns -3:30:52 - LMT 1884
-3:30:52 StJohns N%sT 1918
-3:30:52 Canada N%sT 1919
-3:30:52 StJohns N%sT 1935 Mar 30
-3:30 StJohns N%sT 1942 May 11
-3:30 Canada N%sT 1946
-3:30 StJohns N%sT
The setup code for the examples above is:
from bm_log import Log
import dateutil.parser
import pytz
import datetime
def format(td):
seconds = td.seconds + td.days * ( 24 * 3600 )
return "%02d:%02d (%s)" % ( seconds // 3600, seconds % 3600 // 60, seconds, )
Update 2010-03-09: This has been fixed in the code base and (presumably) will be in the next upcoming release.
Is your system’s timezone set to UTC? If not, you will want to specify the timezone for the now() method. E.g.
dt_now = datetime.datetime.now(pytz.utc)
Sorry, my previous comment was nonsensical. Haven’t had the morning coffee yet.