我很难理解以下代码的行为:
TimeZone zone = TimeZone.getTimeZone("Asia/Jerusalem");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);
//printing out 4 different epoch dates
//print out using formatter with TZ
System.out.println(format.format(new Date(-1712458800000L)));
//print using Date's toString method
System.out.println(new Date(-1712458800000L));
System.out.println(format.format(new Date(-57844760000L)));
System.out.println(new Date(-57844760000L));
System.out.println(format.format(new Date(-1888228760000L)));
System.out.println(new Date(-1888228760000L));
System.out.println(format.format(new Date(1456920000000L)));
System.out.println(new Date(1456920000000L));
在我的本地机器(时区GMT+2耶路撒冷)上运行时,在窗口中选中"自动调整夏令时时钟"(这使我成为GMT+3)它产生以下输出:
Sep 26, 1915 11:20:40 PM
Sun Sep 26 23:20:40 IST 1915
Mar 2, 1968 2:00:40 PM
Sat Mar 02 14:00:40 IST 1968
Mar 2, 1910 2:21:20 PM
Wed Mar 02 14:21:20 IST 1910
Mar 2, 2016 2:00:00 PM
Wed Mar 02 14:00:00 IST 2016
但当我取消选中它时(这使我成为GMT+2),运行相同的代码会产生
Sep 26, 1915 11:20:40 PM
Sun Sep 26 23:00:00 GMT+02:00 1915
Mar 2, 1968 2:00:40 PM
Sat Mar 02 14:00:40 GMT+02:00 1968
Mar 2, 1910 2:21:20 PM
Wed Mar 02 14:00:40 GMT+02:00 1910
Mar 2, 2016 2:00:00 PM
Wed Mar 02 14:00:00 GMT+02:00 2016
第一个和第三个示例在使用日期的toString()时的分钟和秒数不同。正如您所看到的,当我使用DateFormat显式设置TZ时,它会打印出相同的结果。我在这里错过了什么?
谢谢!
让我们看看您的1915示例。自unix纪元以来,1712458800000的值是1915-09-26T21:00:00Z,即UTC晚上9点。
现在回到1915年,耶路撒冷的UTC偏移量是+2:2:40,这就是为什么你在输出的第一行中看到"1915年9月26日11:20:40 PM"。然而,当您在Windows中关闭夏令时时,Windows或Java都会将其视为"将此视为UTC+2的固定时区"。这并不是真正的"将此作为耶路撒冷,不更改夏令时,但更改其他夏令时。"因此,您在第二行中看到UTC+2值,即"9月26日星期日23:00:00 GMT+02:00 1915"。
基本上,"这个没有夏令时的时区"的概念是一个非常奇怪的概念,并且已经被简化(同样,我不确定是Windows还是Java)为一个固定的偏移量。当"标准"偏移量没有改变时,这很好,但当它改变时,会引起这样的问题。在相当现代的历史上,大多数时区都没有改变其标准偏移量,但在20世纪初也有相当多的变化。