As @Gilles said, that BST is something that is output upon
date +%Z, to tell users that it's a British Summer Time date (so GMT+1) not something that defines a timezone, not something that you can use for
That BST is significant to British users. When a British user sees
14:00 BST, they know the timestamp refers to 14:00 summer time in mainland Britain (so 13:00 UTC). The use of those 3-4 letter codes is widespread in Britain, the US and some other English speaking countries, so show up in the default output of
date there (in
en_GB.UTF-8 locales for instance). On the other hand, most French users will have no idea what
14:00 CEST means (even though
CEST refers to Central European Summer Time, the GMT+2 that applies in summer in France), so you'd notice that when dates specify the time zone, they rather include the UTC offset than
CEST there (like
mardi 2 mai 2017, 13:34:09 (UTC+0200)).
$TZ variable is not meant to contain those 3-4 letter codes. It contains something that defines/specifies the timezone, the region you're in. Applications use it to know the offset with UTC at any point in time, when to switch between Winter and Summer time and what the code (if any) for the Winter and Summer time would be displayed to the user (for those users for whom it's significant).
For that, you can either set
TZ to some system-defined timezone specification. Like
TZ=:Europe/London (though many systems also accept
TZ=Europe/London as well), or have
TZ contain the full rules (though those rules are limited).
For instance, If I use
TZ=:Europe/London on my system, then the rules will be read from
That file will specify for instance that since 1996, the offset from UTC is 0 from the last Sunday in October at 2am UTC to the last Sunday in March (with name GMT for "Greenwich Mean Time") and 1 other wise (with name BST for "British Summer Time"), while for 1970 (0 Unix time) to 1972, it was 1 all year round with name BST for "British Standard Time".
You can see already that it makes no sense to use BST as a timezone specification. First, it has meant different things at different points in time, and even if we only consider the current epoch, it's only a code for the summer time, so can't be used to as a timezone specification for the whole year.
Now, you can also have
TZ contain the full rules. For instance for the "British Standard (not Summer) Time" of the early 70s, you can use the simplest form of specification:
That specifies a timezone that is always 1 hour East of UTC and for which
date +%Z always returns
BST. That timezone is correct for mainland Britain for the early 70s and for summer time since 1972, but not for Winter time since 1972 (and we can't tell for the future).
Or you can use the full specification for the current rules:
That says that there are two periods in the year, one for which the name is GMT with offset 0, and one BST with offset 1 (implied as 0+1 above when not specified), where the switch from one to the other is on the last (5) Sunday (0) of March (3) at 1:00:00 UTC and back on the last sunday of October at 2:00.
Again, that TZ works from 1996 to now, but not necessarily otherwise. For instance, for 1970-01-01 00:00:00 UTC (0 Unix epoch time, when the local time was 1:00:00 BST (British Standard Time) in London):
$ TZ=:Europe/London date -d @0
Thu 1 Jan 01:00:00 BST 1970
$ TZ=GMT0BST,M3.5.0/1:00:00,M10.5.0/2:00:00 date -d @0
Thu 1 Jan 00:00:00 GMT 1970
Per POSIX, the behaviour for
TZ=BST-1 is well defined (as described above)
TZ=Europe/London) is unspecified.
TZ=:Europe/London is implementation defined. That is systems are meant to support it and document what that does though POSIX doesn't tell us what's that done.
In the third case above, on GNU systems (and I believe most other Unix-like systems), when
TZ starts with a
:, what followed is taken as a path to a timezone definition file. In the case of GNU system, that's the case as well when
: is omitted (even if the value forms a valid timezone specification like
UTC0, but generally there shouldn't exist such files, though I can see some exceptions on my system which makes it a non-POSIX system (for instance
TZ=CST6CDT date -d 1943-01-01 +%Z outputs
CWT instead of
CST because there's a
/usr/share/zoneinfo/CST6CDT file1 that defines a war time for that period)).
That path is generally a relative path, in which case it's relative to
$TZDIR (or some default like
$TZDIR is unset as is generally the case). For security reasons,
$TZDIR, absolute path or relative paths with
.. components are ignored in privilege escalation contexts (like in setuid contexts).
So typically, on a GNU system, a
TZ=:BST, same as
TZ=BST will typically look for a
/usr/share/zoneinfo/BST file. If not found (as would be the case, as
BST can't possibly identify a timezone definition), it will typically assume UTC time and a timezone name (as in
date +%Z output) of
MET... are remnants from another time. In late 1993, the TZ database (as now maintained by IANA) changed from using adhoc (and most often ambiguous) names (like
Area/City where the city is the most populated city (at the time of release) where the zone applies (Area being large areas like continent/ocean). For mainland Britain, where you used to use
GB-Eire (not WET), you now (since 1993) use
WET) are still available for backward compatibility (
GB-Eire now links to
WET is defined as a Zone using UTC in Winter and the EU Rules for DST (Britain has only been following the EU rules since 1996 and with the UK now leaving the EU, nobody can say what the future holds)) but should not be used now in new deployments.