我有一个运行Docker容器的Linux机器人,它正在运行TomEE,并运行我构建的WAR。
在Linux基本框上,我得到的“日期”值为“2017年1月20日10:37:27太平洋标准时间2017”。未设置TZ环境变量。
当我运行以下课程时:
import java.util.Date;
import java.util.TimeZone;
public class DatePrint {
public static void main(String[] args) {
System.out.println("date[" + new Date() + "] tzoffset[" + TimeZone.getDefault().getOffset(new java.util.Date().getTime()) + "]");
}
}
我明白了:
date[Fri Jan 20 10:39:02 PST 2017] tzoffset[-28800000]
这一切都很好。
在我运行的Docker容器中,我将“-v / etc / localtime:/ etc / localtime”作为其中一个卷映射,我显然拥有相同的/ etc / localtime文件。未设置TZ环境变量。当我在容器中运行“date”时,我在与基本主机相同的时区(PST)中获得时间值。
然后我编译并运行与上面相同的Java类,我得到以下内容:
date[Fri Jan 20 18:30:38 UTC 2017] tzoffset[0]
然后我手动将容器中的TZ环境变量(请记住它未在基本主机中设置)设置为“America / Los_Angeles”(我通过查看“/ etc / localtime”符号链接到的文件来验证此值在基础主机上。)
然后我在容器上重新上课并得到了这个:
date[Fri Jan 20 10:35:08 PST 2017] tzoffset[-28800000]
请注意,基本主机和容器上的两个Java版本几乎完全相同。它们都是OpenJDK 1.8.0_111(主机上的b15,容器上的b14)。
那么,有人可以解释这里发生了什么吗?在基本主机上,我有“etc / localtime”指向正确的文件,但我没有设置TZ。它使用“date”和Java类报告正确的时区。在容器上,“/ etc / localtime”指向正确的文件,我最初没有设置TZ。 “date”命令返回正确的值,但Java没有。
我不得不手动将容器上的TZ设置为来自主机的TZ值,这使它工作。我真的不愿意这样做。这对我来说似乎是个黑客。
更新:
我在“localtime(5)”手册页中注意到以下内容:
因为时区标识符是从符号链接目标中提取的 / etc / localtime的名称,此文件可能不是普通文件或硬链接。
所以,这可能是我问题的一部分。它仍然很好奇来自shell的“日期”工作正常,但Java(没有TZ设置)会感到困惑。
答案 0 :(得分:2)
按照吉尔斯在https://unix.stackexchange.com/questions/452559/what-is-etc-timezone-used-for中的回答,由于历史原因,Java读取/etc/timezone
而不是/etc/localtime
。可以在该帖子中找到进一步的解释。
答案 1 :(得分:1)
我和你有同样的问题(CentOS,Docker,OpenJDK)。我们用这种方式解决了这个问题:
不要挂载本地时间,挂载/ etc / timezone。
如果您没有/ etc / timezone文件(例如在CentOS上),您可以执行以下操作(在主机上):
timedatectl | awk '/Time zone:/ {print $3}' > /etc/timezone_host
然后在容器中(例如入口点)
TZ_HOST=$(cat /etc/timezone_host)
echo $TZ_HOST > /etc/timezone
export TZ=$TZ_HOST
dpkg-reconfigure --frontend noninteractive tzdata
答案 2 :(得分:0)
可能转储环境(env命令),LC_ *(通常是LC_ALL)可以影响它。