Difference between two dates in years, months, days in JavaScript

前端 未结 26 2462
执念已碎
执念已碎 2020-11-22 07:18

I\'ve been searching for 4 hours now, and have not found a solution to get the difference between two dates in years, months, and days in JavaScript, like: 10th of April 201

相关标签:
26条回答
  • 2020-11-22 07:57

    Actually, there's a solution with a moment.js plugin and it's very easy.

    You might use moment.js

    Don't reinvent the wheel again.

    Just plug Moment.js Date Range Plugin.


    Example:

    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>

    0 讨论(0)
  • 2020-11-22 07:58

    Modified this to be a lot more accurate. It will convert dates to a 'YYYY-MM-DD' format, ignoring HH:MM:SS, and takes an optional endDate or uses the current date, and doesn't care about the order of the values.

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

    Then you can use it like this:

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

    Older less accurate but simpler version

    @RajeevPNadig's answer was what I was looking for, but his code returns incorrect values as written. This is not very accurate because it assumes that the sequence of dates from 1 January 1970 is the same as any other sequence of the same number of days. E.g. it calculates the difference from 1 July to 1 September (62 days) as 0Y 2M 3D and not 0Y 2M 0D because 1 Jan 1970 plus 62 days is 3 March.

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

    Then you can use it like this:

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

    If your use case is just date strings, then this works okay if you just want a quick and dirty 4 liner.

    0 讨论(0)
  • 2020-11-22 07:58

    I have created, yet another one, function for this purpose:

    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};
    }
    

    Doesn't require any 3rd party libraries. Takes one argument -- date in YYYY-MM-DD format.

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

    0 讨论(0)
  • 2020-11-22 07:58

    Very old thread, I know, but here's my contribution, as the thread is not solved yet.

    It takes leap years into consideration and does not asume any fixed number of days per month or year.

    It might be flawed in border cases as I haven't tested it thoroughly, but it works for all the dates provided in the original question, thus I'm confident.

    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>

    0 讨论(0)
  • 2020-11-22 08:01
       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));
    

    Above snippet will print: Year: 1, Month: 4, Days: 2

    0 讨论(0)
  • 2020-11-22 08:01

    You should try using date-fns. Here's how I did it using intervalToDuration and formatDuration functions from date-fns.

    let startDate = Date.parse("2010-10-01 00:00:00 UTC");
    let endDate = Date.parse("2020-11-01 00:00:00 UTC");
    
    let duration = intervalToDuration({start: startDate, end: endDate});
    
    let durationInWords = formatDuration(duration, {format: ["years", "months", "days"]}); //output: 10 years 1 month
    
    0 讨论(0)
提交回复
热议问题