Any difference between java.time.Clock.systemDefau

2019-01-02 21:30发布

问题:

Is there any difference in between the two, given that both java.time.Clock.systemDefaultZone().getZone() and java.util.TimeZone.getDefault().toZoneId() return the same output.

For instance this code

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());
  }

}

returns this output

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

回答1:

Both returns the JVM's default timezone (in the end, Clock calls TimeZone.getDefault(), as explained in @Kiskae's answer), but it's not guaranteed that all calls will always return the same value everytime.

That's because the default timezone can be changed:

  • the system where the JVM is running can change its configuration. In Windows machines, for example, this information is read from the registry, while in Linux it gets from /etc/localtime (usually a link to a specific file in /usr/share/zoneinfo) or another similar folder (it can vary in each version/distribution), or by setting the TZ environment variable. If this system configuration changes it and the JVM is restarted, suddenly your code starts returning different values
  • the JVM can be configured to use a different timezone, regardless of OS's config. One example is when the maintanance/infrastructure team changes this configuration (on purpose or by accident, and usually without telling the developers...) and then your code doesn't return the same values anymore (and everything that depends on the timezone will suddenly break)
  • your application (or another application running the same JVM) calls TimeZone.setDefault() method. This will affect all the applications running in the same JVM, at runtime, so if you run this code:

    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());
    

The output will be:

Europe/London
America/New_York
UTC

Note how easily the default timezone is changed at runtime, and all subsequent calls to get it are affected. The same will happen if you call Clock.systemDefaultZone().getZone() or TimeZone.getDefault().toZoneId(), because both uses the default timezone.

As this changes the JVM's default timezone, all applications running in the same JVM will be affected by it. This might lead to unexpected errors that are hard to debug.

Although the methods that use the default timezone are convenient, you must check how your code depends on it and how it can be affected if the zone changes.

If you don't want to depend on the default, the ideal is to use a specific timezone, such as ZoneId.of("Europe/Paris"). Always prefer IANA timezones names (always in the format Region/City, like America/New_York or Europe/Paris). Avoid using the short abbreviations (like CET or CEST) because they are ambiguous and not standard.

You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().



回答2:

Looking at the source code on grepcode, they end up executing the exact same methods, resulting in the same result. Clock.systemDefaultZone() calls ZoneId.systemDefault(), which returns TimeZone.getDefault().toZoneId():

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



标签: