java.time.Clock.systemDefaultZone()。getZone()vs java.util.TimeZone.getDefault()。toZoneId()之间的任何区别?

时间:2017-08-21 09:44:43

标签: java java-8 timezone 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());
  }

}

返回此输出

Clock.systemDefaultZone().getZone() : Europe/Paris
TimeZone.getDefault().toZoneId() : Europe/Paris

2 个答案:

答案 0 :(得分:4)

查看grepcode上的源代码,它们最终会执行完全相同的方法,从而产生相同的结果。 Clock.systemDefaultZone()调用ZoneId.systemDefault(),返回TimeZone.getDefault().toZoneId()

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/time/ZoneId.java#ZoneId.systemDefault%28%29

答案 1 :(得分:3)

两者都返回JVM的默认时区(最后,Clock调用TimeZone.getDefault(),如@Kiskae's answer中所述),但并不能保证全部通话始终每次都返回相同的值

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

  • 运行JVM的系统可以更改其配置。例如,在Windows机器中,这是information is read from the registry,而在Linux中,它来自/etc/localtime(通常是指向/usr/share/zoneinfo中特定文件的链接)或其他类似文件夹(每个文件夹都有所不同)版本/分发),或通过设置TZ环境变量。如果此系统配置更改它并重新启动JVM,则突然您的代码开始返回不同的值
  • JVM can be configured to use a different timezone,无论操作系统的配置如何。一个例子是当维护/基础设施团队改变这种配置时(故意或偶然,并且通常不告诉开发人员......)然后你的代码不再返回相同的值(以及依赖于时区会突然破裂)
  • 您的应用程序(或运行相同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());
    

输出将是:

  

欧洲/伦敦
  美国/纽约
  UTC

请注意在运行时更改默认时区的容易程度,以及所有后续调用都会受到影响。如果您拨打Clock.systemDefaultZone().getZone()TimeZone.getDefault().toZoneId(),则会发生同样的情况,因为两者都使用默认时区。

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

尽管使用默认时区的方法很方便,但您必须检查代码的依赖程度以及区域更改时如何影响代码。

如果您不想依赖默认设置,理想情况是使用特定时区,例如ZoneId.of("Europe/Paris")。始终更喜欢IANA timezones names(始终采用Region/City格式,例如America/New_YorkEurope/Paris)。 避免使用简短缩写(例如CETCEST),因为它们是ambiguous and not standard

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