I'm parsing the National Weather Service alerts feed into a web application. I'd like to purge the alerts when they hit their expiration time. I'd also like to display the expiration time in the local time format for the geographic area they pertain to.
The alerts cover the whole US, so I think the best approach is to store and compare the times in UTC timestamps. The expiration time arrives in the feed as a string like this: 2011-09-09T22:12:00-04:00
.
I'm using the Labix dateutils package to parse the string in a timezone-aware manner:
>>> from dateutil.parser import parse
>>> d = parse("2011-09-18T15:52:00-04:00")
>>> d
datetime.datetime(2011, 9, 18, 15, 52, tzinfo=tzoffset(None, -14400))
I'm also able to capture the UTC offset in hours:
>>> offset_hours = (d.utcoffset().days * 86400 + d.utcoffset().seconds) / 3600
>>> offset_hours
-4
Using the datetime.utctimetuple()
and time.mktime()
methods, I'm able to convert the parsed date to a UTC timestamp:
>>> import time
>>> expiration_utc_ts = time.mktime(d.utctimetuple())
>>> expiration_utc_ts
1316393520.0
At this point, I feel pretty good that I'm able to convert the raw strings into a timestamp representing the expiration time in UTC. I'm able to compare the current time as a UTC timestamp to the expiration and determine if it needs to be purged:
>>> now_utc_ts = time.mktime(time.gmtime())
>>> now_utc_ts
1316398744.0
>>> now_utc_ts >= expiration_tc_ts
True
The difficulty I'm having is trying to convert my stored UTC timestamp back to the original localized format. I have the offset hours stored from the original conversion and a string I parsed to store the timezone label:
>>> print offset_hours
-4
>>> print timezone
EDT
I'd like to convert the UTC timestamp back to a locally formatted time, but converting it back to a datetime
doesn't seem to be working:
>>> import datetime
>>> datetime.datetime.fromtimestamp(expiration_utc_ts) + datetime.timedelta(hours=offset_hours)
datetime.datetime(2011, 9, 18, 16, 52) # The hour is 16 but it should be 15
It looks like it's off by an hour. I'm not sure where the error was introduced? I put together another test and got similar results:
>>> # Running this at 21:29pm EDT
>>> utc_now = datetime.datetime.utcnow()
>>> utc_now_ts = time.mktime(right_now.utctimetuple())
>>> datetime.datetime.fromtimestamp(utc_now_ts)
datetime.datetime(2011, 9, 18, 22, 29, 47) # Off by 1 hour
Can someone help me find my mistake? I'm not sure if it's a daylight savings issue? I came across some stuff that leads me to believe it might be trying to localize my dates and times but at this point I'm pretty stumped. I was hoping to do all of these calculations/comparisons in a timezone-agnostic manner.