Timezone processing (was Re: "cal 9 1752")
Guy Harris
guy at auspex.auspex.com
Sun Dec 9 07:01:29 AEST 1990
>OK...so what was the Arthur Olson approach?
Have the rules for changing between standard and summer time represented
as a list of times/dates at which the offset from GMT changes,
corresponding offsets, flags indicating whether this is standard or
summer time, and abbreviations for the time zone. Have a compiler that
turns various specifications for the rules into such a list, and store
that list in a file. Have "tzset()" and company load up the table from
those files; the setting of the TZ environment variable specifies the
file to load.
>The TZ setup, at least in the System V release 2 systems I've used,
>seems like a very usable approach.
It seems so only under some circumstances.
Problems with it:
1) as it appears in AT&T releases prior to S5R3.1, *all* it can specify
is the time zone abbreviation for standard time, the offset from GMT
for standard time, and the optional time zone abbreviation for summer
time if summer time is used. The actual rules for when the times
change are *hardcoded* into a library routine.
Needless to say, this sucks big time if you live in an area where the
rules don't match those hardcoded into the library routine. Areas
outside the US don't use the same rules as the US (even Canada
skipped Tricky Dicky's modifications of the rules in the '70s, as far
as I know); areas *inside* the US don't use the rules that were found
in most if not all UNIX systems, because the rules changed in 1987
and UNIX systems made before then - and even lots made after then -
had the old rules. (The rule change in question was what originally
prompted Olson's work on this stuff.)
It also didn't handle areas with time zones not offset from GMT by an
even number of hours; yes, they exist.
2) as it appears in S5R3.1, you can specify the rules for the *current*
year, specifying the date and time at which summer time starts and
the date at which it ends. You can also specify the offset from GMT
of summer time, if it doesn't happen to be one hour off from the
offset of standard time (e.g., "double daylight savings time" with
the clock shifting two hours).
It handles areas with time zones not offset from GMT by an even
number of hours. It also lets you specify not only the dates when
the clock moves forward or back, but the *time of day* when it
happens; yes, not everybody does it at 2AM local time.
This does let you convert UNIX times to local time if the time is in
the current year, and most times are probably in the current year
most of the time; however, close only counts in horseshoes - not
*all* times are in the current year, and if it's right after January
1, a fair number of e.g. times on files are not in the current year.
What's more, it requires the system administrator to change the
system time zone every year. The syntax is a bit sucky, in that the
dates are specified as day numbers within the year; *I* sure don't
think in those terms, and don't have any table to give me that
information conveniently. Maybe AT&T gives out calendars like that,
but I sure don't have one here....
3) the POSIX scheme lets you specify certain kinds of repeating rules,
e.g. "first Sunday in October", so that you don't have to change the
time zone every year, can have some dates outside the current year
converted correctly, and don't have to deal with day numbers relative
to the beginning of the year.
Unfortunately, this *still* doesn't handle rules that *aren't*
repeating. The US rules generally repeat, but if you want to include
pre-1987 and post-1987 times, they don't. Other countries change
their rules fairly frequently, e.g. Australia (one of the other
people who worked on the Olson time zone stuff was Robert Elz, an
Australian; he had a very *definite* incentive for doing that).
According to the person who contributed the most recent rules for
Israel, prior to 1989, the rules changed every year, and from 1989
onwards summer time commences midnight of the first Saturday night
following Passover, and standard time is reinstated "on the Saturday
night whereupon Jews following the Ashkenazi (European) rite begin to
recite the Selichot (forgiveness) prayers prior to the Jewish Lunar New
Year).
On top of that, if you want to find out what time it is now in some
other country, you have to know what the right rules and GMT offset
are, and set TZ based on that.
4) the Olson scheme deals with all the objections above:
since the file contains a list of times at which the offset from
GMT changes, it can represent any rules that fit within the
file; they don't have to be described by some simple repeating
rule. The files are generally limited to 370 transitions, which
is enough to handle 138 years of the proposed US scheme wherein
the transitions are different in Presidential election years - or
a bit more than a year's worth of solar time (corrected daily to
the nearest second), although that still has the "only within
the current year" limitation and may now be obsolete if the
Saudis no longer use solar time.
The offsets are in seconds, and the transition times are UNIX
times, so time zones not an integral number of hours from GMT
can be handled, and the transition times aren't hard-coded.
Except in areas using Solar time, they can convert dates in the
past all the way to 1970, if the rules have been put into a
file; they can attempt to convert dates in the future, under the
assumption that the rules to be used are known at the time the
rule file is made.
The rule file syntax is fairly friendly; you don't have to know
the day number within a year of a date.
If you want to know what time it is in Japan, you can do
TZ=Japan date
in the Bourne/Korn/Bourne-again shells, or something slightly
more annoying in the C shell (thanks to its lack of a convenient
ability to override an environment variable setting for one
command). You don't have to already know what the offset from
GMT for Japan is.
And the cost is small. The most recent set of files, as they appear
in SunOS 4.1 (BTW, the rules files are in a machine-independent
format; that was one of my contributions to this stuff), take up
238KB of disk space (8K/1K file system), and include a fair number of
countries. The main memory overhead for the table is less than 1K;
the code takes up about 8.8K on a SPARC (SunOS 4.1 version), and
requires about 230 bytes of data+BSS. The time spent loading the
table wasn't very large, either, when I tested it on various machines
(diskless Sun-3/50, 3B2), and you only do it once, not once per date.
BSD picked it up after 4.3BSD; SunOS picked it up in SunOS 4.0; various
other vendors have picked it up - including AT&T in System V Release 4.
More information about the Comp.unix.questions
mailing list