web-dev-qa-db-fra.com

Différence entre deux dates d'années, de mois et de jours en JavaScript

Cela fait maintenant 4 heures que je cherche, et je n'ai pas trouvé de solution pour obtenir la différence entre deux dates en années, mois et jours en JavaScript, par exemple: Le 10 avril 2010, c'était il y a 3 ans, x mois et y jours.

Il y a beaucoup de solutions, mais elles n'offrent que la différence sous forme de jours OR mois OR années, ou sont inexactes (ce qui signifie ne pas prendre en compte le nombre réel de jours dans un mois ou années bissextiles, etc.). Est-ce vraiment si difficile de faire ça? 

J'ai regardé: 

En php, c'est facile, mais malheureusement, je ne peux utiliser qu'un script côté client sur ce projet. Toute bibliothèque ou tout cadre capable de le faire conviendrait également.

Voici une liste des résultats attendus pour les différences de date:

//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'));
35
Chris

À quel point devez-vous être précis? Si vous avez besoin de prendre en compte les années communes et les années bissextiles, ainsi que la différence exacte en jours entre mois, vous devrez écrire quelque chose de plus avancé, mais pour un calcul basique et approximatif, cela devrait faire l'affaire:

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

N'oubliez pas que ceci est imprécis. Pour calculer la date avec précision, il vous faut un calendrier et savoir si une année est une année bissextile, le calcul du nombre de mois est approximatif. . 

Mais vous pouvez l’améliorer facilement. 

29
Pawel Miech

En fait, il y a une solution avec un plugin moment.js et c'est très facile.

Vous pouvez utiliser moment.js

Ne réinventez plus la roue.

Il suffit de brancher Moment.js Date Range Plugin .


Exemple:

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>

12
Inanc Gumus

J'ai utilisé ce code simple pour obtenir la différence en années, mois, jours avec la date actuelle.

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");
12
Rajeev P Nadig

Pour une utilisation rapide et facile, j’ai écrit cette fonction il ya quelque temps. Il retourne le diff entre deux dates au format Nice. N'hésitez pas à l'utiliser (testé sur 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;
}
5
Chris

Je pense que vous recherchez la même chose que je voulais. J'ai essayé de le faire en utilisant la différence en millisecondes fournie par javascript, mais ces résultats ne fonctionnent pas dans le monde réel des dates. Si vous voulez la différence entre le 1er février 2016 et le 31 janvier 2017, le résultat souhaité serait 1 an, 0 mois et 0 jours. Exactement un an (en supposant que vous comptiez le dernier jour comme une journée complète, comme dans le cas d'un bail pour un appartement). Cependant, l’approche en millisecondes vous donnerait 1 an 0 mois et 1 jour, car la plage de dates comprend une année bissextile. Voici donc le code que j'ai utilisé en javascript pour mon formulaire Adobe (vous pouvez nommer les champs): (modifié, il y a une erreur que j'ai corrigée)

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)"
3
Murray

Quelques maths sont en ordre.

Vous pouvez soustraire un objet Date d'un autre en Javascript et vous obtiendrez la différence en milissecondes. A partir de ce résultat, vous pouvez extraire les autres parties souhaitées (jours, mois, etc.)

Par exemple:

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.

Maintenant, vous pouvez obtenir n'importe quelle partie de votre choix. Par exemple, combien de jours se sont écoulés entre les deux dates:

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.

C'est presque 31 jours. Vous pouvez ensuite arrondir pendant 30 jours et utiliser ce qui reste pour obtenir le nombre d'heures, de minutes, etc.

2
Renan

J'ai créé une autre fonction à cet effet:

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

Ne nécessite aucune bibliothèque tierce. Prend un argument - date au format AAAA-MM-JJ.

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

2
Jakub Pelák
   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));

L'extrait ci-dessus sera imprimé: Année: 1, Mois: 4, Jours: 2

2
Nilesh Patel

