我提到生产项目中的一种方法对日期无效,但是我不能只替换它,因为它已经投入生产很长时间了。我创建了一个新方法,该方法可以正确运行,但是我不知道为什么第一种方法会出错。
旧方法(无效):
public static Integer getNumberOfDays(Date startDate, Date endDate) {
TimeZone.setDefault((TimeZone.getTimeZone("Europe/Moscow")));
startDate.setHours(00);
startDate.setMinutes(00);
startDate.setSeconds(00);
endDate.setHours(23);
endDate.setMinutes(59);
endDate.setSeconds(59);
Calendar cal1 = Calendar.getInstance();
cal1.setTime(startDate);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(endDate);
Calendar date = (Calendar) cal1.clone();
int daysBetween = 0;
while (date.before(cal2)){
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
新方法:
public static Integer getNumberOfDaysSecondVersion(Date startDate, Date endDate) {
long difference = startDate.getTime() - endDate.getTime();
float daysBetween = (difference / (1000*60*60*24));
return (int) daysBetween > 0 ? (int) daysBetween : 0;
}
这是我两者的称呼
DateFormat formated = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(Calculation.getNumberOfDays(
formated.parse("2018-06-14"),
formated.parse("2018-06-06")
));
System.out.println(Calculation.getNumberOfDaysSecondVersion(
format.parse("2018-06-14"),
format.parse("2018-06-06"))
);
输出:
0
8
请帮助。
答案 0 :(得分:3)
您的旧方法是正确的方法。当开始日期晚于结束日期时,它将返回0。在您的通话中就是这种情况。
您的新方法从开始日期中减去结束日期,这是错误的,应该相反。我还怀疑它会给夏令时(DST)前后的过渡带来惊喜。尽管莫斯科目前不使用夏令时,但从历史上看,至少一直到2010年为止,如果政客们决定这样做,它可能会再次使用夏令时。
也就是说,您应该尝试避免使用旧的和过时的日期和时间类DateFormat
,SimpleDateFormat
,Calendar
,Date
和{{1} }。今天,我们在java.time
, the modern Java date and time API中有了很多进步。当然,在旧版代码中,您有老式的TimeZone
对象。编写新方法时,建议您将其转换为现代的Date
并使用ChronoUnit.DAYS.between()
。
LocalDate
-8
请注意,当旧方法设置默认时区时,它将影响您的JVM中运行的所有程序,并且可能会对您程序的其他部分和其他程序产生令人讨厌的惊喜。
答案 1 :(得分:2)
可能是因为startDate和endDate的时区不受设置默认时区的影响,所以当您基于它们设置日历时间(以莫斯科时间为单位)时,您正在转换时区,可能会将00:00:00转换为前一天21:00:00左右。
看到您的输出,这很明显...您传递的是开始日期,该日期是将来的结束日期。原始方法使用只能累加的循环,而新方法则采用差的绝对值。
答案 2 :(得分:2)
对于两个版本,您使用了非常不同的算法。
旧版本会在开始日期之前增加几天,直到结束日期之后。
新版本从开始日期中减去结束日期,然后将其除以一天中的毫秒数。
这意味着要使用第一个版本,开始日期必须在结束日期之前,而要使用第二个版本,开始日期必须在结束日期之后。您给第一个版本提供的参数的开始日期在结束日期之后,使其返回0。
要解决此问题,您可以反转两个参数:
System.out.println(getNumberOfDays(
formated.parse("2018-06-06"),
formated.parse("2018-06-14")
));
或者,在计算两者之间的差额之前,先检查哪个日期先到。
顺便说一句,您的第一个版本似乎比第二个版本输出更多。您似乎想要8天的结果。这意味着您的第一个版本存在1比1错误。您可以通过从计数结果中减去1来解决此问题。
请记住,只要可以就始终与java.time
合作!