java.time.Clock.systemDefaultZone().getZone() 与 java.util.TimeZone.getDefault().toZoneId() 之间有什么区别?

Kir*_*kow 3 java timezone java-8 java-time

鉴于两者java.time.Clock.systemDefaultZone().getZone()java.util.TimeZone.getDefault().toZoneId()返回相同的输出,两者之间有什么区别吗?

例如这段代码

import java.time.Clock;
import java.util.TimeZone;

public class Main {

  public static void main(String[] args) {
    System.out.println("Clock.systemDefaultZone().getZone() : " 
        + Clock.systemDefaultZone().getZone());
    System.out.println("TimeZone.getDefault().toZoneId() : " 
        + TimeZone.getDefault().toZoneId());
  }

}
Run Code Online (Sandbox Code Playgroud)

返回此输出

Clock.systemDefaultZone().getZone() : Europe/Paris
TimeZone.getDefault().toZoneId() : Europe/Paris
Run Code Online (Sandbox Code Playgroud)

小智 5

两者都返回 JVM 的默认时区(最后,Clock调用TimeZone.getDefault(),如@Kiskae 的回答中所述),但不能保证所有调用每次都会返回相同的值

这是因为默认时区可以更改:

  • 运行 JVM 的系统可以更改其配置。例如,在 Windows 计算机中,此信息是从注册表中读取的,而在 Linux 中,它是从/etc/localtime(通常是指向 中特定文件的链接/usr/share/zoneinfo)或另一个类似文件夹(它在每个版本/发行版中可能有所不同)获取的,或者通过设置TZ环境变量。如果此系统配置发生更改并且 JVM 重新启动,您的代码会突然开始返回不同的值
  • JVM可以配置为使用不同的时区无论操作系统的配置如何,一个例子是,当维护/基础设施团队更改此配置时(有意或无意,并且通常没有告诉开发人员......),然后您的代码不再返回相同的值(并且依赖于时区的所有内容都会突然断裂)
  • 您的应用程序(或运行相同 JVM 的另一个应用程序)调用TimeZone.setDefault()method这将影响运行时在同一 JVM 中运行的所有应用程序,因此如果运行以下代码:

    TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
    System.out.println(ZoneId.systemDefault());
    
    TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
    System.out.println(ZoneId.systemDefault());
    
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    System.out.println(ZoneId.systemDefault());
    
    Run Code Online (Sandbox Code Playgroud)

输出将是:

欧洲/伦敦
美洲/纽约
UTC

请注意,默认时区在运行时更改是多么容易,并且所有后续获取它的调用都会受到影响。Clock.systemDefaultZone().getZone()如果您调用或,也会发生同样的情况TimeZone.getDefault().toZoneId(),因为两者都使用默认时区。

由于这会更改 JVM 的默认时区,因此在同一 JVM 中运行的所有应用程序都将受到影响。这可能会导致难以调试的意外错误。

尽管使用默认时区的方法很方便,但您必须检查您的代码如何依赖它以及如果时区发生更改它会如何受到影响。

如果您不想依赖默认值,理想的选择是使用特定时区,例如ZoneId.of("Europe/Paris")。始终首选IANA 时区名称Region/City(始终采用America/New_York或 等格式Europe/Paris)。避免使用简短的缩写(如CETCEST),因为它们不明确且不标准

您可以通过调用 获取可用时区列表(并选择最适合您的系统的时区)ZoneId.getAvailableZoneIds()