JavaScript 中两个日期的年、月、日之间的差异

Posted

技术标签:

【中文标题】JavaScript 中两个日期的年、月、日之间的差异【英文标题】:Difference between two dates in years, months, days in JavaScript 【发布时间】:2013-07-17 23:03:03 【问题描述】:

我现在已经搜索了 4 个小时,但还没有找到一个解决方案来获取 javascript 中两个日期的年、月和日之间的差异,例如:2010 年 4 月 10 日是 3 年,x 月和 y几天前。

有很多解决方案,但它们仅提供天、月或年格式的差异,或者它们不正确(意味着不考虑一个月或闰年的实际天数等) .真的那么难做到吗?

我看过了:

http://momentjs.com/ -> 只能输出年、月或日的差异 http://www.javascriptkit.com/javatutors/datedifference.shtml http://www.javascriptkit.com/jsref/date.shtml http://timeago.yarp.com/ www.***.com -> 搜索功能

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'));

【问题讨论】:

【参考方案1】:

您需要精确到什么程度?如果您确实需要考虑普通年和闰年,以及月份之间天数的确切差异,那么您将不得不编写更高级的东西,但对于基本和粗略的计算,这应该可以解决问题:

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

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

但您可以轻松改进它。

【讨论】:

感谢您的回答。这很棒,但恐怕正是我所说的我不是在寻找的东西。如前所述,您所写的是简单的部分 - 考虑到一个月中的确切天数,闰年,......这是困难的事情。 感谢您的回答。但我稍微修改了一下,下面给出了链接:jsfiddle.net/PUSQU/8 这是一个很好的答案,但我很惊讶没有人考虑到这是关闭的一些......因为月份和年份的数学将基于一年,其中有 372 天 【参考方案2】:

其实有一个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 行函数时,你将支付超过 100k 的巨额罚款 缩小版只有51KB。 ~20KB 如果服务器托管启用了 gzip 压缩(cloudflare 托管)。更不用说浏览器可能已经从您访问过的另一个使用相同 CDN 引用的站点缓存了。考虑到这个库如何处理日期方面的许多其他有用的东西,考虑到 JavaScript 中处理日期的难度,我认为这是一个很好的折衷方案。 不要只为计算机优化,要为程序员优化。您的 2 行函数可以及时变为 20-30。在我的书中使用经过测试且一致的库更好。 那么不要在这些情况下使用它。 答案在最底层是不公平的。我已经找到了图书馆 - 但如果答案在顶部,我会节省几个小时【参考方案3】:

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

function dateDiff(startingDate, endingDate) 
    var startDate = new Date(new Date(startingDate).toISOString().substr(0, 10));
    if (!endingDate) 
        endingDate = new Date().toISOString().substr(0, 10);    // need date in YYYY-MM-DD format
    
    var endDate = new Date(endingDate);
    if (startDate > endDate) 
        var swap = startDate;
        startDate = endDate;
        endDate = swap;
    
    var startYear = startDate.getFullYear();
    var february = (startYear % 4 === 0 && startYear % 100 !== 0) || startYear % 400 === 0 ? 29 : 28;
    var daysInMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    var yearDiff = endDate.getFullYear() - startYear;
    var monthDiff = endDate.getMonth() - startDate.getMonth();
    if (monthDiff < 0) 
        yearDiff--;
        monthDiff += 12;
    
    var dayDiff = endDate.getDate() - startDate.getDate();
    if (dayDiff < 0) 
        if (monthDiff > 0) 
            monthDiff--;
         else 
            yearDiff--;
            monthDiff = 11;
        
        dayDiff += daysInMonth[startDate.getMonth()];
    

    return yearDiff + 'Y ' + monthDiff + 'M ' + dayDiff + 'D';

那么你可以这样使用它:

// 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

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

@Rajee***adig 的答案正是我想要的,但他的代码返回的值不正确。这不是很准确,因为它假定从 1970 年 1 月 1 日开始的日期序列与任何其他相同天数的序列相同。例如。它将 7 月 1 日到 9 月 1 日(62 天)的差异计算为 0Y 2M 3D 而不是 0Y 2M 0D,因为 1970 年 1 月 1 日加上 62 天是 3 月 3 日。

// 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");

那么你可以这样使用它:

// 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"

如果您的用例只是日期字符串,那么如果您只想要一个快速而肮脏的 4 班轮,这可以正常工作。

【讨论】:

