web-dev-qa-db-fra.com

Différence en mois entre deux dates en JavaScript

Comment pourrais-je calculer la différence pour deux objets Date () en JavaScript, tout en ne renvoyant que le nombre de mois dans la différence?

Toute aide est la bienvenue :)

107
williamtroup

La définition du "nombre de mois dans la différence" est sujette à de nombreuses interprétations. :-)

Vous pouvez obtenir l'année, le mois et le jour du mois à partir d'un objet de date JavaScript. En fonction des informations que vous recherchez, vous pouvez les utiliser pour déterminer le nombre de mois entre deux instants.

Par exemple, de manière informelle, elle permet de connaître le nombre de mois entiers compris entre deux dates, sans compter les mois partiels (par exemple, en excluant le mois dans lequel figure chaque date):

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 15: December 2008, all of 2009, and Jan & Feb 2010

monthDiff(
    new Date(2010, 0, 1),  // January 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 1: February 2010 is the only full month between them

monthDiff(
    new Date(2010, 1, 1),  // February 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 0: There are no *full* months between them

(Notez que les valeurs de mois dans JavaScript commencent par 0 = janvier.)

Inclure les fractions de mois dans ce qui précède est beaucoup plus compliqué, car trois jours en février représentent une fraction plus importante de ce mois (~ 10,714%) que trois jours en août (~ 9,677%), et bien sûr, même février est une cible mobile selon qu'il s'agisse d'une année bissextile.

Il existe également des bibliothèques pour la date et l'heure disponibles en JavaScript qui facilitent probablement ce genre de choses.

195
T.J. Crowder
return DisplayTo.getMonth() - DisplayFrom.getMonth()
       + (12 * (DisplayTo.getFullYear() - DisplayFrom.getFullYear()));
56
Tom Gullen

Parfois, vous voudrez peut-être obtenir uniquement la quantité de mois entre deux dates en ignorant totalement la partie jour. Ainsi, par exemple, si vous aviez deux dates - 2013/06/21 et 2013/10/18 - et que vous vous intéressiez uniquement aux parties 2013/06 et 2013/10, voici les scénarios et les solutions possibles:

var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
  month1++;
  month2++;
}
var numberOfMonths; 

1.Si vous voulez juste le nombre de mois entre les deux dates en excluant les mois 1 et 2

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;

2.Si vous souhaitez inclure l'un des mois

numberOfMonths = (year2 - year1) * 12 + (month2 - month1);

3.Si vous souhaitez inclure les deux mois

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
27

Si vous devez compter des mois entiers, quels que soient les 28, 29, 30 et 31 jours du mois. Ci-dessous devrait fonctionner. 

var months = to.getMonth() - from.getMonth() 
    + (12 * (to.getFullYear() - from.getFullYear()));

if(to.getDate() < from.getDate()){
    months--;
}
return months;

Ceci est une version étendue de la réponse https://stackoverflow.com/a/4312956/1987208 mais corrige le cas où il calcule 1 mois pour le cas du 31 janvier au 1er février (1 jour).

Cela couvrira ce qui suit.

  • 1er janvier au 31 janvier ---> 30 jours ---> donnera 0 (logique car ce n'est pas un mois complet)
  • 1er février au 1er mars ---> 28 ou 29 jours ---> donnera 1 (logique puisque c'est un mois complet)
  • 15 février au 15 mars ---> 28 ou 29 jours ---> donnera 1 (logique depuis le mois écoulé)
  • Du 31 janvier au 1er février ---> 1 jour ---> donnera 0 (évident mais la réponse mentionnée dans l'article après 1 mois)
22
harun

Voici une fonction qui fournit avec précision le nombre de mois entre 2 dates.
Le comportement par défaut ne compte que des mois entiers, par exemple. 3 mois et 1 jour entraîneront une différence de 3 mois. Vous pouvez éviter cela en définissant le paramètre roundUpFractionalMonths sur true. Ainsi, une différence de 3 mois et un jour sera renvoyée sous la forme 4 mois.

La réponse acceptée ci-dessus (réponse de T.J. Crowder) n'est pas précise, elle renvoie parfois des valeurs erronées.

Par exemple, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015')) renvoie 0, ce qui est évidemment faux. La différence correcte est soit un mois entier, soit 2 mois arrondis.

Voici la fonction que j'ai écrite:

function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
    //Months will be calculated between start and end dates.
    //Make sure start date is less than end date.
    //But remember if the difference should be negative.
    var startDate=date1;
    var endDate=date2;
    var inverse=false;
    if(date1>date2)
    {
        startDate=date2;
        endDate=date1;
        inverse=true;
    }

    //Calculate the differences between the start and end dates
    var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
    var monthsDifference=endDate.getMonth()-startDate.getMonth();
    var daysDifference=endDate.getDate()-startDate.getDate();

    var monthCorrection=0;
    //If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
    //The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
    if(roundUpFractionalMonths===true && daysDifference>0)
    {
        monthCorrection=1;
    }
    //If the day difference between the 2 months is negative, the last month is not a whole month.
    else if(roundUpFractionalMonths!==true && daysDifference<0)
    {
        monthCorrection=-1;
    }

    return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};
21
Francisc

Différence en mois entre deux dates en JavaScript:

 start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
 end_date = new Date(new Date(year, month, day)

nombre total de mois entre start_date et end_date:

 total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
7
user3355933

Je sais que c'est très tard, mais l'afficher quand même au cas où cela aiderait les autres. Voici une fonction que j’ai conçue et qui semble bien compter les différences de mois entre deux dates. Certes, il est beaucoup plus volumineux que celui de M. Crowder, mais fournit des résultats plus précis en parcourant l’objet de date. Il est en AS3 mais vous devriez juste être capable de laisser tomber le typage fort et vous aurez JS. N'hésitez pas à le rendre plus beau!

    function countMonths ( startDate:Date, endDate:Date ):int
    {
        var stepDate:Date = new Date;
        stepDate.time = startDate.time;
        var monthCount:int;

        while( stepDate.time <= endDate.time ) { 
            stepDate.month += 1;
            monthCount += 1;
        }           

        if ( stepDate != endDate ) { 
            monthCount -= 1;
        }

        return monthCount;
    }
6
James

Considérons chaque date en termes de mois, puis soustrais pour trouver la différence.

var past_date = new Date('11/1/2014');
var current_date = new Date();

var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());

Cela vous donnera la différence de mois entre les deux dates, en ignorant les jours.

5
internet-nico

Pour développer la réponse de @ T.J., Si vous recherchez des mois simples plutôt que des mois civils complets, vous pouvez simplement vérifier si la date de d2 est supérieure ou égale à celle de d1. C'est-à-dire que si d2 est plus tard dans son mois que d1 est dans son mois, alors il y a 1 mois de plus. Donc, vous devriez être capable de faire ceci:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    // edit: increment months if d2 comes later in its month than d1 in its month
    if (d2.getDate() >= d1.getDate())
        months++
    // end edit
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10

Cela ne tient pas totalement compte des problèmes de temps (par exemple, le 3 mars à 16 heures et le 3 avril à 15 heures), mais c’est plus précis et ne contient que quelques lignes de code.

4
calvin

Il existe deux approches, mathématique et rapide, mais sujette aux aléas du calendrier, ou itérative et lente, mais gère toutes les bizarreries (ou au moins les délégués les manipulant dans une bibliothèque bien testée).

Si vous parcourez le calendrier, incrémentez la date de début d'un mois et vérifiez si nous transmettons la date de fin. Cela délègue le traitement des anomalies aux classes Date () intégrées, mais peut être lent SI vous le faites pendant un grand nombre de dates. La réponse de James adopte cette approche. Bien que cette idée me déplaise, je pense que c’est l’approche la plus "sûre", et si vous ne faites que le calcul un, la différence de performance est vraiment négligeable. Nous avons tendance à essayer de sur-optimiser les tâches qui ne seront effectuées qu'une fois.

Maintenant, si vous calculez cette fonction sur un jeu de données, vous ne voudrez probablement pas exécuter cette fonction sur chaque ligne (ou, au contraire, plusieurs fois par enregistrement). Dans ce cas, vous pouvez utiliser presque toutes les autres réponses ici sauf la réponse acceptée, qui est tout simplement fausse (la différence entre new Date() et new Date() est -1)? 

Voici mon approche mathématique et rapide, qui prend en compte des durées de mois et des années bissextiles différentes. Vous ne devriez vraiment utiliser une fonction de ce type que si vous l'appliquez à un jeu de données (en effectuant ce calcul de manière répétée). Si vous avez juste besoin de le faire une fois, utilisez l'approche itérative de James ci-dessus, car vous déléguez la gestion de toutes les (nombreuses) exceptions à l'objet Date ().

function diffInMonths(from, to){
    var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));

    if(to.getDate() < from.getDate()){
        var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
        if (to < newFrom  && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
            months--;
        }
    }

    return months;
}
4
Michael Blackburn

Ici vous passez d'une autre approche avec moins de bouclage:

calculateTotalMonthsDifference = function(firstDate, secondDate) {
        var fm = firstDate.getMonth();
        var fy = firstDate.getFullYear();
        var sm = secondDate.getMonth();
        var sy = secondDate.getFullYear();
        var months = Math.abs(((fy - sy) * 12) + fm - sm);
        var firstBefore = firstDate > secondDate;
        firstDate.setFullYear(sy);
        firstDate.setMonth(sm);
        firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
        return months;
}
3
ggomeze

Cela devrait bien fonctionner:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months += d2.getMonth() - d1.getMonth();
    return months;
}
2
Thiago Jordan

