I’ve never paid much thoughts when dealing with dates, times and timezones until I moved to Australia. I should have.
As it happened, if you’re running a server on the east coast of Australia you’re facing three issues:
- Queensland does not have daylight saving (yay)
- Tasmania, New South Wales and Victoria have daylight saving
- but, all of them are in the same timezone.
That means, if you run date on your Linux box you usually get something like that:
Tue Jun 5 14:04:27 EST 2012
Looks okey, doesn’t it? Not if you start a Zope server:
>>> import DateTime >>> DateTime.DateTime() DateTime('2012/06/05 14:06:49.964253 US/Eastern')
Wait, what? I’m in Australia not in the US? This is not New York? It’s sunny Brisbane?
Apparently Australians also use AEST instead of EST as an appreviated form to specify the timezone. Ted Percival – facing the same problem – created a patch, which introduces these appreviations in the tzdata package. Just pushing this patch upstream seams not to happen for whatever reasons.
With this patch, I also had to compile a new tzdata rpm for CentOS for Mooball servers. This was a very manual and error prone process. And because I’m personally using Ubuntu I had to catch up with the documentation each time I had to compile and patch a new source rpm.
This lead me to create a package with a Makefile:
- It pulls down the source rpm,
- applies the supplied patches and
- builds a new rpm.
This package registered with Jenkins and you have always an updated RPM for each CentOS release.
Copying the zonefile from e.g. Australia/Brisbane to /etc/localtime resulted in this:
Tue Jun 5 14:04:27 AEST 2012
and Zope reports:
>>> import DateTime >>> DateTime.DateTime() DateTime('2012/06/05 14:06:49.964253 GMT+10')
… is still only a workaround
The problem seems to be application specific. Confirming with the man page on tzname seems to suggest, that applications need to check the timezone and the tzname tuple in order to correctly determine time with daylight saving.
Zope seems to have workarounds added to the DateTime package. Setting a TZ environment variable like:
TZ="AEST" bin/instance fg
will set the correct timezone. Unfortunately it means, that you need to adjust the timezone environment variable on daylight saving (in our case Sydney or Melbourne) and restart your application. Using a patched tzdata helps to avoid restarting applications.
What I learned
So what I now got out of this is:
- Be more date/time/timezone aware when building applications
- How to patch source rpms
A nice package
which I can pop into Jenkins which compiles a custom patched rpm.
- You can adjust the time/date with a simple environment variable, e.g. TZ=”AEST” bin/instance fg
- Some problems appear as an easy fix, but reveal a more complex situation underneath
Talking to Dylan Jay from Pretaweb, there is more to the environment variable (I should have read the man page of tzname more carefully). Setting the TZ variable to more than just AEST. You can specify beginning and end of daylight saving, eg:
TZ="AEST-10AEDT-11,M10.4.2,M4.4.3" bin/instance fg
The format is extensively documented in the man page of tzname.