The correct, standard and portable way to define via $TZ
a time zone that is called UTC and is on (with 0 offset to) Universal Time all year round is with:
TZ=UTC0
That is self-contained and give the full specification for that timezone. That tells that the offset to UTC is 0 (all year round as there's no DST part specified) and the label (as reported by date +%Z
for instance) is UTC.
The timezone specification as described by TZ
can get more complicated as you can also embed the DST name and offset and the rules for when to change between summer and winter time. However, those rules are limited and in particular can't cover cases where the rules change change from one year to another (and in most countries, the rules have changed over time or use rules different from the first or last Sunday in some month).
That's why POSIX also specifies TZ=:something
but with how something
is handled left implementation defined to allow implementations to come up with a better way to define a timezone for real life zones.
On most systems, that's implemented using the ICANN's tz database (they also publish reference code to handle those).
So you'd use TZ=:Europe/London
for instance for the mainland Britain timezone which covers timezone offsets and when the change for the current year and all past years in London.
In practice, Europe/London
is interpreted as the path of a file relative to some zoneinfo
directory (often /usr/share/zoneinfo
).
In the tz database, there is also a Etc/UTC
file (with Etc/Universal
and Etc/Zulu
links to it). Etc/GMT
is defined the same way except the label is GMT all year round (with Etc/GMT-0
, Etc/GMT+0
, Etc/Greenwich
as links).
So, you can do TZ=:Etc/UTC
to get the same effect as TZ=UTC0
except that the system needs to open that Etc/UTC
file to find out about the simplest of TZ rules: 0 offset to UTC all year round.
On many (most?) systems, there's a UTC
-> Etc/UTC
symlink, so you can also do TZ=:UTC
.
TZ=UTC
itself is not POSIX, but here in the absence of an offset being given, on most systems, it's interpreted as the same as TZ=:UTC
(looks for the timezone definition in /path/to/zoneinfo/UTC
. But if the tz database is not available, that won't work.
Also note that with date
specifically, you can use the -u
option to get UTC dates regardless of what $TZ
contains. date -u
is equivalent to TZ=UTC0 date
.
TZ=UTC0 date
if you want UTC date portably. The defines a zone named "UTC" with a 0 offset from UTC. WhileTZ=UTC
could be anything.