Le code suivant renvoie des mois entiers entre deux dates en prenant également en compte le nombre de jours de mois partiels.

var monthDiff = function(d1, d2) {
  if( d2 < d1 ) { 
    var dTmp = d2;
    d2 = d1;
    d1 = dTmp;
  }

  var months = (d2.getFullYear() - d1.getFullYear()) * 12;
  months -= d1.getMonth() + 1;
  months += d2.getMonth();

  if( d1.getDate() <= d2.getDate() ) months += 1;

  return months;
}

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0

monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
1
Delorean
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
    var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
          diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24))); 
    d1new = new Date(d2year, d2month, 1,0,0,0,0);
    d1new.setDate(d1new.getDate()-1);
    d1maxday = d1new.getDate();
    months += diffdate / d1maxday;
}
else
{
      if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
    {
        months += 1;
    }
    diffdate = d2day - d1day + 1;
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
    d2new.setDate(d2new.getDate()-1);
    d2maxday = d2new.getDate();
    months += diffdate / d2maxday;
}

return months;

}

1
Tariq

ci-dessous la logique va chercher la différence en mois

(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
1
Anoop Isaac

Calculer la différence entre deux dates comprend la fraction de mois (jours).


var difference = (date2.getDate() - date1.getDate()) / 30 +
    date2.getMonth() - date1.getMonth() +
    (12 * (date2.getFullYear() - date1.getFullYear()));

Par exemple:
date1 : 24/09/2015 (24 septembre 2015)
date2 : 09/11/2015 (9 nov. 2015)
la différence: 2,5 (mois)

1
Shneor
function calcualteMonthYr(){
    var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
    var toDate = new Date($('#txtDurationTo2').val());

var months=0;
        months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
        months -= fromDate.getMonth();
        months += toDate.getMonth();
            if (toDate.getDate() < fromDate.getDate()){
                months--;
            }
    $('#txtTimePeriod2').val(months);
}
1
shoaib fazlani
function monthDiff(date1, date2, countDays) {

  countDays = (typeof countDays !== 'undefined') ?  countDays : false;

  if (!date1 || !date2) {
    return 0;
  }

  let bigDate = date1;
  let smallDate = date2;

  if (date1 < date2) {
    bigDate = date2;
    smallDate = date1;
  }

  let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());

  if (countDays && bigDate.getDate() < smallDate.getDate()) {
    --monthsCount;
  }

  return monthsCount;
}
1
Abbas Siddiqi

