This may come as a surprise to US-based readers, but Mac OS X daylight saving time (DST) algorithms are broken. (Yes, I’ll be filing a bug as soon as I have all the information together.)

Basically, the BSD underpinnings of Mac OS X use the standard timezone files in /usr/share/zoneinfo. There’s a symbolic link at /etc/localtime which points to the correct TZ file; in my case, /usr/share/zoneinfo/Brazil/East. So far so good…

Last weekend all Macs in Brazil running Mac OS X suddenly shifted one hour ahead. Apparently no one had thought of telling Apple icon_wink.gif that the official start of DST in Brazil had been postponed from Oct. 13 to Nov. 3. No one’s sure exactly why; it probably had to do with the presidential elections, or the unseasonably hot weather, or the dropping exchange rate, or all of those…

Naturally, I thought this would be simple to fix; just fix the TZ source file, recompile it with zic, distribute a patch, and presto. Little did I know. First of all, getting hold of the original TZ source file wasn’t easy. The updated files are supposed to be available at ftp://elsie.nci.nih.gov/pub/, which seems to be permanently down. Googling for the files yielded only a few hits, most of which hadn’t been updated since 1999 or 2000.

The obvious place to find them should have been Apple’s Darwin site. However, there’s no easy index to find which files are in which source module, and I had neither time nor bandwidth to download the whole 600+MB thing. Looking in Libc and a dozen other likely places yielded nothing.

I finally chose one of the latest files I could find and updated it according to the government’s official site. There were many small errors, but finally it seemed to be working and I published a patch.

A few days later some readers sent me mail, complaining that the Finder’s timestamps were being set one hour ahead. Entourage was also setting appointments one hour ahead, and similar reports came in for some other Carbon applications.

I’m still investigating this, but apparently the Finder (and some other Carbon apps) still use the old-style APIs to convert UTC to local time. These APIs, instead of using the BSD tables, apparently still use some classic database. Needless to say, there seems to be no easy method for synching this database with the BSD information…

One further problem is that the classic database is using an outdated rule of thumb for Brazil: DST is supposed to start on the first Sunday in October. That has indeed been the case for a couple of years, but not lately… anyway, Brazil is one of those countries where the actual DST dates are set anew every year by government decree. So any such rule of thumb will be more times wrong than right.

Unfortunately, the standard BSD TZ files are in a binary format. This is clearly one place where Apple should break with the standard and go to XML files. Standard Unix tools shouldn’t read those files directly anyway, as there’s an API to get specific information from them.

Last night I did a check on many well-known timezone sites. Most of them still have the old, incorrect, Oct. 13 date stored and therefore incorrectly tell users that DST is active in Brazil. A few still use the “first Sunday in October” rule and therefore have been wrong since Oct. 6! Only one lone site had correct information. All sites, without fail, are applying DST to all 4 of Brazil’s timezones, which is also wrong; only the Brazil/East zone applies DST (some states are exceptions – rarely the same ones).

The same problem, of course, hit many Internet provider’s servers, as they mostly use Linux. The standard fix has usually been to manually set the server’s clock, instead of fixing the TZ data. Those few servers that synch to time servers have to switch timezones instead. These quick-and-dirty fixes further confuses matters, as some software which explicitly checks for DST will continue to show the wrong time.

Finally, there seems to be a large-scale misconception that there are no TZ tables inside each computer, and that DST changes are broadcast by time servers; some people wrote me complaining that they had checked out several time servers, and that even the Brazilian servers were wrong! Of course, that’s not the case; time servers broadcast UTC time and this is converted to local time inside each computer.

Update: It seems that two routines in the Date&Time utilities, which convert between Local time and UTC, use fixed tables built into the CarbonCore framework executable, instead of the TZ tables. icon_twisted.gif

I’ll be updating this post as I find out more clues… stay tuned!