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。
时区/位置可能是问题吗?
答案 0 :(得分:207)
问题在于,由于夏令时的改变(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
答案 1 :(得分:40)
Andreas's answer中已经提到了此问题的原因。
问题是您想算什么。您声明实际差异应为29而不是28,并询问“位置/区域时间是否可能是个问题” ,这一事实揭示了您实际要计算的内容。显然,您希望摆脱任何时区差异。
我假设您只想计算日期,没有时间和时区。
在下面的示例中,如何正确计算之间的天数,我使用了一个类来精确地表示该日期–一个没有时间和时区的日期– 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);
请注意,ChronoUnit
,DateTimeFormatter
和LocalDate
至少需要Java 8,根据java-7标签,Java 8对您不可用。但是,也许是对未来的读者来说。
如Ole V.V.所述,还有ThreeTen Backport,它将Java 8 Date and Time API功能反向移植到Java 6和7。