Java 为什么 2020 年 3 月 30 日和 2020 年 3 月 1 日之间的差值错误地给出了 28 天而不是 29 天?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/60071278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does the difference between 30 March and 1 March 2020 erroneously give 28 days instead of 29?
提问by Joe
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)
The result is 28, while it should be 29.
结果是 28,而它应该是 29。
Could the time zone/location be the problem?
时区/位置可能是问题吗?
采纳答案by Andreas
The problem is that because of Daylight Saving Time shift (on Sunday, March 8, 2020), there are 28 days and 23 hoursbetween those dates. TimeUnit.DAYS.convert(...)
truncatesthe result to 28 days.
问题在于,由于夏令时的变化(2020 年 3 月 8 日星期日),这些日期之间有28 天 23 小时。将结果TimeUnit.DAYS.convert(...)
截断为 28 天。
To see the problem (I'm in US Eastern time zone):
要查看问题(我在美国东部时区):
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);
Output
输出
2502000000
Days: 28
Hours: 695
Days: 28.958333333333332
To fix, use a time zone that doesn't have DST, e.g. UTC:
要修复,请使用没有 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();
Output
输出
2505600000
Days: 29
Hours: 696
Days: 29.0
回答by MC Emperor
The cause of this problem is already mentioned in Andreas's answer.
安德烈亚斯的回答中已经提到了这个问题的原因。
The question is whatexactly you want to count. The fact that you state that the actual difference should be 29 instead of 28, and ask whether "location/zone time could be a problem", reveals what you actually want to count. Apparently, you want to get rid of any timezone difference.
问题是你到底想计算什么。您声明实际差异应该是 29 而不是 28,并询问“位置/区域时间是否可能是一个问题”这一事实表明您实际上想要计算什么。显然,您想摆脱任何时区差异。
I assume you only want to calculate the days, without time and timezone.
我假设您只想计算天数,而没有时间和时区。
Java 8
爪哇 8
Below, in the example of how the number of days between could be calculated correctly, I'm using a class that represents exactly that – a date without time and timezone – LocalDate
.
在下面的示例中,如何正确计算天数之间的天数,我使用了一个准确表示该天数的类 - 一个没有时间和时区的日期 - 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);
Note that ChronoUnit
, DateTimeFormatter
and LocalDate
require at least Java 8, which is not available to you, according to the java-7tag. However, it perhaps is to future readers.
需要注意的是ChronoUnit
,DateTimeFormatter
和LocalDate
至少需要Java 8,这是不提供给你,根据Java的7标记。然而,这也许是为了未来的读者。
As mentioned by Ole V.V., there's also the ThreeTen Backport, which backports Java 8 Date and Time API functionality to Java 6 and 7.
正如 Ole VV 所提到的,还有ThreeTen Backport,它将 Java 8 日期和时间 API 功能向后移植到 Java 6 和 7。