What else apart from /etc/localtime and $TZ affects `date`

datetimezone

I have a fedora 20 installation with the clock set to UTC, and no TZ environment variable. Why the date command is outputting the date in the CET timezone (which by the way is my local timezone)?

[fedora@slave2 ~]$ ls -l /etc/localtime
lrwxrwxrwx. 1 root root 27 Apr  8  2014 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
[fedora@slave2 ~]$ echo $TZ

[fedora@slave2 ~]$ env | grep TZ
[fedora@slave2 ~]$ date
Wed Mar 18 17:20:44 CET 2015

Also, asking for the time in a little java program outputs the time in UTC (while if I set the TZ environment to CET, then in outputs the date in CET):

[fedora@slave2 ~]$ java DateDemo
Wed Mar 18 16:24:17 UTC 2015
[fedora@slave2 ~]$ TZ=CET java DateDemo
Wed Mar 18 17:24:24 CET 2015

(I got the DateDemo java code from http://www.tutorialspoint.com/java/java_date_time.htm)

Additional info:

[fedora@slave2 ~]$ type date
date is hashed (/usr/bin/date)
[fedora@slave2 ~]$ set +h
[fedora@slave2 ~]$ type date
date is /usr/bin/date
[fedora@slave2 ~]$ date
Wed Mar 18 17:58:26 CET 2015
[fedora@slave2 ~]$ strace -fe open date
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
Wed Mar 18 18:02:41 CET 2015
+++ exited with 0 +++

zdump:

[fedora@slave2 ~]$ zdump -v /etc/localtime | head
/etc/localtime  -9223372036854775808 = NULL
/etc/localtime  -9223372036854689408 = NULL
/etc/localtime  Mon Dec 31 23:53:55 1900 UTC = Mon Dec 31 23:59:59 1900 LMT isdst=0 gmtoff=364
/etc/localtime  Mon Dec 31 23:53:56 1900 UTC = Mon Dec 31 23:53:56 1900 WET isdst=0 gmtoff=0
/etc/localtime  Sun Sep 29 23:59:59 1946 UTC = Sun Sep 29 23:59:59 1946 WET isdst=0 gmtoff=0
/etc/localtime  Mon Sep 30 00:00:00 1946 UTC = Mon Sep 30 01:00:00 1946 CET isdst=0 gmtoff=3600
/etc/localtime  Sun Mar 31 00:59:59 1985 UTC = Sun Mar 31 01:59:59 1985 CET isdst=0 gmtoff=3600
/etc/localtime  Sun Mar 31 01:00:00 1985 UTC = Sun Mar 31 03:00:00 1985 CEST isdst=1 gmtoff=7200
/etc/localtime  Sun Sep 29 00:59:59 1985 UTC = Sun Sep 29 02:59:59 1985 CEST isdst=1 gmtoff=7200
/etc/localtime  Sun Sep 29 01:00:00 1985 UTC = Sun Sep 29 02:00:00 1985 CET isdst=0 gmtoff=3600

Best Answer

The date command, like almost all programs, relies on the standard library to access timezone data. On Linux (except for some embedded systems) and *BSD, the standard library determines the current timezone from the content of /etc/localtime.

It appears that on your system, /etc/localtime does not contain what it seems to contain. Like Stéphane Chazelas and derobert, I strongly suspect that the file /usr/share/zoneinfo/Etc/UTC, which /etc/localtime is a symbolic link to, contains incorrect information, probably because someone who didn't know what they were doing attempted to change the system timezone and ended up overwriting a system file.

I recommend reinstalling the time zone information to make sure that your system isn't corrupted. Run rpm -qf /usr/share/zoneinfo/Etc/UTC to see which package contains that file and reinstall it with yum reinstall. Then set the timezone properly, either with the timedatectl command or by changing the /etc/localtime symbolic link and the text file /etc/zoneinfo or /etc/sysconfig/clock (I think Fedora uses the latter):

ln -snf /usr/share/zoneinfo/Europe/Madrid /etc/localtime
echo Europe/Madrid >/etc/zoneinfo
sed -i -e '/^ *ZONE=/d' /etc/sysconfig/clock
echo 'ZONE="Europe/Madrid"' >>/etc/sysconfig/clock

Java does things differently — it bypasses the standard library and reads /etc/timezone or /etc/sysconfig/clock instead. That's why you're seeing different timezone information from Java programs.

Related Question