JavaScript中几年,几个月,几天的两个日期之间的差异

时间:2013-07-18 20:04:56

标签: javascript date datediff

我现在已经搜索了4个小时,并且没有找到解决方案来获取JavaScript中年,月和日的两个日期之间的区别,例如:2010年4月10日是3年,x月和y几天前。

有很多解决方案,但它们只提供日期或月份或年份的格式差异,或者它们不正确(意味着不处理一个月或闰年的实际天数等) 。这样做真的很难吗?

我看过了:

在php中很简单,但不幸的是我只能在该项目上使用客户端脚本。任何能够做到这一点的图书馆或框架都可以。

以下是日期差异的预期输出列表:

//Expected output should be: "1 year, 5 months".
diffDate(new Date('2014-05-10'), new Date('2015-10-10'));

//Expected output should be: "1 year, 4 months, 29 days".
diffDate(new Date('2014-05-10'), new Date('2015-10-09'));

//Expected output should be: "1 year, 3 months, 30 days".
diffDate(new Date('2014-05-10'), new Date('2015-09-09'));

//Expected output should be: "9 months, 27 days".
diffDate(new Date('2014-05-10'), new Date('2015-03-09'));

//Expected output should be: "1 year, 9 months, 28 days".
diffDate(new Date('2014-05-10'), new Date('2016-03-09'));

//Expected output should be: "1 year, 10 months, 1 days".
diffDate(new Date('2014-05-10'), new Date('2016-03-11'));

29 个答案:

答案 0 :(得分:29)

您需要多精确?如果你确实需要考虑常见的年份和闰年,以及几个月之间天数的确切差异,那么你将不得不写一些更高级的东西,但是为了进行基本和粗略的计算,这应该可以解决这个问题:

today = new Date()
past = new Date(2010,05,01) // remember this is equivalent to 06 01 2010
//dates in js are counted from 0, so 05 is june

function calcDate(date1,date2) {
    var diff = Math.floor(date1.getTime() - date2.getTime());
    var day = 1000 * 60 * 60 * 24;

    var days = Math.floor(diff/day);
    var months = Math.floor(days/31);
    var years = Math.floor(months/12);

    var message = date2.toDateString();
    message += " was "
    message += days + " days " 
    message += months + " months "
    message += years + " years ago \n"

    return message
    }


a = calcDate(today,past)
console.log(a) // returns Tue Jun 01 2010 was 1143 days 36 months 3 years ago

请记住,这是不精确的,为了计算完全精确的日期,必须有一个日历并知道一年是否是闰年,也就是我计算月数的方式只是近似的。

但你可以轻松改进它。

答案 1 :(得分:13)

实际上,有一个带有moment.js插件的解决方案,这很容易。

您可以使用moment.js

不要再重新发明轮子。

只需插入Moment.js Date Range Plugin

实施例

var starts = moment('2014-02-03 12:53:12');
var ends   = moment();

var duration = moment.duration(ends.diff(starts));

// with ###moment precise date range plugin###
// it will tell you the difference in human terms

var diff = moment.preciseDiff(starts, ends, true); 
// example: { "years": 2, "months": 7, "days": 0, "hours": 6, "minutes": 29, "seconds": 17, "firstDateWasLater":  false }


// or as string:
var diffHuman = moment.preciseDiff(starts, ends);
// example: 2 years 7 months 6 hours 29 minutes 17 seconds

document.getElementById('output1').innerHTML = JSON.stringify(diff)
document.getElementById('output2').innerHTML = diffHuman
<html>
<head>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>

  <script src="https://raw.githubusercontent.com/codebox/moment-precise-range/master/moment-precise-range.js"></script>

</head>
<body>
  
  <h2>Difference between "NOW and 2014-02-03 12:53:12"</h2>
  <span id="output1"></span>
  <br />
  <span id="output2"></span>
  
</body>
</html>

答案 2 :(得分:12)

我使用这个简单的代码来区分当前日期的年,月,日。

var sdt = new Date('1972-11-30');
var difdt = new Date(new Date() - sdt);
alert((difdt.toISOString().slice(0, 4) - 1970) + "Y " + (difdt.getMonth()+1) + "M " + difdt.getDate() + "D");

答案 3 :(得分:5)

为了方便快捷,我前段时间写了这个函数。它以漂亮的格式返回两个日期之间的差异。随意使用它(在webkit上测试)。

/**
 * Function to print date diffs.
 * 
 * @param {Date} fromDate: The valid start date
 * @param {Date} toDate: The end date. Can be null (if so the function uses "now").
 * @param {Number} levels: The number of details you want to get out (1="in 2 Months",2="in 2 Months, 20 Days",...)
 * @param {Boolean} prefix: adds "in" or "ago" to the return string
 * @return {String} Diffrence between the two dates.
 */
function getNiceTime(fromDate, toDate, levels, prefix){
    var lang = {
            "date.past": "{0} ago",
            "date.future": "in {0}",
            "date.now": "now",
            "date.year": "{0} year",
            "date.years": "{0} years",
            "date.years.prefixed": "{0} years",
            "date.month": "{0} month",
            "date.months": "{0} months",
            "date.months.prefixed": "{0} months",
            "date.day": "{0} day",
            "date.days": "{0} days",
            "date.days.prefixed": "{0} days",
            "date.hour": "{0} hour",
            "date.hours": "{0} hours",
            "date.hours.prefixed": "{0} hours",
            "date.minute": "{0} minute",
            "date.minutes": "{0} minutes",
            "date.minutes.prefixed": "{0} minutes",
            "date.second": "{0} second",
            "date.seconds": "{0} seconds",
            "date.seconds.prefixed": "{0} seconds",
        },
        langFn = function(id,params){
            var returnValue = lang[id] || "";
            if(params){
                for(var i=0;i<params.length;i++){
                    returnValue = returnValue.replace("{"+i+"}",params[i]);
                }
            }
            return returnValue;
        },
        toDate = toDate ? toDate : new Date(),
        diff = fromDate - toDate,
        past = diff < 0 ? true : false,
        diff = diff < 0 ? diff * -1 : diff,
        date = new Date(new Date(1970,0,1,0).getTime()+diff),
        returnString = '',
        count = 0,
        years = (date.getFullYear() - 1970);
    if(years > 0){
        var langSingle = "date.year" + (prefix ? "" : ""),
            langMultiple = "date.years" + (prefix ? ".prefixed" : "");
        returnString += (count > 0 ?  ', ' : '') + (years > 1 ? langFn(langMultiple,[years]) : langFn(langSingle,[years]));
        count ++;
    }
    var months = date.getMonth();
    if(count < levels && months > 0){
        var langSingle = "date.month" + (prefix ? "" : ""),
            langMultiple = "date.months" + (prefix ? ".prefixed" : "");
        returnString += (count > 0 ?  ', ' : '') + (months > 1 ? langFn(langMultiple,[months]) : langFn(langSingle,[months]));
        count ++;
    } else {
        if(count > 0)
            count = 99;
    }
    var days = date.getDate() - 1;
    if(count < levels && days > 0){
        var langSingle = "date.day" + (prefix ? "" : ""),
            langMultiple = "date.days" + (prefix ? ".prefixed" : "");
        returnString += (count > 0 ?  ', ' : '') + (days > 1 ? langFn(langMultiple,[days]) : langFn(langSingle,[days]));
        count ++;
    } else {
        if(count > 0)
            count = 99;
    }
    var hours = date.getHours();
    if(count < levels && hours > 0){
        var langSingle = "date.hour" + (prefix ? "" : ""),
            langMultiple = "date.hours" + (prefix ? ".prefixed" : "");
        returnString += (count > 0 ?  ', ' : '') + (hours > 1 ? langFn(langMultiple,[hours]) : langFn(langSingle,[hours]));
        count ++;
    } else {
        if(count > 0)
            count = 99;
    }
    var minutes = date.getMinutes();
    if(count < levels && minutes > 0){
        var langSingle = "date.minute" + (prefix ? "" : ""),
            langMultiple = "date.minutes" + (prefix ? ".prefixed" : "");
        returnString += (count > 0 ?  ', ' : '') + (minutes > 1 ? langFn(langMultiple,[minutes]) : langFn(langSingle,[minutes]));
        count ++;
    } else {
        if(count > 0)
            count = 99;
    }
    var seconds = date.getSeconds();
    if(count < levels && seconds > 0){
        var langSingle = "date.second" + (prefix ? "" : ""),
            langMultiple = "date.seconds" + (prefix ? ".prefixed" : "");
        returnString += (count > 0 ?  ', ' : '') + (seconds > 1 ? langFn(langMultiple,[seconds]) : langFn(langSingle,[seconds]));
        count ++;
    } else {
        if(count > 0)
            count = 99;
    }
    if(prefix){
        if(returnString == ""){
            returnString = langFn("date.now");
        } else if(past)
            returnString = langFn("date.past",[returnString]);
        else
            returnString = langFn("date.future",[returnString]);
    }
    return returnString;
}

答案 4 :(得分:4)

我认为你正在寻找我想要的东西。我尝试使用javascript提供的毫秒差异来做到这一点,但这些结果在日期的真实世界中不起作用。如果您想要2016年2月1日到2017年1月31日之间的差异,我想要的结果是1年,0个月和0天。整整一年(假设您将最后一天计算为一整天,就像租赁一套公寓一样)。但是,毫秒方法会给你1年0个月和1天,因为日期范围包括闰年。所以这里是我在javascript中用于我的adobe表单的代码(你可以命名字段):(编辑,我纠正了一个错误)

var f1 = this.getField("LeaseExpiration");
var g1 = this.getField("LeaseStart");


var end = f1.value
var begin = g1.value
var e = new Date(end);
var b = new Date(begin);
var bMonth = b.getMonth();
var bYear = b.getFullYear();
var eYear = e.getFullYear();
var eMonth = e.getMonth();
var bDay = b.getDate();
var eDay = e.getDate() + 1;

if ((eMonth == 0)||(eMonth == 2)||(eMonth == 4)|| (eMonth == 6) || (eMonth == 7) ||(eMonth == 9)||(eMonth == 11))

{
var eDays =  31;
}

if ((eMonth == 3)||(eMonth == 5)||(eMonth == 8)|| (eMonth == 10))

{
var eDays = 30;
}

if (eMonth == 1&&((eYear % 4 == 0) && (eYear % 100 != 0)) || (eYear % 400 == 0))
{
var eDays = 29;
}

if (eMonth == 1&&((eYear % 4 != 0) || (eYear % 100 == 0)))
{
var eDays = 28;
}


if ((bMonth == 0)||(bMonth == 2)||(bMonth == 4)|| (bMonth == 6) || (bMonth == 7) ||(bMonth == 9)||(bMonth == 11))

{
var bDays =  31;
}

if ((bMonth == 3)||(bMonth == 5)||(bMonth == 8)|| (bMonth == 10))

{
var bDays = 30;
}

if (bMonth == 1&&((bYear % 4 == 0) && (bYear % 100 != 0)) || (bYear % 400 == 0))
{
var bDays = 29;
}

if (bMonth == 1&&((bYear % 4 != 0) || (bYear % 100 == 0)))
{
var bDays = 28;
}


var FirstMonthDiff = bDays - bDay + 1;


if (eDay - bDay < 0)
{

eMonth = eMonth - 1;
eDay = eDay + eDays;

}

var daysDiff = eDay - bDay;

if(eMonth - bMonth < 0)
{
eYear = eYear - 1;
eMonth = eMonth + 12;
}

var monthDiff = eMonth - bMonth;

var yearDiff = eYear - bYear;

if (daysDiff == eDays)
{
daysDiff = 0;
monthDiff = monthDiff + 1;

if (monthDiff == 12)
{
monthDiff = 0;
yearDiff = yearDiff + 1;
}

}

if ((FirstMonthDiff != bDays)&&(eDay - 1 == eDays))

{
daysDiff = FirstMonthDiff;

}
event.value = yearDiff + " Year(s)" + " " + monthDiff + " month(s) " + daysDiff + " days(s)"

答案 5 :(得分:2)

有些数学是有序的。

你可以在Javascript中从另一个中减去一个Date对象,你将在毫秒之间得到它们之间的差异。从这个结果中你可以提取你想要的其他部分(天,月等)

例如:

var a = new Date(2010, 10, 1);
var b = new Date(2010, 9, 1);

var c = a - b; // c equals 2674800000,
               // the amount of milisseconds between September 1, 2010
               // and August 1, 2010.

现在你可以得到你想要的任何部分。例如,两个日期之间已经过了多少天:

var days = (a - b) / (60 * 60 * 24 * 1000);
// 60 * 60 * 24 * 1000 is the amount of milisseconds in a day.
// the variable days now equals 30.958333333333332.

这差不多31天了。然后你可以向下舍入30天,并使用剩余的东西来获得小时,分钟等数量。

答案 6 :(得分:2)

另一种解决方案,基于一些PHP代码。 同样基于PHP的strtotime函数可以在这里找到:http://phpjs.org/functions/strtotime/

Date.dateDiff = function(d1, d2) {
    d1 /= 1000;
    d2 /= 1000;
    if (d1 > d2) d2 = [d1, d1 = d2][0];

    var diffs = {
        year: 0,
        month: 0,
        day: 0,
        hour: 0,
        minute: 0,
        second: 0
    }

    $.each(diffs, function(interval) {
        while (d2 >= (d3 = Date.strtotime('+1 '+interval, d1))) {
            d1 = d3;
            ++diffs[interval];
        }
    });

    return diffs;
};

用法:

> d1 = new Date(2000, 0, 1)
Sat Jan 01 2000 00:00:00 GMT+0100 (CET)

> d2 = new Date(2013, 9, 6)
Sun Oct 06 2013 00:00:00 GMT+0200 (CEST)

> Date.dateDiff(d1, d2)
Object {
  day: 5
  hour: 0
  minute: 0
  month: 9
  second: 0
  year: 13
}

答案 7 :(得分:2)

将此修改为更准确。它会将日期转换为&#39; YYYY-MM-DD&#39;格式,忽略HH:MM:SS,并采用可选的endDate或使用当前日期,并不关心值的顺序。

// based on a current date of 2019-05-10
dateDiff('2019-05-10'); // 0Y 0M 0D
dateDiff('2019-05-09'); // 0Y 0M 1D
dateDiff('2018-05-09'); // 1Y 0M 1D
dateDiff('2018-05-18'); // 0Y 11M 23D
dateDiff('2019-01-09'); // 0Y 4M 1D
dateDiff('2019-02-10'); // 0Y 3M 0D
dateDiff('2019-02-11'); // 0Y 2M 27D
dateDiff('2016-02-11'); // 3Y 2M 28D - leap year
dateDiff('1972-11-30'); // 46Y 5M 10D
dateDiff('2016-02-11', '2017-02-11'); // 1Y 0M 0D
dateDiff('2016-02-11', '2016-03-10'); // 0Y 0M 28D - leap year
dateDiff('2100-02-11', '2100-03-10'); // 0Y 0M 27D - not a leap year
dateDiff('2017-02-11', '2016-02-11'); // 1Y 0M 0D - swapped dates to return correct result
dateDiff(new Date() - 1000 * 60 * 60 * 24); // 0Y 0M 1D

然后你可以像这样使用它:

// startDate must be a date string
function dateAgo(date) {
    var startDate = new Date(date);
    var diffDate = new Date(new Date() - startDate);
    return ((diffDate.toISOString().slice(0, 4) - 1970) + "Y " +
        diffDate.getMonth() + "M " + (diffDate.getDate()-1) + "D");
}

较旧的不太准确但更简单的版本

@ RajeevPNadig的回答是我正在寻找的,但他的代码返回了不正确的值。这不是很准确,因为它假设1970年1月1日的日期序列与相同天数的任何其他序列相同。例如。它计算从7月1日到9月1日(62天)的差异为0Y 2M 3D而不是0Y 2M 0D因为1970年1月1日加62天是3月3日。

// based on a current date of 2018-03-09
dateAgo('1972-11-30'); // "45Y 3M 9D"
dateAgo('2017-03-09'); // "1Y 0M 0D"
dateAgo('2018-01-09'); // "0Y 2M 0D"
dateAgo('2018-02-09'); // "0Y 0M 28D" -- a little odd, but not wrong
dateAgo('2018-02-01'); // "0Y 1M 5D" -- definitely "feels" wrong
dateAgo('2018-03-09'); // "0Y 0M 0D"

然后你可以像这样使用它:

main_category   state       name    goal    start_date
Film & Video    failed      29653   29652   29653   
Film & Video    successful  21404   21404   21404
Film & Video    canceled    5162    5162    5162
Music           successful  21763   21763   21763
Music           failed      19193   19193   19193
Publishing      failed      19920   19920   19920
Technology      failed      16347   16347   16347
Technology      successful  5062    5062    5062
Technology      canceled    3749    3749    3749
Fashion         successful  4310    4310    4310
Fashion         failed      11500   11500   11500

如果你的用例只是日期字符串,那么如果你只想要一个快速而肮脏的4个衬里就可以了。

答案 8 :(得分:2)

我已经为此目的创建了另一个功能:

function dateDiff(date) {
    date = date.split('-');
    var today = new Date();
    var year = today.getFullYear();
    var month = today.getMonth() + 1;
    var day = today.getDate();
    var yy = parseInt(date[0]);
    var mm = parseInt(date[1]);
    var dd = parseInt(date[2]);
    var years, months, days;
    // months
    months = month - mm;
    if (day < dd) {
        months = months - 1;
    }
    // years
    years = year - yy;
    if (month * 100 + day < mm * 100 + dd) {
        years = years - 1;
        months = months + 12;
    }
    // days
    days = Math.floor((today.getTime() - (new Date(yy + years, mm + months - 1, dd)).getTime()) / (24 * 60 * 60 * 1000));
    //
    return {years: years, months: months, days: days};
}

不需要任何第三方库。采用一个参数 - 以YYYY-MM-DD格式表示日期。

https://gist.github.com/lemmon/d27c2d4a783b1cf72d1d1cc243458d56

答案 9 :(得分:1)

这个链接有最好的答案 http://forums.asp.net/t/1610039.aspx?How+to+calculate+difference+between+two+dates+in+years

您只需添加日期验证,例如:

if(firstDate.getDate()&lt; = now.getDate())

答案 10 :(得分:1)

如果您正在使用date-fns,并且不想安装Moment.jsmoment-precise-range-plugin。您可以使用以下date-fns函数来获得与moment-precise-range-plugin相同的结果

intervalToDuration({
  start: new Date(),
  end: new Date("24 Jun 2020")
})

这将在如下所示的JSON对象中提供输出

{
  "years": 0,
  "months": 0,
  "days": 0,
  "hours": 19,
  "minutes": 35,
  "seconds": 24
}

实时示例https://stackblitz.com/edit/react-wvxvql

链接到文档https://date-fns.org/v2.14.0/docs/intervalToDuration

答案 11 :(得分:1)

我知道很旧的线程,但这是我的贡献,因为线程尚未解决。

它考虑了leap年,并且没有假设每月或每年的固定天数。

由于我尚未对它进行彻底的测试,因此在边境案件中可能存在缺陷,但是它适用于原始问题中提供的所有日期,因此我很有信心。

function calculate() {
  var fromDate = document.getElementById('fromDate').value;
  var toDate = document.getElementById('toDate').value;

  try {
    document.getElementById('result').innerHTML = '';

    var result = getDateDifference(new Date(fromDate), new Date(toDate));

    if (result && !isNaN(result.years)) {
      document.getElementById('result').innerHTML =
        result.years + ' year' + (result.years == 1 ? ' ' : 's ') +
        result.months + ' month' + (result.months == 1 ? ' ' : 's ') + 'and ' +
        result.days + ' day' + (result.days == 1 ? '' : 's');
    }
  } catch (e) {
    console.error(e);
  }
}

function getDateDifference(startDate, endDate) {
  if (startDate > endDate) {
    console.error('Start date must be before end date');
    return null;
  }
  var startYear = startDate.getFullYear();
  var startMonth = startDate.getMonth();
  var startDay = startDate.getDate();

  var endYear = endDate.getFullYear();
  var endMonth = endDate.getMonth();
  var endDay = endDate.getDate();

  // We calculate February based on end year as it might be a leep year which might influence the number of days.
  var february = (endYear % 4 == 0 && endYear % 100 != 0) || endYear % 400 == 0 ? 29 : 28;
  var daysOfMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

  var startDateNotPassedInEndYear = (endMonth < startMonth) || endMonth == startMonth && endDay < startDay;
  var years = endYear - startYear - (startDateNotPassedInEndYear ? 1 : 0);

  var months = (12 + endMonth - startMonth - (endDay < startDay ? 1 : 0)) % 12;

  // (12 + ...) % 12 makes sure index is always between 0 and 11
  var days = startDay <= endDay ? endDay - startDay : daysOfMonth[(12 + endMonth - 1) % 12] - startDay + endDay;

  return {
    years: years,
    months: months,
    days: days
  };
}
<p><input type="text" name="fromDate" id="fromDate" placeholder="yyyy-mm-dd" value="1999-02-28" /></p>
<p><input type="text" name="toDate" id="toDate" placeholder="yyyy-mm-dd" value="2000-03-01" /></p>
<p><input type="button" name="calculate" value="Calculate" onclick="javascript:calculate();" /></p>
<p />
<p id="result"></p>

答案 12 :(得分:0)

我使用了一堆函数。 纯 JavaScript 和精确。

此代码包括计算天、月和年时差的函数。其中之一可用于获得精确的时差,例如 X years, Y months, Z days。在代码的最后,我提供了一些测试。

工作原理:

getDaysDiff()
将时差从毫秒转换为天。


getYearsDiff()
不用担心两个日期的月和日的影响。该函数通过前后移动日期来计算年份差。


getMonthsDiff()(这个与问题无关,但是calExactTimeDiff()中使用了这个概念,我认为有人可能需要这样的功能,所以我插入了它):
这个有点棘手。困难的工作是处理两个日期的月和日。

如果 endDate 的月份大于 startDate 的月份,这意味着又过了一年(12 个月)。但这会在 monthsOfFullYears 中得到处理,因此唯一需要做的就是加上 endDatestartDate 月份的减法。

如果 startDate 的月份大于 endDate 的月份,则没有其他年份。所以我们应该得到它们之间的区别。想象一下,我们想要从今年的 10 月到下一年的 2 月。我们可以这样:11, 12, 1, 2。所以我们过去了 4 个月。这等于 12 - (10 - 2)。我们得到月份之间的差异,然后从一整年的月份中减去它。

下一步是处理几个月的天数。如果 endDate 的天数大于或等于 startDate,则意味着又过了一个月。所以我们添加 1 到它。但如果它更少,那么就没有什么可担心的。但是在我的代码中我没有这样做。因为当我添加月份之间的差异时,我假设月份的天数是相等的。所以我已经添加了 1。因此,如果 endDate 的天数小于 startDate,我必须将 months 减少 1

有一个例外:如果月份相等且 endDate 的日期小于 startDate 的日期,则月份应为 11


我在 calExactTimeDiff() 中使用了相同的概念。

希望有用:)

// time difference in Days
function getDaysDiff(startDate = new Date(), endDate = new Date()) {
    if (startDate > endDate) [startDate, endDate] = [endDate, startDate];

    let timeDiff = endDate - startDate;
    let timeDiffInDays = Math.floor(timeDiff / (1000 * 3600 * 24));

    return timeDiffInDays;
}

// time difference in Months
function getMonthsDiff(startDate = new Date(), endDate = new Date()) {
    let monthsOfFullYears = getYearsDiff(startDate, endDate) * 12;
    let months = monthsOfFullYears;
    // the variable below is not necessary, but I kept it for understanding of code
    // we can use "startDate" instead of it
    let yearsAfterStart = new Date(
        startDate.getFullYear() + getYearsDiff(startDate, endDate),
        startDate.getMonth(),
        startDate.getDate()
    );
    let isDayAhead = endDate.getDate() >= yearsAfterStart.getDate();
    
    if (startDate.getMonth() == endDate.getMonth() && !isDayAhead) {
        months = 11;
        return months;
    }

    if (endDate.getMonth() >= yearsAfterStart.getMonth()) {
        let diff = endDate.getMonth() - yearsAfterStart.getMonth();
        months += (isDayAhead) ? diff : diff - 1;
    }
    else {
        months += isDayAhead 
        ? 12 - (startDate.getMonth() - endDate.getMonth())
        : 12 - (startDate.getMonth() - endDate.getMonth()) - 1;
    }

    return months;
}

// time difference in Years
function getYearsDiff(startDate = new Date(), endDate = new Date()) {
    if (startDate > endDate) [startDate, endDate] = [endDate, startDate];

    let yearB4End = new Date(
        endDate.getFullYear() - 1,
        endDate.getMonth(),
        endDate.getDate()
    );
    let year = 0;
    year = yearB4End > startDate
        ? yearB4End.getFullYear() - startDate.getFullYear()
        : 0;
    let yearsAfterStart = new Date(
        startDate.getFullYear() + year + 1,
        startDate.getMonth(),
        startDate.getDate()
    );
    
    if (endDate >= yearsAfterStart) year++;
    
    return year;
}

// time difference in format: X years, Y months, Z days
function calExactTimeDiff(firstDate, secondDate) {
    if (firstDate > secondDate)
        [firstDate, secondDate] = [secondDate, firstDate];

    let monthDiff = 0;
    let isDayAhead = secondDate.getDate() >= firstDate.getDate();
    
    if (secondDate.getMonth() >= firstDate.getMonth()) {
        let diff = secondDate.getMonth() - firstDate.getMonth();
        monthDiff += (isDayAhead) ? diff : diff - 1;
    }
    else {
        monthDiff += isDayAhead 
        ? 12 - (firstDate.getMonth() - secondDate.getMonth())
        : 12 - (firstDate.getMonth() - secondDate.getMonth()) - 1;
    }

    let dayDiff = 0;

    if (isDayAhead) {
        dayDiff = secondDate.getDate() - firstDate.getDate();
    }
    else {
        let b4EndDate = new Date(
            secondDate.getFullYear(),
            secondDate.getMonth() - 1,
            firstDate.getDate()
        )
        dayDiff = getDaysDiff(b4EndDate, secondDate);
    }
    
        if (firstDate.getMonth() == secondDate.getMonth() && !isDayAhead)
            monthDiff = 11;

    let exactTimeDiffUnits = {
        yrs: getYearsDiff(firstDate, secondDate),
        mths: monthDiff,
        dys: dayDiff,
    };
    
    return `${exactTimeDiffUnits.yrs} years, ${exactTimeDiffUnits.mths} months, ${exactTimeDiffUnits.dys} days`
}

let s = new Date(2012, 4, 12);
let e = new Date(2008, 5, 24);
console.log(calExactTimeDiff(s, e));

s = new Date(2001, 7, 4);
e = new Date(2016, 6, 9);
console.log(calExactTimeDiff(s, e));

s = new Date(2011, 11, 28);
e = new Date(2021, 3, 6);
console.log(calExactTimeDiff(s, e));

s = new Date(2020, 8, 7);
e = new Date(2021, 8, 6);
console.log(calExactTimeDiff(s, e));

答案 13 :(得分:0)

因为我不得不使用 moment-hijri(回历)并且不能使用 moment.diff() 方法,所以我想出了这个解决方案。也可以与moment.js一起使用

var momenti = require('moment-hijri')

    //calculate hijri
    var strt = await momenti(somedateobject)
    var until = await momenti()
    
    var years = await 0
    var months = await 0
    var days = await 0

    while(strt.valueOf() < until.valueOf()){
        await strt.add(1, 'iYear');
        await years++
    }
    await strt.subtract(1, 'iYear');
    await years--
    
    while(strt.valueOf() < until.valueOf()){
        await strt.add(1, 'iMonth');
        await months++
    }
    await strt.subtract(1, 'iMonth');
    await months--

    while(strt.valueOf() < until.valueOf()){
        await strt.add(1, 'day');
        await days++
    }
    await strt.subtract(1, 'day');
    await days--


    await console.log(years)
    await console.log(months)
    await console.log(days)

答案 14 :(得分:0)

您应该尝试使用date-fns。这是我使用intervalToDuration中的formatDurationdate-fns函数进行的操作。

let startDate = Date.parse("2010-10-01 00:00:00 UTC");
let endDate = Date.parse("2020-11-01 00:00:00 UTC");

let duration = intervalToDuration({start: startDate, end: endDate});

let durationInWords = formatDuration(duration, {format: ["years", "months", "days"]}); //output: 10 years 1 month

答案 15 :(得分:0)

使用dayjs,我们以这种方式做到了:

export const getAgeDetails = (oldDate: dayjs.Dayjs, newDate: dayjs.Dayjs) => {
  const years = newDate.diff(oldDate, 'year');
  const months = newDate.diff(oldDate, 'month') - years * 12;
  const days = newDate.diff(oldDate.add(years, 'year').add(months, 'month'), 'day');

  return {
    years,
    months,
    days,
    allDays: newDate.diff(oldDate, 'day'),
  };
};

它可以完美计算,包括including年和不同月份的天数。

答案 16 :(得分:0)

以人性化的方式获取两个日期之间的差异

该函数能够返回类似自然语言的文本。使用它来获得如下回复:

“4 年 2 个月零 11 天”

“1 年零 2 个月”

“11 个月零 20 天”

“12 天”


重要提示:date-fns 是一个依赖项

只需复制下面的代码并将过去的日期插入到我们的 getElapsedTime 函数中即可!它会将输入的日期与当前时间进行比较,并返回您类似人类的响应。

import * as dateFns from "https://cdn.skypack.dev/date-fns@2.22.1";

function getElapsedTime(pastDate) {
  
  const duration = dateFns.intervalToDuration({
    start: new Date(pastDate),
    end: new Date(),
  });

  let [years, months, days] = ["", "", ""];

  if (duration.years > 0) {
    years = duration.years === 1 ? "1 year" : `${duration.years} years`;
  }
  if (duration.months > 0) {
    months = duration.months === 1 ? "1 month" : `${duration.months} months`;
  }
  if (duration.days > 0) {
    days = duration.days === 1 ? "1 day" : `${duration.days} days`;
  }

  let response = [years, months, days].filter(Boolean);

  switch (response.length) {
    case 3:
      response[1] += " and";
      response[0] += ",";
      break;
    case 2:
      response[0] += " and";
      break;
  }
  return response.join(" ");
}

答案 17 :(得分:0)

此代码应该给您想要的结果

//************************** Enter your dates here **********************//

var startDate = "10/05/2014";
var endDate = "11/3/2016"

//******* and press "Run", you will see the result in a popup *********//



var noofdays = 0;
var sdArr = startDate.split("/");
var startDateDay = parseInt(sdArr[0]);
var startDateMonth = parseInt(sdArr[1]);
var startDateYear = parseInt(sdArr[2]);
sdArr = endDate.split("/")
var endDateDay = parseInt(sdArr[0]);
var endDateMonth = parseInt(sdArr[1]);
var endDateYear = parseInt(sdArr[2]);

console.log(startDateDay+' '+startDateMonth+' '+startDateYear);
var yeardays = 365;
var monthArr = [31,,31,30,31,30,31,31,30,31,30,31];
var noofyears = 0
var noofmonths = 0;

if((startDateYear%4)==0) monthArr[1]=29;
else monthArr[1]=28;

if(startDateYear == endDateYear){

    noofyears = 0;
    noofmonths = getMonthDiff(startDate,endDate);
    if(noofmonths < 0) noofmonths = 0;
    noofdays = getDayDiff(startDate,endDate);
   
}else{
    if(endDateMonth < startDateMonth){
        noofyears = (endDateYear - startDateYear)-1;  
    if(noofyears < 1) noofyears = 0;
  }else{
            noofyears = endDateYear - startDateYear;  
  }
    noofmonths = getMonthDiff(startDate,endDate);
    if(noofmonths < 0) noofmonths = 0;
    noofdays = getDayDiff(startDate,endDate);   
}
 
 alert(noofyears+' year, '+ noofmonths+' months, '+ noofdays+' days'); 

function getDayDiff(startDate,endDate){ 
    if(endDateDay >=startDateDay){
      noofdays = 0;
      if(endDateDay > startDateDay) {
        noofdays = endDateDay - startDateDay;
       }
     }else{
            if((endDateYear%4)==0) {
            monthArr[1]=29;
        }else{
            monthArr[1] = 28;
        }
        
        if(endDateMonth != 1)
        noofdays = (monthArr[endDateMonth-2]-startDateDay) + endDateDay;
        else
        noofdays = (monthArr[11]-startDateDay) + endDateDay;
     }
    return noofdays;
}

function getMonthDiff(startDate,endDate){
        if(endDateMonth > startDateMonth){
        noofmonths = endDateMonth - startDateMonth;
        if(endDateDay < startDateDay){
                noofmonths--;
            }
      }else{
        noofmonths = (12-startDateMonth) + endDateMonth;
        if(endDateDay < startDateDay){
                noofmonths--;
            }
     }

return noofmonths;
}

https://jsfiddle.net/moremanishk/hk8c419f/

答案 18 :(得分:0)

我个人会使用http://www.datejs.com/,非常方便。具体来说,请查看time.js文件:http://code.google.com/p/datejs/source/browse/trunk/src/time.js

答案 19 :(得分:0)

通过使用Moment库和一些自定义逻辑,我们可以获得确切的日期差

var out;

out = diffDate(new Date('2014-05-10'), new Date('2015-10-10'));
display(out);

out = diffDate(new Date('2014-05-10'), new Date('2015-10-09'));
display(out);

out = diffDate(new Date('2014-05-10'), new Date('2015-09-09'));
display(out);

out = diffDate(new Date('2014-05-10'), new Date('2015-03-09'));
display(out);

out = diffDate(new Date('2014-05-10'), new Date('2016-03-09'));
display(out);

out = diffDate(new Date('2014-05-10'), new Date('2016-03-11'));
display(out);

function diffDate(startDate, endDate) {
  var b = moment(startDate),
    a = moment(endDate),
    intervals = ['years', 'months', 'weeks', 'days'],
    out = {};

  for (var i = 0; i < intervals.length; i++) {
    var diff = a.diff(b, intervals[i]);
    b.add(diff, intervals[i]);
    out[intervals[i]] = diff;
  }
  return out;
}

function display(obj) {
  var str = '';
  for (key in obj) {
    str = str + obj[key] + ' ' + key + ' '
  }
  console.log(str);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>

答案 20 :(得分:0)

非常简单,请使用以下代码,它将按照// 3年9个月3周5天15小时50分钟

给出该格式的差异

Date.getFormattedDateDiff = function(date1, date2) {
var b = moment(date1),
  a = moment(date2),
  intervals = ['years','months','weeks','days'],
  out = [];

for(var i=0; i<intervals.length; i++){
  var diff = a.diff(b, intervals[i]);
  b.add(diff, intervals[i]);
  out.push(diff + ' ' + intervals[i]);
 }
 return out.join(', ');
 };

 var today   = new Date(),
 newYear = new Date(today.getFullYear(), 0, 1),
 y2k     = new Date(2000, 0, 1);

 //(AS OF NOV 29, 2016)
 //Time since New Year: 0 years, 10 months, 4 weeks, 0 days
 console.log( 'Time since New Year: ' + Date.getFormattedDateDiff(newYear, today) );

 //Time since Y2K: 16 years, 10 months, 4 weeks, 0 days
 console.log( 'Time since Y2K: ' + Date.getFormattedDateDiff(y2k, today) );

答案 21 :(得分:0)

使用平面Javascript:

function dateDiffInDays(start, end) {
    var MS_PER_DAY = 1000 * 60 * 60 * 24;
    var a = new Date(start);
    var b = new Date(end);

    const diffTime = Math.abs(a - b);
    const diffDays = Math.ceil(diffTime / MS_PER_DAY); 
    console.log("Days: ", diffDays);

    // Discard the time and time-zone information.
    const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
    const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
    return Math.floor((utc2 - utc1) / MS_PER_DAY);
}

function dateDiffInDays_Months_Years(start, end) {
    var m1 = new Date(start);
    var m2 = new Date(end);
    var yDiff = m2.getFullYear() - m1.getFullYear();
    var mDiff = m2.getMonth() - m1.getMonth();
    var dDiff = m2.getDate() - m1.getDate();

    if (dDiff < 0) {
        var daysInLastFullMonth = getDaysInLastFullMonth(start);
        if (daysInLastFullMonth < m1.getDate()) {
            dDiff = daysInLastFullMonth + dDiff + (m1.getDate() - 

daysInLastFullMonth);
        } else {
            dDiff = daysInLastFullMonth + dDiff;
        }
        mDiff--;
    }
    if (mDiff < 0) {
        mDiff = 12 + mDiff;
        yDiff--;
    }
    console.log('Y:', yDiff, ', M:', mDiff, ', D:', dDiff);
}
function getDaysInLastFullMonth(day) {
    var d = new Date(day);
    console.log(d.getDay() );

    var lastDayOfMonth = new Date(d.getFullYear(), d.getMonth() + 1, 0);
    console.log('last day of month:', lastDayOfMonth.getDate() ); //

    return lastDayOfMonth.getDate();
}

使用moment.js

function dateDiffUsingMoment(start, end) {
    var a = moment(start,'M/D/YYYY');
    var b = moment(end,'M/D/YYYY');
    var diffDaysMoment = b.diff(a, 'days');
    console.log('Moments.js : ', diffDaysMoment);

    preciseDiffMoments(a,b);
}
function preciseDiffMoments( a, b) {
    var m1= a, m2=b;
    m1.add(m2.utcOffset() - m1.utcOffset(), 'minutes'); // shift timezone of m1 to m2
    var yDiff = m2.year() - m1.year();
    var mDiff = m2.month() - m1.month();
    var dDiff = m2.date() - m1.date();
    if (dDiff < 0) {
        var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1), 

"YYYY-MM").subtract(1, 'M').daysInMonth();
        if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03
            dDiff = daysInLastFullMonth + dDiff + (m1.date() - 

daysInLastFullMonth);
        } else {
            dDiff = daysInLastFullMonth + dDiff;
        }
        mDiff--;
    }
    if (mDiff < 0) {
        mDiff = 12 + mDiff;
        yDiff--;
    }
    console.log('getMomentum() Y:', yDiff, ', M:', mDiff, ', D:', dDiff);
}

使用以下示例测试了上述功能:

var sample1 = all('2/13/2018', '3/15/2018'); // {'M/D/YYYY'} 30, Y: 0 , M: 1 , D: 2
console.log(sample1);

var sample2 = all('10/09/2019', '7/7/2020'); // 272, Y: 0 , M: 8 , D: 29
console.log(sample2);

function all(start, end) {
    dateDiffInDays(start, end);
    dateDiffInDays_Months_Years(start, end);

    try {
        dateDiffUsingMoment(start, end);
    } catch (e) {
        console.log(e); 
    }
}

答案 22 :(得分:0)

我知道这是一个旧线程,但我想根据@Pawel Miech的回答,将2美分作为费用。

的确,您需要将差转换为毫秒,然后需要进行一些数学运算。但是请注意,您需要以倒数方式进行数学运算,即您需要计算年,月,日,小时然后是分钟。

我曾经做过这样的事情:

{{1}}

但是,当然,这是不精确的,因为它假设所有年份都有365天,所有月份都有30天,在所有情况下并非如此。

答案 23 :(得分:0)

使用TypeScript / JavaScript计算年,月,日,分,秒,毫秒中两个日期之间的差异

dateDifference(actualDate) {
            // Calculate time between two dates:
            const date1 = actualDate; // the date you already commented/ posted
            const date2: any = new Date(); // today

            let r = {}; // object for clarity
            let message: string;

            const diffInSeconds = Math.abs(date2 - date1) / 1000;
            const days = Math.floor(diffInSeconds / 60 / 60 / 24);
            const hours = Math.floor(diffInSeconds / 60 / 60 % 24);
            const minutes = Math.floor(diffInSeconds / 60 % 60);
            const seconds = Math.floor(diffInSeconds % 60);
            const milliseconds = 
           Math.round((diffInSeconds - Math.floor(diffInSeconds)) * 1000);

            const months = Math.floor(days / 31);
            const years = Math.floor(months / 12);

            // the below object is just optional 
            // if you want to return an object instead of a message
            r = {
                years: years,
                months: months,
                days: days,
                hours: hours,
                minutes: minutes,
                seconds: seconds,
                milliseconds: milliseconds
            };

            // check if difference is in years or months
            if (years === 0 && months === 0) {
                // show in days if no years / months
                if (days > 0) {
                    if (days === 1) {
                        message = days + ' day';
                    } else { message = days + ' days'; }
                }  else if (hours > 0) {
                    if (hours === 1) {
                        message = hours + ' hour';
                    } else {
                        message = hours + ' hours';
                    }
                } else {
                    // show in minutes if no years / months / days
                    if (minutes === 1) {
                        message = minutes + ' minute';
                    } else {message = minutes + ' minutes';}  
                }
            } else if (years === 0 && months > 0) {
                // show in months if no years
                if (months === 1) {
                    message = months + ' month';
                } else {message = months + ' months';}
            } else if (years > 0) {
                // show in years if years exist
                if (years === 1) {
                    message = years + ' year';
                } else {message = years + ' years';}
            }

            return 'Posted ' + message + ' ago'; 
     // this is the message a user see in the view
        }

但是,您可以更新消息的上述逻辑以显示秒和毫秒,或者使用对象'r'以任何方式格式化消息。

如果您想直接复制代码,可以使用上面的代码here

查看我的要点

答案 24 :(得分:0)

以下是一种算法,它给出了正确但不完全精确的算法,因为它没有考虑到闰年。它还假设一个月30天。例如,如果有人住在 12/11/2010 11/10/2011 的地址中,那么很好用,它可以很快告诉那个人住在那里10数月和29天。从 12/11/2010 11/12/2011 是11个月和1天。对于某些类型的应用,这种精度就足够了。这适用于那些类型的应用程序,因为它旨在简化:

var datediff = function(start, end) {
  var diff = { years: 0, months: 0, days: 0 };
  var timeDiff = end - start;

  if (timeDiff > 0) {
    diff.years = end.getFullYear() - start.getFullYear();
    diff.months = end.getMonth() - start.getMonth();
    diff.days = end.getDate() - start.getDate();

    if (diff.months < 0) {
      diff.years--;
      diff.months += 12;
    }

    if (diff.days < 0) {
      diff.months = Math.max(0, diff.months - 1);
      diff.days += 30;
    }
  }

  return diff;
};

Unit tests

答案 25 :(得分:0)

这两个代码都不适合我,所以我使用它代替了几个月和几天:

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

function daysInMonth(date) {
    return new Date(date.getYear(), date.getMonth() + 1, 0).getDate();
}    

function diffDate(date1, date2) {
    if (date2 && date2.getTime() && !isNaN(date2.getTime())) {
        var months = monthDiff(date1, date2);
        var days = 0;

        if (date1.getUTCDate() >= date2.getUTCDate()) {
            days = date1.getUTCDate() - date2.getUTCDate();
        }
        else {
            months--;
            days = date1.getUTCDate() - date2.getUTCDate() + daysInMonth(date2);
        }

        // Use the variables months and days how you need them.
    }
}

答案 26 :(得分:0)

完整天数,小时数,分钟数,秒数,毫秒数的时间跨度:

// Extension for Date
Date.difference = function (dateFrom, dateTo) {
  var diff = { TotalMs: dateTo - dateFrom };
  diff.Days = Math.floor(diff.TotalMs / 86400000);

  var remHrs = diff.TotalMs % 86400000;
  var remMin = remHrs % 3600000;
  var remS   = remMin % 60000;

  diff.Hours        = Math.floor(remHrs / 3600000);
  diff.Minutes      = Math.floor(remMin / 60000);
  diff.Seconds      = Math.floor(remS   / 1000);
  diff.Milliseconds = Math.floor(remS % 1000);
  return diff;
};

// Usage
var a = new Date(2014, 05, 12, 00, 5, 45, 30); //a: Thu Jun 12 2014 00:05:45 GMT+0400 
var b = new Date(2014, 02, 12, 00, 0, 25, 0);  //b: Wed Mar 12 2014 00:00:25 GMT+0400
var diff = Date.difference(b, a);
/* diff: {
  Days: 92
  Hours: 0
  Minutes: 5
  Seconds: 20
  Milliseconds: 30
  TotalMs: 7949120030
} */

答案 27 :(得分:-1)

我这样做。精确?也许不是。尝试

  vtkSOADataArrayTemplate<double>* pointArray = vtkSOADataArrayTemplate<double>::New();
  pointArray->SetNumberOfComponents(3);
  pointArray->SetNumberOfTuples(nbOfPoints);
  pointArray->SetArray(0, XArray, nbOfPoints, false, true);
  pointArray->SetArray(1, YArray, nbOfPoints, false, true);
  pointArray->SetArray(2, ZArray, nbOfPoints, false, true);

  vtkNew<vtkPoints> points;
  points->SetData(pointArray);
  pointArray->Delete();
  VTKGrid->SetPoints(points);

答案 28 :(得分:-1)

在遇到相同问题的同时,我偶然发现了这一点。 这是我的代码。 它完全依赖JS日期功能,因此可以处理leap年,并且不基于小时比较天,因此避免了夏令时问题。

  function dateDiff(start: Date, end: Date) {
    let years: number = 0, months: number = 0, days: number;
    // Day diffence. Trick is to use setDate(0) to get the amount of days
    // from the previous month if the end day less than the start day.
    if (end.getDate() < start.getDate()) {
      months = -1;
      let datePtr: Date = new Date(end);
      datePtr.setDate(0);
      days = end.getDate() + (datePtr.getDate() - start.getDate());
    } else {
      days = end.getDate() - start.getDate();
    }

    if (end.getMonth() < start.getMonth() || (end.getMonth() === start.getMonth() && end.getDate() < start.getDate())) {
      years = -1;
      months += end.getMonth() + (12 - start.getMonth());
    } else {
      months += end.getMonth() - start.getMonth();
    }

    years += end.getFullYear() - start.getFullYear();
    console.log(years + 'y ' + months + 'm ' + days + 'd');
    return[years, months, days];
  }