Simon Willison: Django vs feedparser on dates. Some useful tips in the comments. I find Python’s timezone stuff endlessly frustrating: I know it can do what I want, but it always takes me a ridiculously long time to figure out the necessary incantations.
My recommendation is to convert to UTC as early as possible, stay in UTC as long as possible, and convert to local time as late as possible — preferably in JavaScript on the client.
>>> import datetime,calendar >>> feedparser_timestamp=(2004, 11, 19, 5, 13, 31, 4, 324, 0) >>> datetime.datetime.utcfromtimestamp(calendar.timegm(feedparser_timestamp)) datetime.datetime(2004, 11, 19, 5, 13, 31)
Hah! I never knew about calendar.timegm() (I love how the documentation admits that it’s an “unrelated but handy function”. That solves the most common problem I’ve been running in to.
I’d love to see that stuff cleaned up for Python 3000.
I respectfully disagree with the advice of storing everything in UTC and convert to local time later. Because conversion to local time requires knowledge of rules of changing to and from daylight saving for a particular locality, and they are hard and tend to change over time.
A simple example. If you store 2007-09-03 15:00 and consider it to be in UTC then to convert it into Moscow time you should know that September 3 is still summer time and add 4 hours, not 3 as for winter times. The hard part is that it depends not on time when program runs when you can get this offset from your OS but on time when the value was stored.
So my advice on preferences for storing times would be as this:
- always store timezone information (in some form) with time values
- in local application store time in local timezone
- in a country-wide application choose one of country’s timezones as base and store an offset from it with time values; it’s better than UTC because inside one country daylight savings are synchronized
- in a global application use UTC and employ some smart up-to-date library that knows rules of daylight savings for every place
If you store 2007-09-03 15:00 and consider it to be in UTC then to convert it into Moscow time you should know that September 3 is still summer time and add 4 hours, not 3 as for winter times. The hard part is that it depends not on time when program runs when you can get this offset from your OS but on time when the value was stored.
>>> import os,time,calendar >>> os.environ['TZ']='Europe/Moscow' >>> time.tzset() >>> UTC = calendar.timegm(time.strptime('2007-09-03 15:00','%Y-%m-%d %H:%M')) >>> time.strftime('%Y-%m-%d %H:%M',time.localtime(UTC)) 2007-09-03 19:00 >>> UTC = calendar.timegm(time.strptime('2007-03-03 15:00','%Y-%m-%d %H:%M')) >>> time.strftime('%Y-%m-%d %H:%M',time.localtime(UTC)) 2007-03-03 18:00
Python’s localtime
is a “smart up-to-date library that knows rules of daylight savings for every place”.
os.environ['TZ']='Europe/Moscow'
Oh... And it was right in the docs. Shame on me and thanks for the pointer!
Simon: “I’d love to see that stuff cleaned up for Python 3000.”
If you’re lucky, you might see related stuff get in before then. See [link] for a patch featuring tm_gmtoff in time structures, timegm in the time module, and some other useful functions which should avoid the need to start setting environment variables. Testing this stuff is a pain, especially with C library interactions, leading me to almost recommend datetime and a timezone library (python-dateutil, perhaps) instead.
If you haven’t already, take a look at the pytz package. It gives you access to the Olson time zone database in datetime compatible tzinfo objects. Great for web applications where fiddling with $TZ
and calling time.tzset()
is not an option due to multiple threads.
I agree with your rule of thumb on working with UTC dates for as long as possible, but I’d add another: avoid naive datetime objects as much as possible. If it is a UTC date, use a UTC tzinfo. If it is in some local time zone, use an appropriate tzinfo object.
I’d also steer away from using javascript hacks to convert to local time unless you are talking about times very close to the present. It will be right often enough to give users a false sense of security but will cause problems once you hit a daylight savings transition. If you don’t know the user’s time zone it’d be better to explicitly state what offset is being used.