这个答案对于各种日期都失败了,因为它假设从 1970 年 1 月 1 日开始的日期序列与任何其他相同天数的序列相同,这是无效的。例如。它将 7 月 1 日到 9 月 1 日(62 天)的差异计算为 0Y 2M 3D 而不是 0Y 2M 0D,因为 1970 年 1 月 1 日加上 62 天是 3 月 3 日。 @RobG 我想我清楚地说明了答案中的局限性,并将纳入您的评论作为解释。鉴于这里的许多其他答案都有完全相同的问题,因此不完全确定为什么要投反对票。这样做的目的是简单快捷,但牺牲了完美的准确性。 @RobG 还为您添加了更长但更准确的版本。 这正是我想要的,谢谢! 这需要更多的支持。它解决了上面答案所遇到的问题。干得好!【参考方案4】:

我使用这个简单的代码来获取当前日期的年、月、日的差异。

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");

【讨论】:

这个代码写的返回不正确的结果。假设今天的日期是 2018 年 3 月 9 日:sdt = new Date("2017-03-09") 将提醒“1Y 1M 1D”,sdt = new Date("2018-02-09") 将提醒“0Y 1M 29D”,sdt = new Date("2018-03-09") 将提醒“0Y 1M 1D”。我对此答案的编辑被拒绝,因此我将更正后的代码添加为单独的答案。【参考方案5】:

我认为您正在寻找与我想要的相同的东西。我尝试使用 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)"

【讨论】:

非常感谢,解决方案包括一切。 对于 2020 年 3 月 4 日和 2020 年 2 月 20 日,这将给出 16 天。但不是 16 天。 将以下代码 sn-p 更改为以下 if (eDay - bDay 工作就像一个魅力,但我不得不做一些调整...... if ((FirstMonthDiff != bDays)&&(eDay == eDays)) 和 Lasitha Benaragama 在上面的评论中提到的变化.【参考方案6】:

我已经为此创建了另一个函数:

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

【讨论】:

为什么没有人想要几周? 我猜是因为太难了。【参考方案7】:

为了方便快捷地使用,我前段时间编写了这个函数。它以一种很好的格式返回两个日期之间的差异。随意使用它(在 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;

【讨论】:

嘿,克里斯,我试过这个答案,但没有用。 getNiceTime(new Date('2014-05-10'), new Date('2015-10-10'), 4, true); 应该返回 1 year, 5 months, 1 hour ago 但确实返回 1 year, 5 months, 2 days, 1 hour ago【参考方案8】:

在 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'),
  ;
;

它完美地计算它,包括闰年和不同月份的天数。

【讨论】:

太棒了!尤其是考虑到 Dayjs 的低占用空间。 你救了我的命!经过多次研究,这就像一个魅力!谢谢老哥!【参考方案9】:

一些数学是有序的。

您可以在 Javascript 中从另一个 Date 对象中减去一个 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 天,并使用剩余的时间来计算小时数、分钟数等。

【讨论】:

感谢 Renan 抽空回答。非常好,但是,相同的 Pawelmhm - 获取两个日期之间的毫秒数或天数很简单 - 但考虑到一个月中的天数和闰年等,精确计算很棘手......【参考方案10】:

如果您正在使用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】:

另一个解决方案,基于一些 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

【讨论】:

我承认这段代码很短,很干净而且不那么难理解,但我怀疑它的性能(特别是有很多数据)。【参考方案12】:
   let startDate = moment(new Date('2017-05-12')); // yyyy-MM-dd
   let endDate = moment(new Date('2018-09-14')); // yyyy-MM-dd

   let Years = newDate.diff(date, 'years');
   let months = newDate.diff(date, 'months');
   let days = newDate.diff(date, 'days');

console.log("Year: " + Years, ", Month: " months-(Years*12), ", Days: " days-(Years*365.25)-((365.25*(days- (Years*12)))/12));

sn-p 上方将打印:年:1,月:4,日:2

【讨论】:

添加注释,如果您从服务器获得更长的日期,即。 2018-10-31T00:58:08.041Z dateVar.substring(0,9) 会很好吃 @mewc 这个库有复杂的解析器,查看文档momentjs.com/docs/#/parsing【参考方案13】:

使用平面 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); 
    

【讨论】:

【参考方案14】:

非常老的线程,我知道,但这是我的贡献,因为线程尚未解决。

它考虑了闰年,并且不假定每月或每年的固定天数。

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

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>

【讨论】:

【参考方案15】:

我使用了一堆函数。 纯 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));

【讨论】:

如果说 2 天之间的 1 天不到一年,则此方法不起作用,例如“2021-07-15”到“2022-07-14”将返回“0 年,- 1个月30天” 谢谢你,@Touchpad。我修好了。【参考方案16】:

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

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

“4年1个月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】:

时间跨度以天、小时、分钟、秒、毫秒为单位:

// 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
 */

【讨论】:

【参考方案18】:

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

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.
    

【讨论】:

【参考方案19】:

