java - Java中的时区问题

标签 java windows timezone timezone-offset

我正在使用这个简单的代码来获取系统中已设置的当前时区的时区 ID。

public class Main {

    public static void main(String[] args)
    {   TimeZone timezone = TimeZone.getDefault();
        System.out.println(timezone.getID());
    }
}

我使用 tzutil/g 来确定时区,并使用 tzutil/s 来设置时区。 我观察到,当时区设置为东部标准时间时,上述代码返回 id 为America/New_York,但当它设置为东部标准时间_dstoff时> 然后我得到的 id 为 GMT-05:00 这是不受欢迎的。我想要大陆/城市形式的输出。

我怎样才能得到它?

最佳答案

我的第一个答案是,你不应该关心 JVM 的默认时区设置。无论如何,您的 Java 代码都不应该依赖它。默认设置可以随时从程序的另一部分或同一 JVM 中运行的另一个程序更改,因此很脆弱。相反,请在时区敏感操作中指定明确的时区。

如果您仍然想依赖默认值,可以通过以下技巧将其设置为某个大陆/城市时区(如果恰好是GMT-05:00)您认为不受欢迎的。

    ZoneId defaultZoneId = ZoneId.systemDefault();
    ZoneId desiredTimeZone = null;
    if (defaultZoneId.equals(ZoneId.of("GMT-05:00"))) {
        // Pick a date in summer
        LocalDate dateInSummer = Year.now().atMonthDay(MonthDay.of(Month.JULY, 7));
        DateTimeFormatter zoneFormatter = DateTimeFormatter.ofPattern("zzzz", Locale.ENGLISH);
        for (String zid : ZoneId.getAvailableZoneIds()) {
            ZoneId zone = ZoneId.of(zid);
            String timeZoneName = dateInSummer.atStartOfDay(zone).format(zoneFormatter);
            if (zid.startsWith("America/") && timeZoneName.equals("Eastern Standard Time")) {
                desiredTimeZone = zone;
                break;
            }
        }
    }

    System.out.println("Time zone: " + desiredTimeZone);

在我的 JDK 11 上,我得到了:

Time zone: America/Panama

不幸的是,要将其设置为默认值,我们必须经历设计不佳且早已过时的 TimeZone 类:

    TimeZone.setDefault(TimeZone.getTimeZone(desiredTimeZone));

还有一个原因警告不要使用美洲/巴拿马或其他时区 ID 而不是 GMT-05:00:虽然巴拿马自 1908 年的某个时间以来一直使用 GMT/UTC 的偏移量 -05:00,但并不总是如此,因此对于历史日期,您会使用它得到错误的时间。

根据 timeanddate.com,全年使用东部标准时间(无夏令时/DST)的地方是:

  • 努勒维特 - 仅限南安普敦岛(珊瑚港)(加拿大)(America/Coral_Harbour 时区)
  • 金塔纳罗奥州(墨西哥)(美国/坎昆时区)
  • 开曼群岛(美洲/开曼)
  • 牙买加(美国/牙买加)
  • 巴拿马(美洲/巴拿马)

我的 Java 还列出了 America/Atikokan(也在加拿大)。

该列表不包括美国的任何地点。我相信以上都没有一直使用偏移量 -05:00 。也就是说,它们中的每一个在历史上的某个时刻都有不同的偏移量,Java 将为历史日期使用该不同的偏移量。

那么使用哪个时区?

编辑:Andreas 在评论中指出,Etc/GMT+5 和 SystemV/EST5 都没有我提到的将偏移量应用于可能意外的历史日期的问题。所以你可以考虑其中之一。在我看来,它们各自的优点是:

                                    America/Xxx Etc/GMT+5 SystemV/EST5 GMT-05:00
Official IANA time zone?                Yes        Yes
With slash?                             Yes        Yes        Yes
Continent/city?                         Yes
Good for historical dates?                         Yes        Yes         Yes
Prints as EST/Eastern Standard Time?    Yes                   Yes

(您的起点 GMT-05:00 仅用于比较。当然,哪些确实适合历史日期取决于您对这些日期的要求。)

链接

关于java - Java中的时区问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60236559/

相关文章:

windows - 跨 Linux、Windows 运行程序集

windows - Windows 上没有 LLC?

php - Laravel 调度程序如何处理夏令时?

Java 数组 : Unexpected behavior regarding size?

java - Android - NoClassDefFoundError

java - 简单 xml : how to annotate my "point" class

java - 如何仅在运行时从类路径嵌入 keystore 证书?

windows - 如何使用 Delphi 2010 以编程方式确定 Windows 的性能设置

Python 字符串到 Django 时区(知道日期时间)

ruby-on-rails - 将 time_zone_select 默认为系统时区