java 6.0
假设今天是: 2018年8月8日
此处方法返回的两个月的日期差。
public static Integer getDiffMonths(Date dateFrom, Date dateTo) {
Calendar cal1 = new GregorianCalendar();
cal1.setTime(dateFrom);
Calendar cal2 = new GregorianCalendar();
cal2.setTime(dateTo);
return differenceInMonths(cal1, cal2);
}
private static Integer differenceInMonths(Calendar dateFrom, Calendar dateTo) {
int month1 = dateFrom.get(Calendar.YEAR) * 12 + dateFrom.get(Calendar.MONTH);
int month2 = dateTo.get(Calendar.YEAR) * 12 + dateTo.get(Calendar.MONTH);
int diff = month2 - month1;
return diff;
}
这里有4个测试用例的结果:
1。
currentDate = Aug 08 2018
DateTo = Aug 13 2018
diffMonth = 0
2。
currentDate = Aug 08 2018
DateTo = Oct 14 2018
diffMonth = 2
3。
currentDate = Aug 08 2018
DateTo = Jan 03 2019
diffMonth = 5
错误:相差必须为4个月
4。
currentDate = Aug 08 2018
DateTo = Aug 03 2019
diffMonth = 12
错误:相差必须为11个月
您可以看到测试用例#1和#2是正确的,但是测试用例#3和#4是不正确的。
为什么?
答案 0 :(得分:6)
计算差异时,您将完全忽略这一天。因此1月1日与1月31日相同。
前两个案例在第二个日期碰巧有较大的一天,后两个案例的碰头则较小。但是这些信息将被忽略。
答案 1 :(得分:1)
示例3和4按预期方式工作。 8月-> 1月是5个月,8月-> 8月是12个月。减去月份值时,它严格处理月份值,而不是月份中的天。如果要考虑该月的某天,请添加以下内容:
if(dateFrom.get(Calendar.DAY_OF_MONTH) > dateTo.get(Calendar.DAY_OF_MONTH) && diff != 0){
diffMonth -=1;
}
答案 2 :(得分:1)
这是现代Java日期和时间API java.time表现出色的(很多)情况之一:
public static long differenceInMonths(LocalDate dateFrom, LocalDate dateTo) {
return ChronoUnit.MONTHS.between(dateFrom, dateTo);
}
是的,我强烈建议您在旧的Java 6代码中使用此代码。当然,它需要更多的解释。在开始之前,请允许我证明上面的一种方法可以为您带来预期的结果:
LocalDate currentDate = LocalDate.of(2018, Month.AUGUST, 8);
System.out.println("1. Months until Aug 13 2018: "
+ differenceInMonths(currentDate, LocalDate.of(2018, Month.AUGUST, 13)));
System.out.println("2. Months until Oct 14 2018: "
+ differenceInMonths(currentDate, LocalDate.of(2018, Month.OCTOBER, 14)));
System.out.println("3. Months until Jan 03 2019: "
+ differenceInMonths(currentDate, LocalDate.of(2019, Month.JANUARY, 3)));
System.out.println("4. Months until Aug 03 2019: "
+ differenceInMonths(currentDate, LocalDate.of(2019, Month.AUGUST, 3)));
输出:
1. Months until Aug 13 2018: 0 2. Months until Oct 14 2018: 2 3. Months until Jan 03 2019: 4 4. Months until Aug 03 2019: 11
Date
类型的变量时,如何使用此方法?据我了解,您有一个采用两个老式Date
参数的旧方法,并且您在问为什么它给出错误的结果。因此,我想您也将希望对其进行修复,以提供用户认为正确的结果(如您自己的答案所建议)。因此,重写您的方法以使用我上面的方法:
public static Integer getDiffMonths(Date dateFrom, Date dateTo) {
ZoneId zone = ZoneId.systemDefault();
LocalDate localDateFrom = DateTimeUtils.toInstant(dateFrom)
.atZone(zone)
.toLocalDate();
LocalDate localDateTo = DateTimeUtils.toInstant(dateTo)
.atZone(zone)
.toLocalDate();
long diff = differenceInMonths(localDateFrom, localDateTo);
if (diff < Integer.MIN_VALUE || diff > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Dates are too far apart");
}
return (int) diff;
}
即使在您自己的代码中,从Date
到LocalDate
的转换至少与到Calendar
的转换一样冗长,但您可能会认为差值计算本身是值得的简单明了。
您的旧代码出了什么问题,别人已经很好地解释了,我没有理由重复。
java.time
在Java 6上运行良好。
org.threeten.bp
导入日期和时间类。上面的代码使用ThreeTen Backport并使用子包从org.threeten.bp
导入日期和时间类:
import org.threeten.bp.DateTimeUtils;
import org.threeten.bp.LocalDate;
import org.threeten.bp.Month;
import org.threeten.bp.ZoneId;
import org.threeten.bp.temporal.ChronoUnit;
如果要在Java 8或更高版本上使用相同的代码,并使用内置的java.time,则转换会有所不同,例如:
LocalDate localDateFrom = dateFrom.toInstant()
.atZone(zone)
.toLocalDate();
java.time
。java.time
。java.time
向Java 6和7(JSR-310的ThreeTen)的反向端口。答案 3 :(得分:-1)
这里是正确的代码:
public static Integer getDiffMonths(Date dateFrom, Date dateTo) {
Calendar cal1 = new GregorianCalendar();
cal1.setTime(dateFrom);
Calendar cal2 = new GregorianCalendar();
cal2.setTime(dateTo);
return differenceInMonths(cal1, cal2);
}
private static Integer differenceInMonths(Calendar dateFrom, Calendar dateTo) {
if (dateFrom == null || dateTo == null) {
return 0;
}
int month1 = dateFrom.get(Calendar.YEAR) * 12 + dateFrom.get(Calendar.MONTH);
int month2 = dateTo.get(Calendar.YEAR) * 12 + dateTo.get(Calendar.MONTH);
int diff = month2 - month1;
if (diff > 0) {
if (dateFrom.get(Calendar.DAY_OF_MONTH) > dateTo.get(Calendar.DAY_OF_MONTH)) {
diff--;
}
} else if (diff < 0) {
if (dateTo.get(Calendar.DAY_OF_MONTH) > dateFrom.get(Calendar.DAY_OF_MONTH)) {
diff++;
}
}
return diff;
}