以下是一种算法,它给出了正确但不完全精确的算法,因为它没有考虑闰年。它还假设一个月有 30 天。例如,如果某人居住在 12/11/201011/10/2011 的地址中,它可以快速判断此人在那里住了 10 年。月零 29 天。从 12/11/201011/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

【讨论】:

【参考方案20】:

使用 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查看我的gist

【讨论】:

【参考方案21】:

我知道这是一个旧线程,但我想根据@Pawel Miech 的回答投入我的 2 美分。

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

我曾经做过这样的事情:

    var mins;
    var hours;
    var days;
    var months;
    var years;

    var diff = new Date() - new Date(yourOldDate);  
// yourOldDate may be is coming from DB, for example, but it should be in the correct format ("MM/dd/yyyy hh:mm:ss:fff tt")

    years = Math.floor((diff) / (1000 * 60 * 60 * 24 * 365));
    diff = Math.floor((diff) % (1000 * 60 * 60 * 24 * 365));
    months = Math.floor((diff) / (1000 * 60 * 60 * 24 * 30));
    diff = Math.floor((diff) % (1000 * 60 * 60 * 24 * 30));
    days = Math.floor((diff) / (1000 * 60 * 60 * 24));
    diff = Math.floor((diff) % (1000 * 60 * 60 * 24));
    hours = Math.floor((diff) / (1000 * 60 * 60));
    diff = Math.floor((diff) % (1000 * 60 * 60));
    mins = Math.floor((diff) / (1000 * 60));

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

【讨论】:

【参考方案22】:

它非常简单,请使用下面的代码,它将根据 //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) );

【讨论】:

【参考方案23】:

通过使用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);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"&gt;&lt;/script&gt;

【讨论】:

【参考方案24】:

这段代码应该会给你想要的结果

//************************** 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/

【讨论】:

【参考方案25】:

您应该尝试使用date-fns。下面是我使用来自date-fns 的intervalToDuration 和formatDuration 函数的方法。

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

【讨论】:

【参考方案26】:

因为我不得不使用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)

【讨论】:

【参考方案27】:

我个人会使用http://www.datejs.com/,真的很方便。具体看time.js文件:http://code.google.com/p/datejs/source/browse/trunk/src/time.js

【讨论】:

感谢乔的分享。但是,我找不到 datejs 能够说出“4 年 2 个月和 11 天前”这样的两个日期之间的确切时差?【参考方案28】:

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

<html>
  <head>
    <title> Age Calculator</title>
  </head>

  <input type="date" id="startDate" value="2000-01-01">
  <input type="date" id="endDate"  value="2020-01-01">
  <button onclick="getAge(new Date(document.getElementById('startDate').value), new Date(document.getElementById('endDate').value))">Check Age</button>
  <script>
    function getAge (startDate, endDate) 
      var diff = endDate-startDate
      var age = new Date(new Date("0000-01-01").getTime()+diff)
      var years = age.getFullYear()
      var months = age.getMonth()
      var days = age.getDate()
      console.log(years,"years",months,"months",days-1,"days")
      return (years+"years "+ months+ "months"+ days,"days")
    
  </script>
</html>

【讨论】:

【参考方案29】:

我在遇到同样问题时偶然发现了这一点。 这是我的代码。 完全依赖JS日期函数,处理闰年,不按小时比较天数,避免了夏令时问题。

function dateDiff(start, end) 
    let years = 0, months = 0, days = 0;
    // 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 = 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(`$yearsy $monthsm $daysd`);
    return [years, months, days];


let a = new Date(2019,6,31);  // 31 Jul 2019
let b = new Date(2022,2, 1);  //  1 Mar 2022

console.log(dateDiff(a, b));  // [2, 7, -2]

【讨论】:

这个问题需要 Javascript,而不是 Typescript。如果你修复它,我会投票有用。 只需删除点后面的类型标识符。我在这里分享了最好的算法。我不在乎你的投票。 这与个人无关。作者需要一个 Javascript 解决方案。不是打字稿解决方案。我要求你进行修复。这是正确的。 这不处理不同长度的月份,如添加的示例所示。 2019年7月31日到2022年3月1日应该是2年6个月1天,但是函数返回[2, 7, -2],即2年7个月-2天。

以上是关于JavaScript 中两个日期的年、月、日之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

如何用excel计算两个日期之间相差的年数和月数

PHP 如何获取两个时间之间的年和月份及间隔天数 PHP两个日期之间的所有日期

excel中怎么计算两个日期之间哪一年差几个月

c#中,如何获取日期型字段里的年、月、日?

计算两个日期的天数问题

如何根据R中另一列的日期(月/日/年)计算列的年/月平均值、最大值、最小值等