在JAVA中使用Date类处理TimeZone更改

我正在尝试打印当前系统日期和时间,如下所示,

public class PrintDate { public void getDate(){ while(true){ System.out.println(new Date()); } } public static void main(String[] args) { new PrintDate().getDate(); } } 

这个无限循环按预期打印当前系统时间戳,当我在操作系统中更改日期或时间但没有时区更改时,它工作正常。

示例:

  1. 我启动了上面的代码,它按预期连续打印当前系统时间戳。
  2. 当我更改系统日期或时间时,它会成功反映在代码中。
  3. 当我更改系统时区时,它没有反映在代码中。 自程序启动以来,它仍然显示相同的时区。

我可以知道这背后的原因吗?

时区是流程环境的一部分。 全局更改系统的时区只会影响新进程。

另请参见如何设置java.util.Date的时区? :

请注意,java.util.Date对象本身不包含任何时区信息 – 您无法在Date对象上设置时区。 Date对象包含的唯一内容是自“epoch” – 1970年1月1日00:00:00 UTC以来的毫秒数。

正如ZZ Coder所示,您在DateFormat对象上设置时区,告诉它您要在哪个时区显示日期和时间。

neuhaus的答案是正确的。

如果您意味着在运行该代码时更改了主机操作系统的时区,请知道Java虚拟机(JVM)具有其自己的当前默认时区。

通常,默认值是从主机操作系统的默认值中获取的。 如果是这样,那么这必然意味着您的Java实现仅在启动时检测主机时区,而不是检查主机操作系统时区的后续更改。

您的JVM的时区也可以在启动时设置为配置参数。 在这种情况下,我认为JVM会故意忽略主机操作系统的时区变化。

该JVM中任何应用程序的任何线程中的任何Java代码都可以在运行时期间的任何时刻更改JVM的当前默认时区。 同样,我认为JVM会故意忽略主机操作系统的时区变化。

java.util.TimeZone.getDefault()的类doc概述了确定当前默认时区的步骤。

如果缓存的默认TimeZone可用,则返回其克隆。 否则,该方法采用以下步骤来确定默认时区。

•如果user.timezone属性值可用,则将其用作默认时区ID。

•检测平台时区ID。 平台时区和ID映射的来源可能随实现而变化。

•如果给定或检测到的时区ID未知,请使用GMT作为最后的手段。

从ID创建的默认TimeZone将被缓存,并返回其克隆。 user.timezone属性值在返回时设置为ID。

在我的阅读中,它说JVM不会检测到对主机操作系统设置的任何更改。 一旦启动,一旦确定了默认值,它就会存储在该user.timezone属性(以及缓存中的值)中,直到通过调用setDefault更改。

java.time

您正在使用旧的java.util.Date类,该类已被Java 8中的java.time框架取代。

使用java.time.ZonedDateTime类并指定所需/预期的时区。

 ZoneId zoneId = ZoneId.of( " America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.now( ZoneId ); 

您几乎不应该依赖于JVM的当前默认时区(也不是当前的默认Locale )。

 import java.util.Date; public class DateDemo { public static void main(String args[]) { //Instantiate a Date object Date date = new Date(); //display time and date using toString() System.out.println(date.toString()); } }