Time zones in Google App Engine

Time zones are a human — by which I mean comical and insanely complex — thing. If you’re the sort of person who likes to bore people with inane trivia, and I know I am, you’ll find endless grist for your mill in Riyadh Solar Time, where they tried to make 0:00 fall on sunset. Every day. In the best case, that meant the DST offset changed daily. In the worst case, it changed moment by moment. Imagine the hassle of keeping your clocks up to date.

But even in the relatively sane time zone world we have here in the US, things are still pretty complex. There are places that don’t observe DST, and places where time zone borders make things complicated. So my policy for time zone handling in software is similar to my policy for unicode handling in software: convert to UTC on input to the application, and convert to the desired timezone on output. That way, you can do all the datetime math you need, without worrying about getting caught in a time rift or something.

Another way datetimes are similar to strings is this: a datetime without a timezone attached is meaningless. If I tell you a meeting is at 14:00, you could perhaps guess the time zone based on where the meeting will be held. But if you couldn’t do that (perhaps it is an online meeting) you actually don’t know when it will occur at all, because that might be 14:00 Central Time, 14:00 Pacific Time, or 14:00 Central European Time.

Google’s App Engine drops the ball a little when it comes to datetimes. If fed a timezone-aware datetime, it will convert it to UTC for storage. But when the value is read back out of the datastore, there will be no timezone attached. The context of the datetimes is lost, and you could make a case that part of the value of the datetimes is being lost as well.

So I wrote a type wrapper that fixes that. It attaches the UTC timezone to datetimes when they’re read out, as well as ensuring that only UTC datetimes are stored and everything else is converted. That part is perhaps a little redundant, but I wanted consistency.

Saturday, April 12th, 2008 Write
  • Thanks - this code sample and your explanation is really useful. I am only new to python (started with Google App Engine) but I needed to make a change to your code to avoid errors with entities without values in the TzDateTimeProperty.

    def make_value_from_datastore(self, value):
    value = super(TzDateTimeProperty, self).\
    make_value_from_datastore(value)
    #Added this check to see if the property had a value
    if value is not None:
    if value.tzinfo is None:
    value = value.replace(tzinfo=pytz.utc)
    else:
    value = value.astimezone(pytz.utc)
    return value

    Thanks again and let me know if the above change makes sense. (Works for me)
  • Yeah, that does make sense.
  • jdeibele
    I'm trying to write out log data in a way that is more user-friendly. So rather than showing the UTC time, I want to show it in Pacific time and let the user change it.

    I'm new to Python and Django. Can you give simple examples of how to use this?

    Thanks very much for sharing.
blog comments powered by Disqus