java.time.Clock.systemDefaultZone().getZone() 与 java.util.TimeZone.getDefault().toZoneId() 之间有什么区别? [英] Any difference between java.time.Clock.systemDefaultZone().getZone() vs java.util.TimeZone.getDefault().toZoneId()?

查看:24
本文介绍了java.time.Clock.systemDefaultZone().getZone() 与 java.util.TimeZone.getDefault().toZoneId() 之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如这段代码

import java.time.Clock;导入 java.util.TimeZone;公共课主要{公共静态无效主(字符串 [] args){System.out.println("Clock.systemDefaultZone().getZone() :"+ Clock.systemDefaultZone().getZone());System.out.println("TimeZone.getDefault().toZoneId() :"+ TimeZone.getDefault().toZoneId());}}

返回这个输出

Clock.systemDefaultZone().getZone() :欧洲/巴黎TimeZone.getDefault().toZoneId() :欧洲/巴黎

解决方案

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

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

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

    TimeZone.setDefault(TimeZone.getTimeZone("欧洲/伦敦"));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());

输出将是:

<块引用>

欧洲/伦敦
美国/纽约
世界标准时间

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

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

虽然使用默认时区的方法很方便,但您必须检查您的代码如何依赖它以及如果时区发生变化会如何影响它.

如果您不想依赖默认值,理想的做法是使用特定的时区,例如 ZoneId.of("Europe/Paris").始终更喜欢 IANA 时区名称(始终采用 Region/City 格式,例如 America/New_YorkEurope/Paris).避免使用简短的缩写(如 CETCEST),因为它们模棱两可且不标准.

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

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

解决方案

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

这篇关于java.time.Clock.systemDefaultZone().getZone() 与 java.util.TimeZone.getDefault().toZoneId() 之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