除了 /etc/localtime 和 $TZ 之外还有什么影响`date`?

Car*_*rós 6 date timezone

我有一个 Fedora 20 安装,时钟设置为 UTC,没有TZ环境变量。为什么该date命令在CET时区(顺便说一下是我的本地时区)中输出日期?

[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
Run Code Online (Sandbox Code Playgroud)

另外,在一个小java程序中询问时间以UTC输出时间(而如果我将TZ环境设置为CET,则在输出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
Run Code Online (Sandbox Code Playgroud)

(我DateDemohttp://www.tutorialspoint.com/java/java_date_time.htm得到了java 代码)

附加信息:

[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 +++
Run Code Online (Sandbox Code Playgroud)

转储:

[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
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 7

date与几乎所有程序一样,该命令依赖于标准库来访问时区数据。在 Linux(某些嵌入式系统除外)和 *BSD 上,标准库根据/etc/localtime.

似乎在您的系统上,/etc/localtime不包含它似乎包含的内容。像斯特凡Chazelasderobert,我强烈怀疑该文件/usr/share/zoneinfo/Etc/UTC,这/etc/localtime是一个符号链接,包含不正确的信息,可能是因为人谁不知道他们在做什么尝试更改系统时区,并最终覆盖系统文件。

我建议重新安装时区信息以确保您的系统没有损坏。运行rpm -qf /usr/share/zoneinfo/Etc/UTC以查看哪个包包含该文件并使用yum reinstall. 然后使用timedatectl命令或通过更改/etc/localtime符号链接和文本文件/etc/zoneinfo/etc/sysconfig/clock(我认为 Fedora 使用后者)正确设置时区:

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
Run Code Online (Sandbox Code Playgroud)

Java 以不同的方式做事——它绕过标准库并读取/etc/timezone/etc/sysconfig/clock替代。这就是为什么您会从 Java 程序中看到不同的时区信息。