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。时区/地点会不会是问题所在?
问题是,由于夏令时的转变(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);
输出
``lang-none 2502000000 天数: 28 小时。695 天数: 28.9583333333332
要解决这个问题,请使用没有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();
*输出*
``lang-none
2505600000
天数: 29
小时。696
天数: 29.0
这个问题的原因在Andreas'的回答中已经提到。
问题是*你到底想算什么。你说实际的差异应该是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,根据[tag:java-7]标签,你无法使用。然而,对于未来的读者来说,也许是的。
正如Ole V.V.提到的,还有ThreeTen Backport,它将Java 8的日期和时间API功能回传到Java 6和7。