为什么 TimeUnit 计算这么不正确?
其他答案是正确的:您正在执行与预期相反的转换。 TimeUnit.MILLISECONDS.convert(difference, TimeUnit.DAYS); 从天转换为毫秒。
但是你怎么得到一个负数?这是因为int 溢出。相反的转换正确执行并产生 434 758 135 795 200 000。这比 32 位 int 可以容纳的要大得多。因此,当您转换为 int 时,最高有效位将被切掉。偶然地,最终成为 int 符号位的位是 1,表示负数。我通常会避免在没有先进行范围检查的情况下进行这种转换。你可能想养成同样的习惯。 Math.toIntExact() 在这里很有帮助。
如何修复:java.time
其他答案基本还是正确的。我仍然想提供一些建议。
如果您认为从一天 16:04 到第二天 16:04 的时间是 1 天,那么您需要考虑时区才能得到正确的结果。例如:
ZoneId zone = ZoneId.of("Africa/Mogadishu");
ZonedDateTime birth = Instant.ofEpochMilli(ts).atZone(zone);
long ageInDays = ChronoUnit.DAYS.between(birth, ZonedDateTime.now(zone));
System.out.println(ageInDays);
在这种情况下,刚才运行代码的结果也是你预期的结果:
58
另一方面,如果您将 1 天定义为 24 小时,无论挂钟读数如何,这里有一种方法可以以亚秒级精度获取年龄。您可以随时转换为之后的几天。
Instant birth = Instant.ofEpochMilli(ts);
Duration age = Duration.between(birth, Instant.now());
System.out.println(age);
System.out.println(age.toDays());
输出:
PT1398H52M13.994841S
58
两行中的第一行表示年龄是 1398 小时 52 分 13.994841 秒。第二行与之前的结果一致。
这两个sn-ps背后的想法也可以组合混合。总而言之,我认为java.time 提供了一些TimeUnit 难以获得的可能性,以及一些非常清晰且不言自明的代码,您不会轻易犯与问题中相同的错误。
链接: