191

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

任何帮助都会很棒:)

4

28 回答 28

283

“差异月数”的定义有很多解释。:-)

您可以从 JavaScript 日期对象中获取年、月和日。根据您要查找的信息,您可以使用这些信息来计算两个时间点之间的月数。

例如,即兴表演:

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

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

function test(d1, d2) {
    var diff = monthDiff(d1, d2);
    console.log(
        d1.toISOString().substring(0, 10),
        "to",
        d2.toISOString().substring(0, 10),
        ":",
        diff
    );
}

test(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16

test(
    new Date(2010, 0, 1),  // January 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 2

test(
    new Date(2010, 1, 1),  // February 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 1

(请注意,JavaScript 中的月份值以 0 = 一月开头。)

包括上面的小数月要复杂得多,因为典型的二月的三天比八月的三天(~9.677%)占该月的比例更大(~10.714%),当然即使是二月也是一个移动目标要看是不是闰年。

还有一些可用于 JavaScript 的日期和时间库,可能会使这类事情变得更容易。


注意:上面曾经有一个+ 1,这里:

months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();

那是因为最初我说:

...这会找出两个日期之间有多少完整的月份,不包括部分月份(例如,不包括每个日期所在的月份)。

我删除它有两个原因:

  1. 不计算部分月份结果并不是很多(大多数?)来回答的人想要的,所以我想我应该把它们分开。

  2. 即使按照这个定义,它也并不总是有效。:-D(对不起。)

于 2010-03-29T07:49:37.787 回答
133

如果您不考虑月份中的哪一天,这是迄今为止更简单的解决方案

function monthDiff(dateFrom, dateTo) {
 return dateTo.getMonth() - dateFrom.getMonth() + 
   (12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}


//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1

请注意,月份索引是从 0 开始的。这意味着January = 0December = 11

于 2010-11-30T10:59:17.370 回答
35

这是一个准确提供两个日期之间的月数的函数。
默认行为仅计算整月,例如 3 个月和 1 天将导致 3 个月的差异。roundUpFractionalMonths您可以通过将参数设置为 来防止这种情况true,因此 3 个月和 1 天的差异将返回为 4 个月。

上面接受的答案(TJ Crowder 的答案)并不准确,它有时会返回错误的值。

例如,monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015'))返回0显然是错误的。正确的差异是 1 个整月或 2 个月的四舍五入。

这是我写的函数:

function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
    //Months will be calculated between start and end dates.
    //Make sure start date is less than end date.
    //But remember if the difference should be negative.
    var startDate=date1;
    var endDate=date2;
    var inverse=false;
    if(date1>date2)
    {
        startDate=date2;
        endDate=date1;
        inverse=true;
    }

    //Calculate the differences between the start and end dates
    var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
    var monthsDifference=endDate.getMonth()-startDate.getMonth();
    var daysDifference=endDate.getDate()-startDate.getDate();

    var monthCorrection=0;
    //If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
    //The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
    if(roundUpFractionalMonths===true && daysDifference>0)
    {
        monthCorrection=1;
    }
    //If the day difference between the 2 months is negative, the last month is not a whole month.
    else if(roundUpFractionalMonths!==true && daysDifference<0)
    {
        monthCorrection=-1;
    }

    return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};
于 2014-11-14T13:22:27.997 回答
33

有时您可能只想获取两个日期之间的月份数,而完全忽略日部分。因此,例如,如果您有两个日期 - 2013/06/21 和 2013/10/18- 并且您只关心 2013/06 和 2013/10 部分,以下是场景和可能的解决方案:

var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
  month1++;
  month2++;
}
var numberOfMonths; 

1.如果您只想要两个日期之间的月份数,不包括月份 1 和月份 2

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;

2.如果你想包括任一月份

numberOfMonths = (year2 - year1) * 12 + (month2 - month1);

3.如果你想包括这两个月

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
于 2013-03-01T13:25:35.580 回答
28

如果您需要计算完整的月份,无论月份是 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 个月内产生)
于 2014-01-09T13:02:44.713 回答
7

JavaScript 中两个日期之间的月差:

 start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
 end_date = new Date(new Date(year, month, day)

start_date 和 end_date 之间的总月数:

 total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
于 2014-03-15T13:41:08.337 回答
6

我知道这真的很晚了,但无论如何都会发布它以防万一它对其他人有帮助。这是我想出的一个函数,它似乎可以很好地计算两个日期之间的月份差异。无可否认,它比 Mr.Crowder 的更粗俗,但通过遍历日期对象可以提供更准确的结果。它在 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;
    }
于 2010-07-21T21:28:35.800 回答
5

要扩展@TJ 的答案,如果您正在寻找简单的月份,而不是完整的日历月份,您可以检查 d2 的日期是否大于或等于 d1 的日期。也就是说,如果 d2 的月份晚于 d1 的月份,那么还有 1 个月。所以你应该能够做到这一点:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    // edit: increment months if d2 comes later in its month than d1 in its month
    if (d2.getDate() >= d1.getDate())
        months++
    // end edit
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10

这并不能完全解决时间问题(例如,3 月 3 日下午 4:00 和 4 月 3 日下午 3:00),但它更准确,并且只需要几行代码。

于 2014-03-18T21:33:56.693 回答
5

以月为单位考虑每个日期,然后减去以找出差异。

var past_date = new Date('11/1/2014');
var current_date = new Date();

var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());

这将为您提供两个日期之间的月份差,忽略日期。

于 2015-11-22T06:17:32.310 回答
5

您也可以考虑这个解决方案,它function返回整数或数字的月差

将开始日期作为第一个或最后一个传递param,是容错的。意思是,该函数仍将返回相同的值。

const diffInMonths = (end, start) => {
   var timeDiff = Math.abs(end.getTime() - start.getTime());
   return Math.round(timeDiff / (2e3 * 3600 * 365.25));
}

const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));

// shows month difference as integer/number
console.log(result);

于 2019-02-15T09:48:41.500 回答
4

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

如果您遍历日历,将开始日期增加一个月并查看我们是否超过结束日期。这将异常处理委托给内置的 Date() 类,但如果您对大量日期执行此操作可能会很慢。詹姆斯的回答采用了这种方法。尽管我不喜欢这个想法,但我认为这是“最安全”的方法,如果你只做一次计算,性能差异真的可以忽略不计。我们倾向于尝试过度优化只会执行一次的任务。

现在,如果您在数据集上计算此函数,您可能不想在每一行上运行该函数(或者上帝禁止,每条记录多次)。在这种情况下,您可以在这里使用几乎任何其他答案,除了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;
}
于 2015-02-27T18:54:10.397 回答
3

在这里,您可以采用较少循环的其他方法:

calculateTotalMonthsDifference = function(firstDate, secondDate) {
        var fm = firstDate.getMonth();
        var fy = firstDate.getFullYear();
        var sm = secondDate.getMonth();
        var sy = secondDate.getFullYear();
        var months = Math.abs(((fy - sy) * 12) + fm - sm);
        var firstBefore = firstDate > secondDate;
        firstDate.setFullYear(sy);
        firstDate.setMonth(sm);
        firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
        return months;
}
于 2011-12-07T13:30:06.830 回答
2

日期和时间无关紧要的月数

在这种情况下,我不关心整月、部分月、一个月有多长等。我只需要知道月数。一个相关的现实世界案例是每个月都要提交一份报告,我需要知道应该有多少份报告。

例子:

  • 一月 = 1 个月
  • 一月 - 二月 = 2 个月
  • 11 月 - 1 月 = 3 个月

这是一个详细的代码示例,用于显示数字的去向。

让我们取 2 个时间戳,结果应该是 4 个月

  • 2019年11月13日的时间戳:1573621200000
  • 2020年2月20日的时间戳:1582261140000

您的时区/时间可能会略有不同。日、分、秒无关紧要,可以包含在时间戳中,但我们将在实际计算中忽略它。

第 1 步:将时间戳转换为 JavaScript 日期

let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);

第 2 步:获取月/年的整数值

let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();

这给了我们

  • 开始月份:11
  • 开始年份:2019
  • 结束月份:2
  • 结束年份:2020

第 3 步:添加(12 * (endYear - startYear)) + 1到结束月份。

  • 这使我们的开始月份停留在 11
  • 这使我们的结束月份等于 152 + (12 * (2020 - 2019)) + 1 = 15

第 4 步:减去月份

15 - 11 = 4; 我们得到了 4 个月的结果。

29 个月示例示例

2019 年 11 月至 2022 年 3 月为 29 个月。如果将这些放入 Excel 电子表格,您将看到 29 行。

  • 我们的开始月份是 11
  • 我们的结束月份是 403 + (12 * (2022-2019)) + 1

40 - 11 = 29

于 2020-01-29T04:08:04.107 回答
2

这应该可以正常工作:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months += d2.getMonth() - d1.getMonth();
    return months;
}
于 2016-05-06T22:06:26.550 回答
2

计算两个日期之间的差异,包括月份的分数(天)。


var difference = (date2.getDate() - date1.getDate()) / 30 +
    date2.getMonth() - date1.getMonth() +
    (12 * (date2.getFullYear() - date1.getFullYear()));

例如:
date1:​​24/09/2015(2015 年 9 月 24 日)
date2:09/11/2015(2015 年 11 月 9 日)
差异:2.5(月)

于 2015-11-03T16:44:59.677 回答
2

这是我能找到的最简单的解决方案。这将直接返回月数。虽然,它总是给出一个绝对值。

new Date(new Date(d2) - new Date(d1)).getMonth();

