为什么 2020 年 3 月 30 日和 2020 年 3 月 1 日之间的差异错误地给出了 28 天而不是 29 天?

Why does the difference between 30 March and 1 March 2020 erroneously give 28 days instead of 29?

TimeUnit.DAYS.convert(
   Math.abs(
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("30-03-2020 00:00:00").getTime() - 
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("1-03-2020 00:00:00").getTime()
   ),
   TimeUnit.MILLISECONDS)

结果是28,而应该是29。

时间 zone/location 可能是问题所在吗?

问题是由于夏令时的变化(2020 年 3 月 8 日,星期日),这些日期之间有 28 天 23 小时TimeUnit.DAYS.convert(...) 将结果截断 为 28 天。

查看问题(我在美东时区):

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

System.out.println(diff);
System.out.println("Days: " + TimeUnit.DAYS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Hours: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Days: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS) / 24.0);

输出

2502000000
Days: 28
Hours: 695
Days: 28.958333333333332

要修复,请使用没有 DST 的时区,例如UTC:

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

输出

2505600000
Days: 29
Hours: 696
Days: 29.0

这个问题的原因已经在中提到了。

问题是您到底想数什么。您声明实际差异应该是 29 而不是 28,并询问 "location/zone time could be a problem" 是否揭示了您实际想要计算的内容。显然,您想摆脱任何时区差异。

我假设你只想计算天数,没有时间和时区。

Java 8

下面,在如何正确计算两者之间的天数的示例中,我使用的 class 恰好表示 - 没有时间和时区的日期 - LocalDate

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MM-yyyy HH:mm:ss");
LocalDate start = LocalDate.parse("1-03-2020 00:00:00", formatter);
LocalDate end = LocalDate.parse("30-03-2020 00:00:00", formatter);

long daysBetween = ChronoUnit.DAYS.between(start, end);

请注意 ChronoUnitDateTimeFormatterLocalDate 至少需要 Java 8,根据 标签,您无法使用.然而,它可能是给未来的读者的。

正如 Ole V.V 所提到的,还有 ThreeTen Backport,它向后移植 Java 8 日期和时间 API 功能到 Java 6 和7.