Une autre solution encore, basée sur du code PHP . La fonction strtotime, également basée sur PHP, est disponible ici: 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;
};

Usage:

> 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
}
2
webtweakers

La réponse de @ RajeevPNadig correspond à ce que je cherchais, mais le code retourne des valeurs incorrectes telles qu'écrites. 

Ma modification de sa réponse a été rejetée et on m'a dit de l'afficher comme ma propre réponse. Cela peut donner des résultats un peu bizarres, mais techniquement incorrects.

// startDate must be a
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");
}

Ensuite, vous pouvez l'utiliser comme ceci:

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

Les choses peuvent devenir un peu bizarres si vous appelez dateAgo avec la date actuelle et n'utilisez pas de chaîne AAAA-MM-JJ, c'est-à-dire:

oneMinuteAgo = Date.now() - 60000;
dateAgo(oneMinuteAgo); // "0Y 11M 30D" -- ???

Si votre cas d'utilisation est uniquement une chaîne de date, cela devrait plutôt bien fonctionner pour la plupart des gens.

2
Mordred

Ce lien a la meilleure réponse http://forums.asp.net/t/1610039.aspx?How+to+calculate+difference+b+++++++++++++

Il vous suffit d'ajouter une validation pour les jours, comme par exemple:

if (firstDate.getDate () <= now.getDate ())

1
myself

Ce qui suit est un algorithme qui donne correct mais pas totalement précis car il ne prend pas en compte les années bissextiles. Cela suppose également 30 jours par mois. Un bon usage, par exemple, est que si quelqu'un habite dans une adresse du 12/11/2010 au 11/10/2011, cela indique rapidement que la personne y habite pendant 10 mois et 29 jours. Du 12/11/2010 au 11/12/2011 correspond à 11 mois et un jour. Pour certains types d'applications, ce type de précision est suffisant. Ceci est pour ces types d'applications car il vise la simplicité:

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

Tests unitaires

0
Kevin Le - Khnle

Je sais que c'est un vieux fil, mais j'aimerais mettre mes 2 centimes sur la réponse de @Pawel Miech.

Il est vrai que vous devez convertir la différence en millisecondes, puis vous devez faire quelques calculs. Mais remarquez que vous devez faire les calculs de manière arriérée, c’est-à-dire que vous devez calculer les années, les mois, les jours, les heures puis les minutes.

Je faisais quelque chose comme ça:

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

Mais, bien sûr, ceci n’est pas précis car cela suppose que toutes les années ont 365 jours et que tous les mois 30 jours, ce qui n’est pas vrai dans tous les cas.

0
Dr. MAF

Personnellement, j'utiliserais http://www.datejs.com/ , vraiment pratique. Plus précisément, consultez le fichier time.js: http://code.google.com/p/datejs/source/browse/trunk/src/time.js

0
Joe Minichino

Pour calculer la différence entre deux dates en années, mois, jours, minutes, secondes et millisecondes à l'aide de 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
        }

Cependant, vous pouvez mettre à jour la logique ci-dessus pour que le message affiche également les secondes et les millisecondes, ou bien utilisez l'objet 'r' pour formater le message comme vous le souhaitez.

Si vous voulez copier directement le code, vous pouvez voir mon résumé avec le code ci-dessus ici

0
Sai Nikhil

Durée en jours, heures, minutes, secondes et millisecondes:

// 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
} */
0
Oleg

Aucun des codes ne fonctionne pour moi, je l'utilise donc pendant des mois et des jours:

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.
    }
}
0

Très vieux fil, je sais, mais voici ma contribution, car le fil n'est pas encore résolu.

Il prend en considération les années bissextiles et ne suppose pas un nombre fixe de jours par mois ou par année.

Cela peut être imparfait dans les cas à la frontière car je ne l’ai pas testé de manière approfondie, mais cela fonctionne pour toutes les dates fournies dans la question initiale;.

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
David SN