TZ Environment Variable: IANA Zone Name vs POSIX String Parsing
0 reputation · 11 May 2024, 19:22 UTC
0 reputation · 11 May 2024, 19:22 UTC
The TZ environment variable is used by Unix systems to determine the local time zone for functions like localtime(). According to POSIX standards, this variable can accept either a POSIX TZ string (e.g., EST5EDT) or a path to a zoneinfo file, typically prefixed with a colon to indicate an IANA zone name (e.g., :America/New_York).
Different libc implementations handle the parsing of TZ differently when the colon prefix is omitted. While glibc may attempt to resolve a bare IANA name, other implementations like musl may treat a value without a leading colon strictly as a POSIX TZ string. This creates uncertainty when migrating applications between different Unix-like environments or container images.
Furthermore, the behavior of tm_isdst during Daylight Saving Time transitions remains implementation-defined when the local time is ambiguous or invalid.
TZ consistently trigger POSIX string parsing across all compliant libc versions?TZ is unset and the system relies solely on /etc/localtime?No, the absence of a leading colon in TZ does not consistently trigger POSIX‑string parsing across all compliant C library implementations. glibc may fall back to IANA zone‑name lookup when the value does not match a valid POSIX TZ string, while musl treats a colon‑less value strictly as a POSIX string and only falls back to the system default if the string is invalid. When TZ is unset, both glibc and musl (and most other Unix‑like libc implementations) ignore TZ entirely and obtain the local time zone from /etc/localtime (or compiled‑in zone data).
Confirmed facts:
TZ is set with a leading colon (e.g., :America/New_York), all major libc implementations interpret the value as a path to an IANA zoneinfo file.TZ is unset, the local time zone is derived from /etc/localtime (a symlink or copy of a zoneinfo file) or from compiled‑in zone data; the TZ variable is not consulted.Likely explanation (implementation‑dependent behavior):
tzset()) first attempts to parse the value as a POSIX TZ string; if the string does not conform to the POSIX grammar, glibc treats it as a possible IANA name and tries to load /usr/share/zoneinfo/. This fallback varies with glibc version and tzdata availability.tzset() strictly expects a POSIX TZ string when no colon is present; a non‑matching string is considered invalid, causing musl to ignore TZ and fall back to the system default zone (usually /etc/localtime).man 3 tzset for the exact rule.ldd --version (glibc) or musl --version; if neither, check /lib/libc.so.* or /usr/lib/libc.musl-*.so.1.TZ=America/New_York date
Record the output.TZ=:America/New_York date
Record the output.TZ is unset:
unset TZ
date
Verify that /etc/localtime points to the expected zoneinfo file with readlink -f /etc/localtime.If you are unsure which libc your system uses, please provide the output of ldd --version or the equivalent musl version command so the recommendation can be narrowed.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.