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

我现在已经搜索了 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'));

【问题讨论】:

    标签: javascript date datediff


    【解决方案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
    

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

    @RajeevPNadig 的答案正是我想要的,但他的代码返回的值不正确。这不是很准确,因为它假定从 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-fnsintervalToDurationformatDuration 函数的方法。

                            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(`${years}y ${months}m ${days}d`);
                                      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天。
                                  猜你喜欢
                                  • 2014-04-07
                                  • 2022-10-02
                                  • 2016-03-22
                                  • 1970-01-01
                                  • 2014-12-06
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多