I'm looking for a portable/robust way to obtain timezone of a Linux box (mainly different versions of Debian) in form of Continent/City, like Europe/Kiev.

Till now I did it using timedatectl status | grep zone | cut -d' ' -f10 The problem with this approach is that it works on Debian 9, but not on Debian 10 (can easily be checked using docker images).

Is there a better, more universal/portable way to do this (better without scratching/parsing the output of another command)? If not, how should I modify the command above, so it works on both Debian 9 and 10.

timedatectl status | awk '/zone/ {print $3}'
|improve this answer|||||
  • How do you square that with the question saying that it does not work? – JdeBP Feb 13 at 17:11
  • 1
    The ... | cut -d' ' -f10 in the question relies on the number of spaces being constant on timedatectl's output, but that changes between Debian 9 and 10. Debian 10's timedatectl aligns the fields differently, but the number of words on the line is still the same, so awk works where cut fails. It would be a better idea to parse the machine-readable output of timedatectl show instead - but unfortunately Debian 9 does not seem to have that option available. – telcoM Feb 13 at 18:04
  • 1
    All of that should be explained in the answer. Think of the poor readers coming to this in the future. – JdeBP Feb 13 at 19:32
  • Lacking time here, but you always can edit my answer and insert the explanation ;-) – JucaPirama Feb 14 at 16:06

You can get the timezone from /etc/timezone file:

cat /etc/timezone
|improve this answer|||||
  • 1
    The problem with this approach is that the file that actually determines the system default timezone is /etc/localtime - and while the OS installer sets both files with the same timezone, a system administrator who's used to older ways of doing things may overwrite /etc/localtime without changing /etc/timezone to match. – telcoM Feb 13 at 17:56

The geographic timezone names are both an abstraction and a convenience. Under the hood, the timezone data files are binaries which list offsets, discontinuities and DST changes but not location (even if the filename indicates it, hence the problem with /etc/localtime). There is a mapping from location and date to timezone offsets, but it's not 1:1 – given the output of date for example, you cannot easily and deterministically derive the geographic location in use (but you could compute a set of compatible ones for the current date; or you could, with some effort, inspect earlier dates for discontinuities in order to deduce a location).

There is a master list of zone names, and the timezone definition files look like:

# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Europe/London   -0:01:15 -      LMT     1847 Dec  1 0:00s
                         0:00   GB-Eire %s      1968 Oct 27
                         1:00   -       BST     1971 Oct 31 2:00u
                         0:00   GB-Eire %s      1996
                         0:00   EU      GMT/BST
Link    Europe/London   Europe/Jersey
Link    Europe/London   Europe/Guernsey
Link    Europe/London   Europe/Isle_of_Man

When creating the binary Europe/London file the indicated rules are processed to build the time rules (the timestamps where something changes, inspect with zdump -v Europe/London), and the related locations are aliased. The localtime file contents or date output from any of the above locations will be indistinguishable.

The abstraction lets you handle legal changes in time, such as

# TZ=Europe/Andorra date -d "Aug 31 1984"
Fri Aug 31 00:00:00 CET 1984

TZ=Europe/Andorra date -d "Aug 31 1985"
Sat Aug 31 00:00:00 CEST 1985

(Andorra is not in the EU, but follows EU DST rules since 1985)

/etc/localtime is the (binary) timezone data file, on Debian by convention it should be a symlink to the named geographic timezone file according to the ''Stretch'' (9) and ''Buster'' (10) localtime man pages:

The /etc/localtime file configures the system-wide timezone of the local system that is used by applications for presentation to the user. It should be an absolute or relative symbolic link pointing to /usr/share /zoneinfo/, followed by a timezone identifier such as "Europe/Berlin" or "Etc/UTC". The resulting link should lead to the corresponding binary tzfile(5) timezone data for the configured timezone.

Because the timezone identifier is extracted from the symlink target name of /etc/localtime, this file may not be a normal file or hardlink.

Assuming that's the case:

if [ -L /etc/localtime ]; then
  IFS=/ read -a TZFILE < <(readlink -f /etc/localtime)
  printf -v TZNAME "%s/%s\n" ${TZFILE[-2]} ${TZFILE[-1]}
  echo $TZNAME

In earlier versions (or if someone has not been following the documentation) it was a copy of the timezone data file. So, to verify that /etc/localtime and /etc/timezone are in agreement you need to compare them:

$ diff -s /etc/localtime /usr/share/zoneinfo/`cat /etc/timezone`
Files /etc/localtime and /usr/share/zoneinfo/America/New_York are identical

If you need to work backwards, or be thorough:

read CHECK file < <(sha256sum /etc/localtime)
while read sum file; do 
  [[ "$sum" == "$CHECK" ]] && printf "%s\n" "$file"
done < <(find /usr/share/zoneinfo/ -type f |xargs sha256sum)

This isn't a truly portable answer (POSIX doesn't define or require these long names, they come from ICANN/IANA), and you're using systemd commands on those versions of Debian.

|improve this answer|||||

Use tzselect in modern linux servers. run tzselect and start drilling down through the prompts.

~]# tzselect 
Please identify a location so that time zone rules can be set correctly.
Please select a continent or ocean.
 1) Africa
 2) Americas
 3) Antarctica
 4) Arctic Ocean
 5) Asia
 6) Atlantic Ocean
 7) Australia
 8) Europe
 9) Indian Ocean
10) Pacific Ocean
11) none - I want to specify the time zone using the Posix TZ format.

Sorry I just re-read you orig post. looks like you want a scriptable way to get the time zone. I will leave this in case it helps but prob not what you needed.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.