3

On Ubuntu 18.04, I have the following behavior of date:

$ date --version | head -n1
date (GNU coreutils) 8.28
$ date
Вт окт  8 13:18:18 MSK 2019
$ TZ=UTC date
Вт окт  8 10:18:23 UTC 2019

So far so good. But now I'm trying to do the same on Raspbian 9:

$ date --version | head -n1
date (GNU coreutils) 8.26
$ date
Tue Oct  8 13:18:50 MSK 2019
$ TZ=UTC date
Tue Oct  8 13:18:51 MSK 2019

What could be the reason for Raspbian version of date to ignore the TZ environment variable?

3

2 Answers 2

5

I can think of two possible causes:

  1. the file /usr/share/zoneinfo/UTC is not present or is corrupted on your Raspbian 9, so glibc fails to implement the TZ variable setting and falls back to system default timezone,

  2. you may have a previously-configured TZ variable that has been marked as read-only, so your attempt to change it won't take effect.

6
  • Indeed, dpkg -V tzdata reveals that exactly this file was changed. And comparison of hashes shows that for some reason it had the same contents as W-SU. Doing apt install --reinstall tzdata and dpkg-reconfigure tzdata fixed the problem.
    – Ruslan
    Commented Oct 8, 2019 at 11:22
  • 1
    The system default timezone is determined by file /etc/localtime, which is, depending on distribution, either a symlink to /usr/share/zoneinfo/some/zone or a copy of the appropriate file from the zoneinfo directory. If it is a link, and someone attempts to copy a new file over it to change the system default timezone, the overwrite will actually happen to the file the link points to. So I guess your Raspbian originally had UTC linked as the default timezone, and an attempt was made to switch it by cp /usr/share/zoneinfo/W-SU /etc/localtime, but it ended up overwriting ...zoneinfo/UTC.
    – telcoM
    Commented Oct 8, 2019 at 12:14
  • So you may wish to check that the system default timezone is still set correctly, and adjust it if necessary. If /etc/localtime is a symbolic link, you can either use e.g. ln -sf /usr/share/zoneinfo/W-SU /etc/localtime or just delete the old /etc/localtime first before copying/linking the desired timezone file in its place.
    – telcoM
    Commented Oct 8, 2019 at 12:17
  • You're spot on! After dpkg-reconfigure tzdata I now have a symlink to my desired default timezone, not a copy.
    – Ruslan
    Commented Oct 8, 2019 at 12:18
  • @Ruslan Raspberry is known for corrupting SD cards. Keep backups. Commented Oct 9, 2019 at 10:45
4

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .