Java 更改操作系统时区不会更改JVM默认时区

Java 更改操作系统时区不会更改JVM默认时区,java,linux,date,timezone,Java,Linux,Date,Timezone,我在Linux机器上运行Java程序,但是当我使用System.out.println(new Date())时,它总是打印相同的时区(EAT),即使我将链接/etc/localtime更改为不同的时区,Date命令也会显示正确的时区(被/etc/localtime引用的一个)。 我知道Date.toString()使用java默认时区,该时区必须与主机操作系统时区相同,但在我的情况下,这不会发生,因为JVM默认时区从未更改。 我的问题是:Java从何处获得默认时区,即哪个文件或环境变量 我正在

我在Linux机器上运行Java程序,但是当我使用
System.out.println(new Date())
时,它总是打印相同的时区
(EAT)
,即使我将链接
/etc/localtime
更改为不同的时区,
Date
命令也会显示正确的时区(被
/etc/localtime
引用的一个)。 我知道
Date.toString()
使用java默认时区,该时区必须与主机操作系统时区相同,但在我的情况下,这不会发生,因为JVM默认时区从未更改。 我的问题是:Java从何处获得默认时区,即哪个文件或环境变量


我正在使用Red Hat Enterprise Linux Server 6.5版(Santiago)和openjdk 1.7,这在堆栈溢出方面已经讨论过很多次了,请搜索更多信息

简单地说


不,
java.util.Date
没有时区。
它总是在UTC。不幸的是,它的
toString
方法在生成字符串时动态应用JVM的当前默认时区,这是一个用意良好但不明智的反功能。甚至更令人困惑的是:实际上在字符串中隐藏了一个时区e
java.util.Date
类,但与本讨论无关。令人困惑?确实如此。这些旧的日期时间类是糟糕设计的一团乱麻

避免这些麻烦的旧日期时间类。它们现在是遗留的,被java.time类取代。不要使用
date
使用
java.time.Instant
以UTC为单位。对于其他区域,应用
ZoneId
以获得
ZonedDateTime

我的问题是:Java从哪里获得默认时区

取决于Java的实现

通常,默认值是检测主机操作系统的当前默认时区,并将其复制为JVM的当前默认时区。JVM启动后,两者分开。主机操作系统可以更改其默认时区而不影响JVM。反之亦然,JVM可以更改其当前默认时区而不影响JVM但是,就我所知,这种行为是依赖于实现的,而不是强制的

在启动期间传递给JVM的参数可能会设置初始默认时区,以覆盖主机操作系统的默认检测

注意:运行时不可预测-JVM内任何应用程序的任何线程中的任何代码都可能随时更改JVM的当前默认时区,从而立即影响该JVM所有应用程序的所有代码

因此,由于所有这些原因,您可以看到依赖默认时区是不明智的。最好始终传递可选的
ZoneId
参数,以明确指定所需/预期的时区

通常,最佳实践是在UTC中工作、思考、存储数据和交换数据

Instant instant = Instant.now() ;  // Always in UTC. 
仅在需要时应用其他时区,例如向用户演示

ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

java.time类在生成或解析字符串时使用标准ISO 8601格式。对于其他格式,请使用
DateTimeFormatter
类。您可以选择在格式化程序上设置时区,以便在生成字符串期间动态应用。

根据我对代码的理解,它使用
/etc/timezone
文件.
java.util.Date
没有任何内部时区,但如果使用方法
Date.toString()打印代码,则只使用JVM运行代码的时区
。使用合适的格式化程序在您想要的时区打印您的对象。在Linux中,如果未设置
TZ
变量,并且
/etc/sysconfig/clock
中没有
zone
条目,它将使用
/etc/localtime
(在不同的发行版中可能有所不同,但在RedHat中我相信就是这样),但可能与您的情况有关(不确定)。或者可能您没有重新启动JVM,因此它没有获得新的配置。或者代码在JVM中运行,并带有
user.timezone
属性集,该属性集覆盖了系统的配置。或者可能JVM中运行的其他程序在JVM启动后更改了JVM的时区设置(不太可能,但值得一提)@MenoHochschild我知道Date没有时区;我的问题是关于它的toStringI know Date类使用的默认时区没有时区;我已经更新了我的问题,以便更清楚