Java 8中Instant.EPOCH的时区不正确

6

我有一台Linux机器,其时区设置为Asia/Qatar。当我使用格式化程序打印Instant.EPOCH时,它会给出错误的区域信息,而对于Instant.now(),区域信息是正确的。以下是我的代码及其输出。请问有人可以帮帮我,为什么会出现这种差异?

import java.util.Date;
import java.time.format.DateTimeFormatter;
import java.time.Instant;
import java.time.ZoneId;

public class DateTest {
   public static void main(String[] args) {
      String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";
      Instant myInstant = Instant.EPOCH;
      Instant myInstantNow = Instant.now();
      DateTimeFormatter formatter =  DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault());
      System.out.println(formatter.format(myInstant));
      System.out.println(formatter.format(myInstantNow));
   }
}

代码的输出结果是:
1970-01-01T04:00:00.000 +0400
2019-09-29T18:30:14.766 +0300

Java版本: "1.8.0_181"

如果我在Windows上运行相同的代码,它能正常工作。对于Instant.EPOCH,我也得到了+0300。


1
你的Windows电脑设置的是哪个时区?我相信Windows的时区是不同的,所以Asia/Qatar可能在Windows设置中不可选。另外,你的Windows电脑是否也运行着Java版本1.8.0_181? - Ole V.V.
2个回答

8

简述:你在Linux上的结果是正确的,与预期相符。

1970年卡塔尔比格林威治时间(GMT)快4小时。时代纪元是1970年1月1日。1972年,卡塔尔将时区从+04:00更改为+03:00。来源:Doha,Qatar(Ad Dawhah)时区中,在“Time zone changes for:”下拉菜单中选择1970-1979。

那么,你的Windows电脑出了什么问题呢?我猜测:根据我阅读Windows文档Default Time Zones,Windows在设置中没有亚洲/卡塔尔时区。因此,我的猜测是,根据我刚刚链接的表格,你的Windows设置为“阿拉伯标准时间”,这将转换为UTC+03:00。阿拉伯标准时间(或阿拉伯标准时间;缩写为AST)也用于科威特、伊拉克和也门等其他国家。但是这些国家自1970年及之前一直处于+03:00偏移量。因此,当Java尝试从Windows获取默认时区时,它可能会轻易地获取具有此历史记录的时区,而不是卡塔尔的正确历史记录。正如我所说,现在只是一个猜测。但你可以很容易地验证。在你的Windows电脑上尝试:

    System.out.println(ZoneId.systemDefault());

如果它打印出 "Asia/Qatar",那么我的猜测是错误的。如果它打印出类似于 "GMT+03:00" 的东西,则我是正确的。如果它打印出其他内容,则可能是或可能不是。
编辑:进一步的链接:AST - 阿拉伯标准时间(标准时间) 提供科威特作为一个例子城市。 科威特城的年度时间更改 告诉我们,自1950年以来,科威特也一直处于 +03:00 的偏移量上。
进一步编辑:感谢您确认Java在您的Windows计算机上打印Asia/Riyadh作为其默认时区。沙特阿拉伯的利雅得自1947年以来一直处于+03:00的偏移量上,这至少部分解释了为什么您会获得此偏移量,即使对于卡塔尔来说并不正确。 来源

1
在我最初的观察中,我认为由于您的日期显示1月(冬季)和9月(夏季),所以存在夏令时差异,但是据我所知,卡塔尔现在不使用这个系统。
然而,当我们回顾过去时,我们可以发现,卡塔尔于1972年7月1日从GST(-04:00)更改为AST(-03:00)的UTC区域,因此我想结果是正确的。这些信息可以在Doha,Qatar的时区和时钟变化中找到。
问题在于Windows机器使用当前的卡塔尔UTC,因为基于Windows的平台跟踪一些历史记录。请参阅注册表中写入的Windows时区可靠吗?

5
有趣。但 JVM 有自己的时区数据。它是否使用 Windows 的时区数据?(我没有 Windows 计算机来测试。) - Ole V.V.
3
JVM本身并不保存时钟信息,而是保存自己的时区数据。因此,对于旧版Java安装/版本,我们需要使用“时区更新工具”(Timezone Updater Tool)来更新时区数据以保持最新状态。 - Ole V.V.
1
卡塔尔从未观察过夏令时(DST)。你第一段的措辞在这一点上是误导性的。 - Basil Bourque
@BasilBourque:我说“在第一次观察时……”和“……卡塔尔不使用”。我认为我的最初想法是针对夏令时的,而我在其他地方找到了解决方案。我不是母语人士,所以我承认我可能错了 - 你能重新表述一下吗?请随意这样做:)) - Nikolas Charalambidis
1
@Nikolas 我喜欢你对如何让你的帖子更清晰的兴趣。我认为,如果我们省略了一直在进行的思考过程,只呈现结论,通常(尽管不总是)会有所帮助。在我看来,这里的一个选项是省略介绍,从“当我们回顾过去时…”开始。如果你愿意,你可以在最后加上类似“我们可以排除DST作为问题的来源,因为卡塔尔不使用DST”的内容。仅供参考。 - Ole V.V.
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接