对于非绝对值,您可以使用以下解决方案:

function diff_months(startDate, endDate) {
  let diff = new Date( new Date(endDate)  - new Date(startDate) ).getMonth();
  return endDate >= startDate ? diff : -diff;
}
于 2021-07-05T07:22:54.720 回答
1
function monthDiff(date1, date2, countDays) {

  countDays = (typeof countDays !== 'undefined') ?  countDays : false;

  if (!date1 || !date2) {
    return 0;
  }

  let bigDate = date1;
  let smallDate = date2;

  if (date1 < date2) {
    bigDate = date2;
    smallDate = date1;
  }

  let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());

  if (countDays && bigDate.getDate() < smallDate.getDate()) {
    --monthsCount;
  }

  return monthsCount;
}
于 2018-11-21T18:30:59.717 回答
1
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
    var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
          diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24))); 
    d1new = new Date(d2year, d2month, 1,0,0,0,0);
    d1new.setDate(d1new.getDate()-1);
    d1maxday = d1new.getDate();
    months += diffdate / d1maxday;
}
else
{
      if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
    {
        months += 1;
    }
    diffdate = d2day - d1day + 1;
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
    d2new.setDate(d2new.getDate()-1);
    d2maxday = d2new.getDate();
    months += diffdate / d2maxday;
}

return months;

}

于 2016-10-16T13:17:44.207 回答
1
function calcualteMonthYr(){
    var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
    var toDate = new Date($('#txtDurationTo2').val());

var months=0;
        months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
        months -= fromDate.getMonth();
        months += toDate.getMonth();
            if (toDate.getDate() < fromDate.getDate()){
                months--;
            }
    $('#txtTimePeriod2').val(months);
}
于 2015-09-29T06:07:14.657 回答
1

以下代码还通过考虑部分月份的天数来返回两个日期之间的完整月份。

var monthDiff = function(d1, d2) {
  if( d2 < d1 ) { 
    var dTmp = d2;
    d2 = d1;
    d1 = dTmp;
  }

  var months = (d2.getFullYear() - d1.getFullYear()) * 12;
  months -= d1.getMonth() + 1;
  months += d2.getMonth();

  if( d1.getDate() <= d2.getDate() ) months += 1;

  return months;
}

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0

monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
于 2016-04-25T22:07:57.863 回答
1

下面的逻辑将在几个月内获取差异

(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
于 2017-08-16T00:01:14.010 回答
0
getMonthDiff(d1, d2) {
    var year1 = dt1.getFullYear();
    var year2 = dt2.getFullYear();
    var month1 = dt1.getMonth();
    var month2 = dt2.getMonth();
    var day1 = dt1.getDate();
    var day2 = dt2.getDate();
    var months = month2 - month1;
    var years = year2 -year1
    days = day2 - day1;
    if (days < 0) {
        months -= 1;
    }
    if (months < 0) {
        months += 12;
    }
    return months + years*!2;
}
于 2020-08-06T12:46:59.317 回答
0

看看我用什么:

function monthDiff() {
    var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
    var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
    var months = 0;
    while (startdate < enddate) {
        if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
            months++;
            startdate.addMonths(1);
            startdate.addDays(2);
        } else {
            months++;
            startdate.addMonths(1);
        }
    }
    return months;
}
于 2017-08-07T12:31:11.820 回答
0

它还计算天数并将其转换为月数。

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 
于 2017-12-08T12:21:29.293 回答
0

返回任何值及其绝对值。

function differenceInMonths(firstDate, secondDate) {
    if (firstDate > secondDate) [firstDate, secondDate] = [secondDate, firstDate];
    let diffMonths = (secondDate.getFullYear() - firstDate.getFullYear()) * 12;
    diffMonths -= firstDate.getMonth();
    diffMonths += secondDate.getMonth();
    return diffMonths;
}
 
于 2020-11-09T14:08:04.893 回答
-2

我不喜欢重新发明轮子,保持简单(我的意思是不关心月份的天数、闰年等)并使用date-fnslib,因此

 npm install -s date-fns

const differenceInMonths = require('date-fns/differenceInMonths')

;(() => {
    console.log(differenceInMonths(new Date(`2015-12-01`), new Date(`2013-12-01`)))
    console.log(differenceInMonths(new Date(1582261140000), new Date(`2014-12-01`)))
    console.log(differenceInMonths(new Date(1582261140000), new Date(1573621200000)))
})()
于 2021-02-15T09:35:00.260 回答
-2
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
于 2016-02-11T06:03:12.957 回答
-8

一种方法是编写一个使用 JODA 库的简单 Java Web 服务 (REST/JSON)

http://joda-time.sourceforge.net/faq.html#datediff

计算两个日期之间的差异并从 javascript 调用该服务。

这假设您的后端是 Java。

于 2012-02-19T02:00:39.873 回答