Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java日历在MS Windows中返回的'America/Santiago'区域的时间错误_Java_Date_Time_Calendar_Timezone - Fatal编程技术网

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

Java日历在MS Windows中返回的'America/Santiago'区域的时间错误,java,date,time,calendar,timezone,Java,Date,Time,Calendar,Timezone,我有一个桌面应用程序(必须在Windows中运行),在执行特定操作时需要记录时间戳,但调用日历时得到的时间带有错误的小时和正确的时区。 运行我发现的一些测试时,如果我取消选中windows时区设置上的“自动调整夏令时时钟”复选框,日历将提供正确的小时数。Linux上不存在此问题。不幸的是,我不允许在windows计算机上进行任何更改 更多信息: 在windows时钟中设置时区:“美国/圣地亚哥”(-4:00) 测试代码: public class Test2 { public sta

我有一个桌面应用程序(必须在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)

未选中“自动调整夏令时时钟”(Windows时钟:17:50:37)

示例:当windows时钟读数为13:00:00(美国/圣地亚哥-4:00)时执行该操作,但时间戳标记时间为14:00:00(美国/圣地亚哥-3:00)。我取消选中windows“自动调整夏令时时钟”,因为它不是DST,所以windows时钟保持不变,我再次执行该操作,时间戳现在读取的时间与windows时钟的时间相同

我发现了之前关于时区和该时区的DST变化的问题,但大多数问题都涉及到2015年的问题,智利没有改为DST

有没有办法在不干预windows机器的情况下解决这个问题?

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

详情如下

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

关注UTC 程序员应该首先考虑问题。始终确保计算机的时间正确。翻转时区和变化会让你的大脑受伤,UTC是你的阿司匹林

在Java8及更高版本中,该类以UTC表示时间线上的一个时刻,分辨率为纳秒

Instant now = Instant.now();
System.out.println( "Instant.now(): " + now );
始终在诸如此问题的帖子中包含UTC值

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

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

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

2016年初智利重新定义时区 政客们喜欢摆弄时区和时间。智利也不例外。请参阅维基百科文章

据我所知……去年,即2015年,智利在
-03:00
永久停留在DST上,并决定永远不再回到
-04:00
的标准时间。然后他们又改变了主意,他们将重新引入冬天的标准时间(南半球,现在是冬天,5月底,6月,7月)。2016年5月15日午夜(几周前),旧的标准偏移量
-04:00
开始生效。标准/冬季时间将持续到2016年8月14日(或直到他们再次改变主意)。[对所有这些都不屑一顾。请证实我的事实是正确的。]

这些频繁的变化对计算机造成了巨大的破坏,计算机需要更新其文件以反映最新的变化

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

当前的Java8更新92缺少最近的更改 因此,让我们在Java8Update92中运行一个测试,看看
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 );
米利斯:1464645007120 |即时:2016-05-30T21:50:07.120Z |地区:美洲/圣地亚哥| zdt:2016-05-30T18:50:07.120-03:00[美洲/圣地亚哥]

您可以看到最后一部分中的偏移量是
-03:00
。因此,在我看来,不幸的是,该计划没有跟上智利3月份宣布的变化

从我的读数来看,今天(2016-05-30)美国/圣地亚哥的正确偏移量应该是
-04:00
,如图所示

通常我会建议使用。但是这个标签上有单词
2015
,所以我认为它也不是最新的

我建议在Oracle的Java团队提交一份bug报告

变通办法 您可能需要一段时间才能获得
tz
数据库的正确版本(尽管您可能需要修改自己的更新,我不知道)。在此之前,作为一种解决方法,您可能可以使用类在Java代码中指定自己的偏移量,该类是的一个子类,只表示与UTC的偏移量,而不需要任何规则来调整异常,例如DST。我还没有想清楚其中的含义;小心点

ZoneOffset zoneOffset = ZoneOffset.of( -4 ); // Negative four hours for '-04:00'.

提供您的代码。第一个实例名为“calen”,而日期是从“calendar”读取的。两个实例可能使用不同的配置。或者你需要更新到真实的代码。getInstance是一个函数调用,我甚至看不到这段代码是如何通过编译器的,忘记了其中固有的运行时错误。我将为测试用例和
System.out.println ( "millis: " + millis + "  | instant: " + instant + " | zoneId: " + zoneId + " | zdt: " + zdt );
ZoneOffset zoneOffset = ZoneOffset.of( -4 ); // Negative four hours for '-04:00'.