Calendar.setTimeInMillis 错误 - 为什么?

Calendar.setTimeInMillis error - why is that?

calendar 得到了错误的 unix 时间。

long millis = 1568814839L;
System.out.println(millis); //1568814839
Calendar.getInstance(TimeZone.getTimeZone("Asia/Tashkent"));
calendar.setTimeInMillis(millis);
System.out.println(calendar.get(Calendar.MILLISECOND));//839

我该怎么办? Calendar.YEAR 应该是 2019 年。但是,日历给我 1970,为什么?

错误是由于您混淆了以毫秒为单位的时间和以秒为单位的时间。 1568814839L 是自 1970 年 1 月 1 日以来的秒数,但您将其视为毫秒。这很容易检查:

long millis = 1568814839L;
System.out.println(millis); //1568814839
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tashkent"));
System.out.println(calendar.getTimeInMillis()); //1568820981321
calendar.setTimeInMillis(millis);
System.out.println(calendar.get(Calendar.YEAR));//839

这将产生:

1568814839
1568820981321
1970

如您所见,您的数字相差 3 个数量级。在您的毫秒数末尾添加三个 0:

long millis = 1568814839000L;
...
System.out.println(calendar.get(Calendar.YEAR));

现在你得到:

1568814839000
1568821211006
2019

java.time

现代代码将使用 java.time,现代 Java 日期和时间 API。

将自 1970-01-01T00:00Z 以来的整秒数输入 Instant class:

    ZonedDateTime zdt = Instant.ofEpochSecond(1_568_814_839L)
                               .atZone(ZoneId.of("Asia/Tashkent"));
    System.out.println(zdt);
    System.out.println("Year: " + zdt.getYear());
    System.out.println("Millisecond of second: "
                        + zdt.get(ChronoField.MILLI_OF_SECOND));

输出为:

2019-09-18T18:53:59+05:00[Asia/Tashkent]
Year: 2019
Millisecond of second: 0

正如其他人所说,您的数字是自纪元以来的秒数,而不是毫秒。

问题:我可以在 Android 上使用 java.time 吗?

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

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

链接