Java 8计算两个日期之间的月份

时间:2018-02-23 14:32:29

标签: java java-8

请注意,这不是以下任何一项重复

我有两个日期:

  • 开始日期:"2016-08-31"
  • 结束日期:"2016-11-30"

在上述两个日期之间有91天的持续时间,我预计我的代码将返回3个月的持续时间,但以下方法仅返回2个月。有人有更好的建议吗?或者你们认为这是Java 8中的一个错误吗? 91天,持续时间仅返回2个月。

非常感谢您的帮助。

方法1:

Period diff = Period.between(LocalDate.parse("2016-08-31"),
    LocalDate.parse("2016-11-30"));

方法2:

long daysBetween = ChronoUnit.MONTHS.between(LocalDate.parse("2016-08-31"),
    LocalDate.parse("2016-11-30"));

方法3:

我尝试使用Joda库而不是Java 8 API,它可以工作。它将loos返回3,看起来像Java持续时间的月计算也使用了天数值。但就我而言,我不能在我的项目中使用Joda。所以还在寻找其他解决方案。

    LocalDate dateBefore= LocalDate.parse("2016-08-31");
    LocalDate dateAfter = LocalDate.parse("2016-11-30");
    int months = Months.monthsBetween(dateBefore, dateAfter).getMonths();
    System.out.println(months);

8 个答案:

答案 0 :(得分:9)

因为你不关心你案件的日子。您只需要两个日期之间的月份数,使用期间的文档来调整日期,它使用日期作为Jacob的解释。只需将两个实例的天数设置为相同的值(该月的第一天)

Period diff = Period.between(
            LocalDate.parse("2016-08-31").withDayOfMonth(1),
            LocalDate.parse("2016-11-30").withDayOfMonth(1));
System.out.println(diff); //P3M

与其他解决方案相同:

long monthsBetween = ChronoUnit.MONTHS.between(
        LocalDate.parse("2016-08-31").withDayOfMonth(1),
        LocalDate.parse("2016-11-30").withDayOfMonth(1));
System.out.println(monthsBetween); //3

答案 1 :(得分:3)

Period#between的文档说明如下:

  

包含开始日期,但结束日期不包括在内。

此外:

  

如果结束日期大于或等于月初日,则会考虑一个月。

您的结束日期30 大于或等于您的开始日期31,因此不会考虑第三个月。

请注意参数名称:

public static Period between​(LocalDate startDateInclusive, LocalDate endDateExclusive)

要返回3个月,您可以将endDateExclusive增加一天。

答案 2 :(得分:2)

如果您想坚持使用java.time.Period API

根据java.time.Period文档

Period between(LocalDate startDateInclusive, LocalDate endDateExclusive)

其中

@param startDateInclusive  the start date, inclusive, not null
@param endDateExclusive  the end date, exclusive, not null

因此,最好调整实施方式,使结束日期具有包容性,并获得所需的结果

Period diff = Period.between(LocalDate.parse("2016-08-31"),
                LocalDate.parse("2016-11-30").plusDays(1));
System.out.println("Months : " + diff.getMonths());
//Output -> Months : 3

答案 3 :(得分:1)

///与旧版Java向后兼容

public static int monthsBetween(Date d1, Date d2){
    if(d2==null || d1==null){
        return -1;//Error
    }
    Calendar m_calendar=Calendar.getInstance()
    m_calendar.setTime(d1);
    int nMonth1=12*m_calendar.get(Calendar.YEAR)+m_calendar.get(Calendar.MONTH);
    m_calendar.setTime(d2);
    int nMonth2=12*m_calendar.get(Calendar.YEAR)+m_calendar.get(Calendar.MONTH);
    return java.lang.Math.abs(nMonth2-nMonth1);
}

答案 4 :(得分:1)

您必须小心,永远不要使用LocalDateTime来计算两个日期之间的月份,结果是奇怪的和不正确的,请始终使用LocalDate!

这是一些证明以上内容的代码:

package stack.time;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class TestMonthsDateTime {
    public static void main(String[] args) {
        /**------------------Date Time----------------------------*/
        LocalDateTime t1 = LocalDateTime.now();
        LocalDateTime t2 = LocalDateTime.now().minusMonths(3);
        long dateTimeDiff = ChronoUnit.MONTHS.between(t2, t1);  
        System.out.println("diff dateTime : " + dateTimeDiff); //diff dateTime : 2
        /**-------------------------Date----------------------------*/
        LocalDate t3 = LocalDate.now();
        LocalDate t4 = LocalDate.now().minusMonths(3);
        long dateDiff = ChronoUnit.MONTHS.between(t4, t3);
        System.out.println("diff date : "  +  dateDiff);//diff date : 3
    }
}

我的2%

答案 5 :(得分:0)

经过短暂的调查,仍然没有完全解决我的问题,但我使用了一个肮脏的解决方案,以避免返回不正确的持续时间。至少,我们可以获得合理的持续时间。

private static long durationMonths(LocalDate dateBefore, LocalDate dateAfter) {
        System.out.println(dateBefore+"   "+dateAfter);
        if (dateBefore.getDayOfMonth() > 28) {
            dateBefore = dateBefore.minusDays(5);
        } else if (dateAfter.getDayOfMonth() > 28) {
            dateAfter = dateAfter.minusDays(5);
        }
        return ChronoUnit.MONTHS.between(dateBefore, dateAfter);
    }

答案 6 :(得分:0)

从Java8开始:

ChronoUnit.MONTHS.between(startDate, endDate);

答案 7 :(得分:0)

此示例检查第二个日期是否是该月的月底。如果是该月的月底,并且该月的第一个日期大于第二个月的日期,则它会知道需要添加 1

LocalDate date1 = LocalDate.parse("2016-08-31");
LocalDate date2 = LocalDate.parse("2016-11-30");
    
long monthsBetween = ChronoUnit.MONTHS.between(
            date1,
            date2);
    
if (date1.isBefore(date2) 
        && date2.getDayOfMonth() == date2.lengthOfMonth() 
        && date1.getDayOfMonth() > date2.getDayOfMonth()) {
    monthsBetween += 1;
}