gpt4 book ai didi

Java 日历在 MS Windows 中为 `America/Santiago` 区域返回错误的时间

转载 作者:行者123 更新时间:2023-11-30 06:53:30 28 4
gpt4 key购买 nike

我有一个桌面应用程序(必须在 Windows 中运行),它需要在执行特定操作时记录时间戳,但是我在调​​用日历时得到的时间带有错误的时间和正确的时区。
运行一些测试,我发现如果我取消选中 Windows 时区设置上的“自动调整夏令时时钟”复选框,日历会提供正确的时间。 Linux 上不存在此问题。不幸的是,我不允许在 Windows 机器上进行任何更改。

更多信息:

  • Windows 时钟中设置的时区:“美国/圣地亚哥”(-4:00)。
  • 测试代码:
    public class Test2 {

    public static void main(String[] args) {
    SimpleDateFormat sdfBase = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    long milisBase = Calendar.getInstance().getTimeInMillis();
    Calendar calenBase = Calendar.getInstance();
    Date fechaBase = calenBase.getTime();
    String fechaStringBase = sdfBase.format(fechaBase);
    TimeZone tzBase = Calendar.getInstance().getTimeZone();


    System.out.println("Time (in mill): " + milisBase);
    System.out.println("TimeZone: " + tzBase.getDisplayName() + " - " + tzBase.getID() + " -Offset: " + tzBase.getRawOffset());
    System.out.println("Date Calendar: " + fechaBase);
    System.out.println("Fecha StringBase: " + fechaStringBase);
    }
    }

  • 获得以下结果:

    选中“自动调整夏令时时钟”(Windows 时钟:17:50:07)
    Time (in mill): 1464645007120
    TimeZone: Chile Time - America/Santiago -Offset: -10800000
    Date Calendar: Mon May 30 18:50:07 CLT 2016
    Fecha StringBase: 30-05-2016 18:50:07

    未选中“自动调整夏令时时钟”(Windows 时钟:17:50:37)
    Time (in mill): 1464645037914
    TimeZone: GMT-04:00 - GMT-04:00 -Offset: -14400000
    Date Calendar: Mon May 30 17:50:37 GMT-04:00 2016
    Fecha StringBase: 30-05-2016 17:50:37

    示例:当 windows 时钟读取 13:00:00 (America/Santiago -4:00) 时执行该操作,但时间戳将时间标记为 14:00:00(America/Santiago -3:00)。我取消选中windows“自动调整夏令时时钟”,由于它不是 DST,windows 时钟保持不变,我再次执行该操作,时间戳现在读取与 windows 时钟相同的小时。

    我发现了有关该时区的时区和 DST 更改的先前问题,但其中大多数是指智利没有更改为 DST 的 2015 年问题。

    有什么方法可以在不干预 Windows 机器的情况下解决这个问题?

    最佳答案

    概括

    智利当局在最后一刻更改了今年(2016 年)的时区规则。 tz Java中的数据库尚未更新。

    详情如下。

    java.time

    您正在使用与早期 Java 捆绑在一起的旧日期时间类,这些类已被证明很麻烦。在 Java 8 及更高版本中,这些类被 java.time 框架(受 Joda-Time 库的启发)取代。避免旧类(class)。

    关注UTC

    程序员应该首先考虑 UTC .总是 verify the current time in UTC以确保计算机甚至有正确的时间。翻转时区和Daylight Saving Time (DST)变化会让你的大脑受伤,而UTC就是你的阿司匹林。

    在 Java 8 及更高版本中, Instant 类表示 UTC 时间线上的时刻,分辨率以纳秒为单位。

    Instant now = Instant.now();
    System.out.println( "Instant.now(): " + now );

    始终在此问题等帖子中包含 UTC 值。

    主机操作系统的时区无关紧要

    JVM 拥有自己的当前默认时区表示。默认情况下,在大多数实现中,该区域是从主机操作系统的时区设置中选取的。但是 Java 启动配置可以覆盖该默认值。 JVM 内任何应用程序的任何线程中的任何 Java 代码都可以在运行时通过调用 TimeZone.setDefault 来更改 JVM 当前的默认时区。 .

    因此主机操作系统的当前时区设置是无关紧要的。重要的是 JVM 中的当前设置。

    主机操作系统中真正重要的部分是它的硬件时钟是否正确地知道当前时刻。在大多数 JVM 实现中,当前时刻由主机硬件时钟确定,然后 JVM 应用自己的当前默认时区。

    2016 年初为智利重新定义时区

    政客们喜欢摆弄时区和 Daylight Saving Time (DST) .智利也不异常(exception)。参见维基百科文章, Time in Chile .

    据我所知……去年,2015 年,智利在 -03:00 永久停留在 DST。并决定永远不再回到 -04:00 的标准时间.然后他们又改变了主意, announcing in March 2016他们将重新引入冬季的标准时间(南半球,现在是冬季,五月下旬,六月,七月)。在 2016 年 5 月 15 日午夜(几周前), -04:00 的旧标准偏移量开始了。那个标准/冬季时间将持续到 2016 年 8 月 14 日(或者直到他们再次改变主意)。 [带着一粒盐把这一切都拿走。请确认我得到的事实是正确的。]

    这些频繁的更改对需要安装 tz time zone database 的计算机造成严重破坏。更新文件以反射(reflect)最新的摆弄。

    您的操作系统有自己的时区定义副本。 Java 有自己的副本。而其他软件,例如您的数据库引擎,可能有自己的副本。

    当前的 Java 8 Update 92 缺少智利最近的更改

    所以让我们在 Java 8 Update 92 中运行一个测试,看看 tz 的 Java 副本是否已是最新。
    long millis = 1464645007120L;
    Instant instant = Instant.ofEpochMilli ( millis ); // UTC, always.

    ZoneId zoneId = ZoneId.of ( "America/Santiago" );
    ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );

    转储到控制台。
    System.out.println ( "millis: " + millis + "  | instant: " + instant + " | zoneId: " + zoneId + " | zdt: " + zdt );

    millis: 1464645007120 | instant: 2016-05-30T21:50:07.120Z | zoneId: America/Santiago | zdt: 2016-05-30T18:50:07.120-03:00[America/Santiago]



    您可以看到最后一部分的偏移量是 -03:00 .所以在我看来 current version of Java released mid-April不幸的是,它与 3 月份宣布的智利变化不同步。

    从我的读数看来,今天 (2016-05-30) 的 America/Santiago 的正确偏移量应该是 -04:00如此处所示 time.is/Santiago .

    通常我会建议使用 Java tzupdater tool .但是 current download标有 2015 字样所以我认为它也不是最新的。

    我建议向 Oracle 的 Java 团队提交错误报告。

    解决方法

    您可能需要一段时间才能获得 tz 的更正版本。数据库(虽然也许你可以破解你自己的更新——我不知道)。在此之前,作为一种解决方法,也许您可​​以使用 ZoneOffset 在 Java 代码中指定自己的偏移量。类, ZoneId 的子类仅表示与 UTC 的偏移量,没有任何调整异常(例如 DST)的规则。我还没有考虑过其中的含义。警惕。
    ZoneOffset zoneOffset = ZoneOffset.of( -4 ); // Negative four hours for '-04:00'.

    关于Java 日历在 MS Windows 中为 `America/Santiago` 区域返回错误的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37533796/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com