在 Ubuntu 18.04 上,我有以下行为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
到目前为止,一切都很好。但现在我尝试在 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
date
Raspbian 版本忽略环境变量的原因可能是什么TZ
?
答案1
我可以想到两个可能的原因:
该文件
/usr/share/zoneinfo/UTC
在您的 Raspbian 9 上不存在或已损坏,因此glibc
无法实现 TZ 变量设置并回退到系统默认时区,您可能有一个先前配置的 TZ 变量已被标记为只读,因此您尝试更改它不会生效。
答案2
$TZ
通过称为 UTC 且全年处于通用时间(与 0 偏移)的时区进行定义的正确、标准和可移植的方法是:
TZ=UTC0
这是独立的,并给出了该时区的完整规范。这表明与 UTC 的偏移量为 0(全年都是如此,因为没有指定 DST 部分)并且标签(例如报告的date +%Z
)是 UTC。
所描述的时区规范TZ
可能会变得更加复杂,因为您还可以嵌入 DST 名称和偏移量以及何时在夏令时和冬令时之间更改的规则。然而,这些规则是有限的,特别是不能涵盖规则从一年到另一年变化的情况(并且在大多数国家/地区,规则随着时间的推移而变化,或者使用与某个月的第一个或最后一个星期日不同的规则) 。
这就是为什么 POSIX 也指定TZ=:something
了如何something
处理左实现定义,以允许实现提出更好的方法来定义现实生活中的时区。
在大多数系统上,这是使用ICANN 的 tz 数据库(他们还发布了处理这些问题的参考代码)。
因此,您可以使用TZ=:Europe/London
例如英国大陆时区,其中涵盖时区偏移以及伦敦当年和过去所有年份的变化时间。
在实践中,Europe/London
被解释为文件相对于某个目录的路径zoneinfo
(通常/usr/share/zoneinfo
)。
在 tz 数据库中,还有一个Etc/UTC
文件(包含该文件Etc/Universal
及其Etc/Zulu
链接)。Etc/GMT
定义方式相同,但标签全年均为 GMT(使用Etc/GMT-0
, Etc/GMT+0
,Etc/Greenwich
作为链接)。
因此,您可以TZ=:Etc/UTC
得到与 UTC 相同的效果,TZ=UTC0
只不过系统需要打开该Etc/UTC
文件来找出最简单的 TZ 规则:全年与 UTC 的 0 偏移量。
在许多(大多数?)系统上,有一个UTC
->Etc/UTC
符号链接,因此您也可以执行TZ=:UTC
.
TZ=UTC
本身不是 POSIX,但在没有给出偏移量的情况下,在大多数系统上,它被解释为相同TZ=:UTC
(在 中查找时区定义/path/to/zoneinfo/UTC
。但如果 tz 数据库不可用,则不起作用。
另请注意,date
特别是,您可以使用该-u
选项来获取 UTC 日期,无论$TZ
包含什么内容。date -u
相当于TZ=UTC0 date
.