TIME_ZONE setting: How does it work?

441 views
Skip to first unread message

Michael Elsdoerfer

unread,
Aug 19, 2007, 5:15:18 AM8/19/07
to django...@googlegroups.com
I'm having some trouble with time zones on my production machine (debian,
apache prefork with mod_python). On Windows, everything works as expected.
I'm running the trunk from maybe two weeks ago.

Basically, I have TIME_ZONE = 'GMT+1', but while datetime.datetime.today()
in a vanilla python shell returns the correct date, the same in manage.py
shell does not (off by 3 hours).

While I try to figure this out, allow me a more general question. It seems
every time I change the time zone, the date that gets written to my MySQL
database changes.

Frankly, what I would have expected is: The values stored in the backend
remain the same, only when read are interpreted differently. Isn't that how
it *should* work? Although I am always confused by time zones, so maybe I'm
way off here.

What am I missing?

Thanks,

Michael

Michael Elsdoerfer

unread,
Aug 19, 2007, 5:15:18 AM8/19/07
to django...@googlegroups.com

Malcolm Tredinnick

unread,
Aug 19, 2007, 5:54:16 AM8/19/07
to django...@googlegroups.com
On Sun, 2007-08-19 at 11:15 +0200, Michael Elsdoerfer wrote:
> I'm having some trouble with time zones on my production machine (debian,
> apache prefork with mod_python). On Windows, everything works as expected.
> I'm running the trunk from maybe two weeks ago.

More accurately, on Windows, Django's timezone stuff does absolutely
nothing. Setting timezones on Windows requires code we don't have
(there's an open invitation for somebody to write the necessary code if
they need it), so we don't modify the environment at all.

> Basically, I have TIME_ZONE = 'GMT+1', but while datetime.datetime.today()
> in a vanilla python shell returns the correct date, the same in manage.py
> shell does not (off by 3 hours).

You've fallen into a common trap with POSIX timezone specifications,
which is what are being used here.

The string "GMT+1" actually means (in POSIX terms) "my timezone is
called 'GMT' and it is one hour *west* of the Prime Meridian." The
format is parsed as "name + offset" where offset is negative for East
and positive for West -- it's the number of hours you add to localtime
to get UTC, instead of vice-versa.

Based on your e-mail headers, it looks like you are in the Central
European timezone and, since it's summer time, one hour behind UTC (west
of the Prime Meridian) is three hours behind your current timezone,
which is what you are seeing.

So, either use something like "CET-2" or use the more descriptive names.
These names used to be in the PostgreSQL documentation, but I just
noticed that they have been removed in the latest version. So check a
slightly older version of the PostgreSQL documentation (using a similar
link to that in settings.py above TIME_ZONE) for some examples.

> While I try to figure this out, allow me a more general question. It seems
> every time I change the time zone, the date that gets written to my MySQL
> database changes.
>
> Frankly, what I would have expected is: The values stored in the backend
> remain the same, only when read are interpreted differently. Isn't that how
> it *should* work? Although I am always confused by time zones, so maybe I'm
> way off here.

Django doesn't support datetime fields with timezones. Instead, it
writes the time to the database using the local time (as configured via
the TIME_ZONE setting). This isn't particularly optimal in a number of
cases, but reflects Django's historical usage where the server was only
serving one timezone and never changing, etc. I would expect that to be
fixed in some fashion in the future, because it's hardly uncommon to
have to store multiple time-zoned information (even the Lawrence guys
are discovering this, I gather). There are also problems with corrupting
the environment for other processes by setting the TZ environment
variable.

Tom Tobin has opened a ticket in Trac, volunteering to take on this
effort. I am fully behind it in the broader sense (although he doesn't
seem to have proposed using timezone-aware database fields yet, which is
the best solution a lot of times).

> What am I missing?

Don't let your assumptions lead you around by the nose. :-)

Cheers,
Malcolm

--
Honk if you love peace and quiet.
http://www.pointy-stick.com/blog/

Malcolm Tredinnick

unread,
Aug 19, 2007, 6:05:29 AM8/19/07
to django...@googlegroups.com
On Sun, 2007-08-19 at 19:54 +1000, Malcolm Tredinnick wrote:
[...]

> So, either use something like "CET-2" or use the more descriptive names.
> These names used to be in the PostgreSQL documentation, but I just
> noticed that they have been removed in the latest version. So check a
> slightly older version of the PostgreSQL documentation (using a similar
> link to that in settings.py above TIME_ZONE) for some examples.

Probably the best list at the moment is

http://en.wikipedia.org/wiki/List_of_tz_zones_by_name

with an explanation at http://en.wikipedia.org/wiki/Zoneinfo

One thing I forgot to mention and it's important: A big advantage of
using the zoneinfo name for your timezone is the underlying C library
will then return the daylight-saving-aware version of the time. Whereas
if you use something like 'XYZ-1' it will *always* be one hour ahead of
UTC, since it is a location-independent specification -- no daylight
savings rules come into play.

So, as a general rule, use the zoneinfo form (Europe/Vienna, etc).

Regards,
Malcolm


--
On the other hand, you have different fingers.
http://www.pointy-stick.com/blog/

Michael Elsdoerfer

unread,
Aug 19, 2007, 3:14:58 PM8/19/07
to django...@googlegroups.com
Malcom,

Thank you for the elaborate explanation. That fixed the problem, and I
actually understood it ;)

Michael

Reply all
Reply to author
Forward
0 new messages