[tz] Bug report: "Asia" timezone

Zefram zefram at fysh.org
Tue Jun 19 21:15:29 UTC 2012


Boruch Baum wrote:
>It's a double bug. It's printing out a
>non-existent timezone, and it's using GMT for
>"Asia"

It's well-known behaviour.  It's part of libc, not date per se, as you
can see through (for example) ls's display of file timestamps:

$ TZ=UTC date; TZ=Europe/Paris date; TZ=Foo/Bar date
Tue Jun 19 21:04:33 UTC 2012
Tue Jun 19 23:04:33 CEST 2012
Tue Jun 19 21:04:33 Foo 2012
$ touch foo; TZ=UTC ls -l --full-time foo; TZ=Europe/Paris ls -l --full-time foo; TZ=Foo/Bar ls -l --full-time foo;
-rw-rw-r-- 1 zefram zefram 0 2012-06-19 21:04:43.105251376 +0000 foo
-rw-rw-r-- 1 zefram zefram 0 2012-06-19 23:04:43.105251376 +0200 foo
-rw-rw-r-- 1 zefram zefram 0 2012-06-19 21:04:43.105251376 +0000 foo

Finding that Foo/Bar or Asia/Moscow doesn't exist in the timezone
database, libc tries to interpret it as a POSIX timezone specification.
It's not actually well-formed as a POSIX timezone specification, but
it tries the best it can to interpret it anyway.  In this case, the "/"
causes a parse error and so the specification is being truncated there.
(Some implementations don't truncate it, and you get the whole "Foo/Bar"
or whatever as the abbreviation in the date output.)  The simplest form
of POSIX timezone specification consists of an abbreviation followed
by an offset; in this case the offset is missing, so libc is treating
it as a zero offset.  The result is that "Foo/Bar" acts like the valid
POSIX timezone spec "Foo0", meaning a fixed offset of zero hours from
UT with abbreviation "Foo".

It would be better if libc could reject this $TZ value, rather than making
this futile attempt to make sense of it, but the historical API has very
little scope to signal errors, and backward compatibility is a bitch.
So you're stuck with this behaviour.  Just learn the lesson from it:
don't make any new API or library be this forgiving with bad input.

-zefram


More information about the tz mailing list