Pour la prospérité,

Avec Moment.js vous pouvez y parvenir en faisant: 

const monthsLeft = moment(endDate).diff(moment(startDate), 'month');
0
The224

Il compte également les jours et les convertit en mois.

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;   //calculates months between two years
    months -= d1.getMonth() + 1; 
    months += d2.getMonth();  //calculates number of complete months between two months
    day1 = 30-d1.getDate();  
    day2 = day1 + d2.getDate();
    months += parseInt(day2/30);  //calculates no of complete months lie between two dates
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2017, 8, 8), // Aug 8th, 2017    (d1)
    new Date(2017, 12, 12)  // Dec 12th, 2017   (d2)
);
//return value will be 4 months 
0
Gaurav Jain

anyVar = (((DisplayTo.getFullYear () * 12) + DisplayTo.getMonth ()) - ((DisplayFrom.getFullYear () * 12) + DisplayFrom.getMonth ()));

0
Aris Dela Rea

Vous pouvez également envisager cette solution, cette function renvoie la différence en mois en nombre entier ou en nombre 

Passer la date de débuten tant que première ou dernière param est tolérant aux pannes. Cela signifie que la fonction retournera toujours la même valeur.

const diffInMonths = (end, start) => {
   var timeDiff = Math.abs(end.getTime() - start.getTime());
   return Math.round(timeDiff / (2e3 * 3600 * 365));
}

const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));

// shows month difference as integer/number
console.log(result);

0
Hamzeen Hameem

Voyez ce que j'utilise:

function monthDiff() {
    var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
    var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
    var months = 0;
    while (startdate < enddate) {
        if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
            months++;
            startdate.addMonths(1);
            startdate.addDays(2);
        } else {
            months++;
            startdate.addMonths(1);
        }
    }
    return months;
}
0
Fayez Zalloum