我如何在JavaScript中计算出两个Date()对象的差异,而只返回差异中的月份数?

任何帮助都是最好的:)


当前回答

你也可以考虑这个解决方案,这个函数返回整数或数字形式的月差

将开始日期作为第一个或最后一个参数传递是容错的。这意味着,函数仍然会返回相同的值。

const diffInMonths = (end, start) => { var timeDiff = Math.abs(end.getTime() - start.getTime()); 返回数学。round(timeDiff / (2e3 * 3600 * 365.25)); } const result = diffInMonths(new Date(2015, 3,28), new Date(2010, 1,25)); //显示月差值为整数/数字 console.log(结果);

其他回答

这应该可以正常工作:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months += d2.getMonth() - d1.getMonth();
    return months;
}

它还计算天数并以月为单位进行转换。

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;   //calculates months between two years
    months -= d1.getMonth() + 1; 
    months += d2.getMonth();  //calculates number of complete months between two months
    day1 = 30-d1.getDate();  
    day2 = day1 + d2.getDate();
    months += parseInt(day2/30);  //calculates no of complete months lie between two dates
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2017, 8, 8), // Aug 8th, 2017    (d1)
    new Date(2017, 12, 12)  // Dec 12th, 2017   (d2)
);
//return value will be 4 months 

我知道这真的很晚了,但还是把它贴出来,以防它能帮助到其他人。下面是我想出的一个函数,它似乎很好地计算了两个日期之间的月份差异。不可否认,这个方法比克劳德的方法要粗俗得多,但通过遍历日期对象提供了更准确的结果。它是在AS3中,但你应该能够放弃强类型,你会有JS。请随意让大家看起来更漂亮!

    function countMonths ( startDate:Date, endDate:Date ):int
    {
        var stepDate:Date = new Date;
        stepDate.time = startDate.time;
        var monthCount:int;

        while( stepDate.time <= endDate.time ) { 
            stepDate.month += 1;
            monthCount += 1;
        }           

        if ( stepDate != endDate ) { 
            monthCount -= 1;
        }

        return monthCount;
    }

如果你需要计算完整的月份,不管这个月是28、29、30还是31天。下面应该可以。

var months = to.getMonth() - from.getMonth() 
    + (12 * (to.getFullYear() - from.getFullYear()));

if(to.getDate() < from.getDate()){
    months--;
}
return months;

这是答案https://stackoverflow.com/a/4312956/1987208的扩展版本,但修复了从1月31日到2月1日(1天)计算1个月的情况。

这将包括以下内容;

1月1日至1月31日—> 30天—>将导致0(逻辑上,因为它不是一个完整的月) 2月1日至3月1日-> 28或29天->将导致1(逻辑上,因为它是一个完整的月) 2月15日至3月15日-> 28或29天->将导致1(逻辑上,因为一个月过去了) 1月31日至2月1日-> 1天->结果为0(明显,但在1个月后的结果中提到的答案)

有两种方法,数学的和快速的,但受制于日历的变幻莫测,或者迭代的和缓慢的,但处理所有奇怪的(或者至少委托处理它们到一个经过良好测试的库)。

If you iterate through the calendar, incrementing the start date by one month & seeing if we pass the end date. This delegates anomaly-handling to the built-in Date() classes, but could be slow IF you're doing this for a large number of dates. James' answer takes this approach. As much as I dislike the idea, I think this is the "safest" approach, and if you're only doing one calculation, the performance difference really is negligible. We tend to try to over-optimize tasks which will only be performed once.

现在,如果您在数据集中计算这个函数,您可能不希望在每一行上运行该函数(或者上帝禁止,每条记录多次)。在这种情况下,您几乎可以使用这里的任何其他答案,除了接受的答案,这是错误的(new Date()和new Date()之间的差异是-1)?

下面是我尝试的一种数学而快速的方法,它解释了不同的月份长度和闰年。你真的应该只使用这样的函数,如果你将应用它到一个数据集(做这个计算一遍又一遍)。如果只需要执行一次,可以使用上面James的迭代方法,因为您正在将所有(许多)异常的处理委托给Date()对象。

function diffInMonths(from, to){
    var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));

    if(to.getDate() < from.getDate()){
        var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
        if (to < newFrom  && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
            months--;
        }
    }

    return months;
}