224 votes

Différence en mois entre deux dates en JavaScript

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

Toute aide serait la bienvenue :)

0 votes

Un mois n'est pas une unité de mesure très précise, car la durée du mois change en fonction du mois dans lequel on se trouve. Si un intervalle dure 30 jours entre janvier et février, c'est moins d'un mois si l'on raisonne en termes de mois de 31 jours, mais plus d'un mois si l'on considère que février compte 28 ou 29 jours.

8 votes

Question pas très bien définie. Est-ce que le 28 février 23:58 au 1er mars 00:01 est un mois ? Ou juste un jour ? Ou seulement trois minutes ? Ou les trois ?

2 votes

La personne qui doit mettre en œuvre cette mesure n'aura probablement pas de réponse, car son responsable n'a aucune idée de ce qu'elle demande :)

322voto

T.J. Crowder Points 285826

La définition du "nombre de mois de différence" est sujette à beaucoup d'interprétation :-)

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

Par exemple, à brûle-pourpoint :

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

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

function test(d1, d2) {
    var diff = monthDiff(d1, d2);
    console.log(
        d1.toISOString().substring(0, 10),
        "to",
        d2.toISOString().substring(0, 10),
        ":",
        diff
    );
}

test(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16

test(
    new Date(2010, 0, 1),  // January 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 2

test(
    new Date(2010, 1, 1),  // February 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 1

(Notez que les valeurs des mois en JavaScript commencent par 0 = janvier).

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

Il y a aussi des bibliothèques de dates et d'heures disponibles pour JavaScript qui rendent probablement ce genre de choses plus faciles.


Note : Il y avait un + 1 dans l'article ci-dessus, ici :

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

C'est parce qu'à l'origine j'ai dit :

...cela permet de savoir combien mois entiers se situent entre deux dates, sans compter les mois partiels (par exemple, en excluant le mois dans lequel se trouve chaque date).

Je l'ai supprimé pour deux raisons :

  1. Le fait de ne pas compter les mois partiels ne correspond pas à ce que souhaitent beaucoup (la plupart ?) des personnes qui viennent chercher la réponse, j'ai donc pensé qu'il fallait les séparer.

  2. Cela n'a pas toujours fonctionné, même selon cette définition. :-D (Désolé.)

163voto

Tom Gullen Points 20826

Si vous ne tenez pas compte du jour du mois, cette solution est de loin la plus simple.

function monthDiff(dateFrom, dateTo) {
 return dateTo.getMonth() - dateFrom.getMonth() + 
   (12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}

//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1

Il faut savoir que l'indice mensuel est basé sur 0. Cela signifie que January = 0 et December = 11 .

15 votes

C'est le code le plus court et le plus facile à comprendre que j'ai vu jusqu'à présent !

0 votes

Rien de compliqué avec celui-ci, si ce n'est le fait que chaque mois commencé est compté. 31/03/2011 -> 01/05/2011 sera deux mois ainsi que 01/03/2011 -> 31/05/2011 mais il devrait être trois pour être exact.

0 votes

Si vous voulez simplement connaître le nombre de mois, celui-ci est PARFAIT. ! !!!! Si vous avez besoin de connaître le nombre de jours du mois, cette application ne fonctionnera pas.

47voto

Francisc Points 11926

Voici une fonction qui fournit avec précision le nombre de mois entre 2 dates.
Le comportement par défaut ne compte que les mois entiers, par exemple, 3 mois et 1 jour donneront une différence de 3 mois. Vous pouvez éviter cela en définissant l'option roundUpFractionalMonths param comme true Ainsi, une différence de 3 mois et 1 jour sera considérée comme 4 mois.

La réponse acceptée ci-dessus (la réponse de T.J. Crowder) n'est pas exacte, 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 deux 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);
};

6 votes

Sérieusement, qui a voté contre ça ? Il a raison, la réponse acceptée est juste... fausse.

2 votes

C'est la meilleure réponse.

0 votes

Ce n'est pas correct si la date 1 est le 22 janvier et la date 2 le 22 août. Il renvoie alors 7, ce qui devrait être 8 ?

34voto

Mike JM Points 3895

Parfois, on peut vouloir obtenir uniquement la quantité de mois entre deux dates en ignorant totalement la partie jour. Ainsi, par exemple, si vous avez deux dates - le 21/06/2013 et le 18/10/2013 - et que vous ne vous intéressez qu'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; 

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

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

Si vous voulez inclure l'un ou l'autre des mois

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

3. si vous voulez inclure les deux mois.

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

0 votes

Bien joué ! Ça a marché parfaitement pour moi.

3 votes

Pour le dernier, je recommanderai : numberOfMonths=(year2-year1)*12+(month2-month1)+1; qui fait la même chose mais qui est plus correct sémantiquement pour moi

0 votes

Oui, une approche agréable et plus élégante.

31voto

harun Points 798

Si vous avez besoin de compter des mois entiers, que le mois compte 28, 29, 30 ou 31 jours. La formule ci-dessous devrait fonctionner.

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

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

Voici 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).

Il s'agit de couvrir les points suivants ;

  • Du 1er janvier au 31 janvier ---> 30 jours ---> donnera 0 (logique puisque ce n'est pas un mois complet).
  • du 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 puisqu'un mois s'est écoulé)
  • 31 janvier au 1er février ---> 1 jour ---> donnera 0 (évident mais la réponse mentionnée dans le post donne 1 mois).

2 votes

C'est ce que je pensais. Je suis venu ici pour vérifier et c'est la seule réponse qui a du sens pour moi.

2 votes

Cela ne fonctionne pas lorsque l'on compare deux mois où le mois est plus court. Par exemple, du 31 mars au 30 avril. Cela fait tous d'avril, la réponse devrait donc être "1".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X