Java:为什么Calendral.setTimeInMillis(0)设置的时间不正确

Java: why does Calendral.setTimeInMillis(0) set incorrect time

我的 Android 应用程序(在 java 中,在 Android Studio 中)使用 class `Calendar'。之后

Calendar cal=Calendar.getInstance();
cal.setTimeInMillis(0);
Log.i("Interim",cal.getTime().toString());

正在生成这样的输出:I/Interim: Thu Jan 01 03:00:00 GMT+02:00 1970。我的时区是 GMT+02:00(乌克兰基辅),一月份的夏令时不适用。为什么日历时间设置为 03:00?我希望 00:00(不考虑时区)或 02:00(考虑时区),但为什么 03:00?

提前感谢任何想法

PS 为了澄清情况,我将 Calendar 时区设置为 GMT 并获取小时值:

Calendar cal=Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTimeInMillis(0);
Log.i("Interim hours",Integer.toString(cal[i].get(Calendar.HOUR)));
Log.i("Interim",cal.getTime().toString());

与预期相反,输出是:

I/Interim hours: 0

I/Interim: Thu Jan 01 03:00:00 GMT+02:00 1970

因此,小时字段的值为 0,但时间为 03:00。 我刚刚听说 1975 年 6 月 13 日轮班 1 小时(见下面的答案),但这似乎只涉及越南 TZ,不是吗?

如果您在 1975 年 6 月 13 日之前输入,结果总是 +1 小时。那天有25个小时。您可以查看它 https://currentmillis.com/ 。如果输入 13/06/1975 我们得到 171824400000 和 12/06/1975 我们得到 171734400000.

171824400000 - 171734400000 = 90000000。

90000000 / (60*60*1000) = 25 (???)

因此,如果您在 1975 年 6 月 13 日之前输入,我认为您可以增加 1 小时

请区分时区时差。您的时区是 Europe/Kiev(存在英文拼写的地方使用时区 ID 中地名的英文拼写)。 Europe/Kiev 一月份的偏移量为 +02:00。直到 10 月 27 日,它的偏移量为 +03:00,并且由于夏令时(夏令时,DST),将从 3 月 29 日起再次出现。可能会让一些人感到惊讶的是,它从 1944 年到 1980 年一直处于偏移量 +03:00。所以在那个时代——1970 年 1 月 1 日 00:00 UTC——乌克兰的时间是 3:00。所以对于乌克兰,这部分输出是正确的。

简而言之:时区包含该时区使用的 UTC/GMT 的历史、现在和已知的未来偏移量。 GMT+02:00是一个偏移量,不是时区。

java.time 和 ThreeTenABP

这是获得我认为您想要的东西的现代方法:

    ZonedDateTime epochInUkraine = Instant.EPOCH.atZone(ZoneId.of("Europe/Kiev"));
    System.out.println(epochInUkraine);

这些行的输出是:

1970-01-01T03:00+03:00[Europe/Kiev]

如果您想要的打印输出与打印老式 java.util.Date 对象的打印输出类似:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
    System.out.println(epochInUkraine.format(formatter));

Thu Jan 01 03:00:00 EET 1970

不过,您可能会找到更适合您的观众的输出格式。我把那部分留给你自己。

出了什么问题?

Why does Calendar.setTimeInMillis(0) set incorrect time?

没有。 Calendar class 及其子 class 设计不佳且早已过时,但 setTimeInMillis(0) 设置了正确的时间。您还已经注意到,当您的 Calendar 使用 UTC 时,其上午或下午的时钟时间(0 到 11)为 0。您如何获得 03:00:00 GMT+02:00 的输出与 0[= 之间的矛盾103=] 和 +02:00?可能的解释包括:

  • 很可能是您这边的错误。这不是来自您设置为 0 的 Calendar,或者您在输入问题时复制的输出不准确。如果您再次检查是否可以重现该输出,我很想听听。
  • 不太可能是 Date.toString() 中的错误,当您打印从 cal.getTime() 获得的 Date 时,它会被隐式调用。
  • 仍然不太可能是 Calendar.getTime() 中的错误,它给你来自 Calendar 的错误 Date 对象。

问题:java.time 不需要 Android API 26 级吗?

java.time 在新旧 Android 设备上都能很好地工作。它只需要至少 Java 6.

  • 在 Java 8 和更新的 Android 设备上(从 API 级别 26)内置现代 API。
  • In-Android Java 6 和 7 得到 ThreeTen Backport,现代 classes 的 backport(ThreeTen for JSR 310;见底部的链接) .
  • 在(较旧的)Android 使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间 classes。

链接