Ole-Morten Heggertveit
Ole-Morten Heggertveit

Reputation: 489

Moment.js - Get difference in two birthdays in years, months and days

I'm looking for a way to use momentjs to parse two dates, to show the difference.

I want to have it on the format: "X years, Y months, Z days".

For the years and months the moment library and modulo operator works nice. But for the days it's another tale as I don't want to handle leap years and all that by myself. So far the logic I have in my head is this:

var a = moment([2015, 11, 29]);
var b = moment([2007, 06, 27]);

var years = a.diff(b, 'years');
var months = a.diff(b, 'months') % 12;
var days = a.diff(b, 'days');
// Abit stuck here as leap years, and difference in number of days in months. 
// And a.diff(b, 'days') returns total number of days.
return years + '' + months + '' + days;

Upvotes: 41

Views: 41037

Answers (7)

Rakshith HR
Rakshith HR

Reputation: 41

All the solutions presented here are failing for some of the test cases. So I made some changes to the accepted answer.

function getYMD(date1, date2) {
    const a = moment(date1);
    const b = moment(date2);
    var years = a.diff(b, 'year');
    b.add(years, 'years');

    const noOfDaysInb = b.daysInMonth();
    const noOfDaysIna = a.daysInMonth();
    let months = 0;
    if (noOfDaysInb > noOfDaysIna) {
        months = b.diff(a, "months");
        a.add(months, "months");
    } else {
        months = a.diff(b, 'months');
        b.add(months, 'months');
    }
    var days = a.diff(b, 'days');
    return {
        years: Math.abs(years),
        months: Math.abs(months),
        days: Math.abs(days),
    }
}

This is the best answer I can come up with.

Upvotes: 1

Muneeb
Muneeb

Reputation: 1549

I just converted @Josh Crozier's answer into a function and added hours, minutes and seconds too.

 function diffYMDHMS(date1, date2) {

    let years = date1.diff(date2, 'year');
    date2.add(years, 'years');

    let months = date1.diff(date2, 'months');
    date2.add(months, 'months');

    let days = date1.diff(date2, 'days');
    date2.add(days, 'days');

    let hours = date1.diff(date2, 'hours');
    date2.add(hours, 'hours');

    let minutes = date1.diff(date2, 'minutes');
    date2.add(minutes, 'minutes');

    let seconds = date1.diff(date2, 'seconds');

    console.log(years + ' years ' + months + ' months ' + days + ' days ' + hours + ' 
    hours ' + minutes + ' minutes ' + seconds + ' seconds'); 

    return { years, months, days, hours, minutes, seconds};
}

Upvotes: 3

Abdus Salam Azad
Abdus Salam Azad

Reputation: 5502

Use this

  var totalDays = endDate.diff(startDate, "days");

Upvotes: -1

Alaksandar Jesus Gene
Alaksandar Jesus Gene

Reputation: 6887

This is another answer. Verified with Age Calculator

function calculateAge(){
    ageText = jQuery("#dob").closest(".form-group").find(".age-text");
    ageText.text("");
    level2.dob = jQuery("#dob").val();
    if(!level2.dob) return;
    level2.mdob= moment(level2.dob, 'DD-MM-YYYY');
    if(!level2.mdob.isValid()){
        alert("Invalid date format");
        return;
    }
    level2.targetDate = moment();//TODO: Fill in the target date
    level2.months = level2.targetDate.diff(level2.mdob, 'months'); // Calculate the months
    let years = parseInt(level2.months/12); // A year has 12 months irrespective or leap year or not
    let balanceMonths = level2.months%12; // The balance gives the number of months 
    let days;
    if(!balanceMonths){ // If no balance months, then the date selected lies in the same month
        months = 0; // so months = 0
        days = level2.targetDate.diff(level2.mdob, 'days'); // only the days difference
    }else{
    months = balanceMonths;
    dob_date = level2.mdob.date();
    target_month = level2.targetDate.month();
    construct_date = moment().month(target_month).date(dob_date);
    days = level2.targetDate.diff(construct_date, 'days')+1; // There might be one day missed out. Not sure on UTC
}

ageText = years +" years " + months+ " months " + days +" days";
}

Upvotes: -1

Chandresh
Chandresh

Reputation: 277

Above solution is not working with momentjs 2.19.1

Then with reference of Date of Joining calculation not working with moment 2.19.1 I have implemented new solution with latest solution for momentjs 2.19.1.

Required npm packages:

"moment": "^2.19.4",

"moment-duration-format": "^1.3.0",

"react-moment": "^0.6.8",

import following in reactjs:

 import moment from "moment";
 import Moment from "react-moment";
 import momentDurationFormatSetup from "moment-duration-format";

var DOJ = moment([work_data.joining_date]).format("YYYY,MM,DD");      
var today = moment().format("YYYY,MM,DD");      
var totalMonths =  parseInt(moment(today).diff(moment(DOJ), 'months'));      
var totalDuration = moment.duration(totalMonths, "months").format();      
if(totalDuration.search('1y') > -1) {
   totalDuration = totalDuration.replace("1y", "1 Year,");
} else {
   totalDuration = totalDuration.replace("y", " Years,");
}

if(totalDuration.search('1m') > -1){
  totalDuration = totalDuration.replace("1m", "1 Month");
} else {
  totalDuration = totalDuration.replace("m", " Months");
}

console.log(totalDuration);

Upvotes: 2

Kunal Kapadia
Kunal Kapadia

Reputation: 3353

Moment.js also has duration object. A moment is defined as single point in time, whereas duration is defined as a length of time which is basically what you want.

var a = moment([2015, 11, 29]);
var b = moment([2007, 06, 27]);

var diffDuration = moment.duration(a.diff(b));

console.log(diffDuration.years()); // 8 years
console.log(diffDuration.months()); // 5 months
console.log(diffDuration.days()); // 2 days

What @Josh suggest may work, but is definitely not the right way of calculating difference in 2 moments.

Upvotes: 41

Josh Crozier
Josh Crozier

Reputation: 240938

You could get the difference in years and add that to the initial date; then get the difference in months and add that to the initial date again.

In doing so, you can now easily get the difference in days and avoid using the modulo operator as well.

Example Here

var a = moment([2015, 11, 29]);
var b = moment([2007, 06, 27]);

var years = a.diff(b, 'year');
b.add(years, 'years');

var months = a.diff(b, 'months');
b.add(months, 'months');

var days = a.diff(b, 'days');

console.log(years + ' years ' + months + ' months ' + days + ' days');
// 8 years 5 months 2 days

I'm not aware of a better, built-in way to achieve this, but this method seems to work well.

Upvotes: 81

Related Questions