Parce que la définition de "mois" est... flexible, le plus simple est d'utiliser un peu d'arithmétique, comme vous le feriez de calcul dans votre tête, et ne pas impliquer l' Date
classe.
Pour le [a] de l'homme de l'interprétation de "l'âge en mois", la règle est
Calculer la différence entre les deux dates dans le mois,
comme si le jour du mois est le 1er du mois pour les deux dates
Soustraire 1 pour exclure le dernier mois
Ensuite, si le jour du mois du dernier jour de la période est sur
ou après le jour-de-la-mois de la première journée de la période, le [potentiellement partielle] dernier mois est complet: ajouter 1 à restaurer le comte
Une mouche dans la soupe est, depuis des mois contenir un nombre différent de jours, traitant les cas où les 2 mois qui diffèrent par leur nombre de jours.
Si, cependant, à la fin du mois est plus court que le mois de départ, vous pouvez vous retrouver dans une situation où la condition à la limite ne peut jamais être remplies (par exemple, la date de début est le 28 février et la date de fin le 31 Mars. Pour corriger cela, vous devez regarder à la "fin du mois" comme étant une fenêtre allant de la dernière journée du mois de début jusqu'au dernier jour de la fin du mois inclus.
Qui mène à ce code. Je suis à l'aide d'une structure comme suit pour représenter une date:
{
year: 2021 , // 4-digit year
month: 11 , // month of year (1-12 mapping to January-December)
day: 23 // day of month (1-[28-31] depending on year/month
}
S'assurer que les données de cette structure représente une date valide est laissé comme exercice pour le lecteur.
Le code n'est pas très compliqué:
/**
*
* @param {object} bgn - start date of period
* @param {number} bgn.year - 4-digit year
* @param {number} bgn.month - month of year [1-12]
* @param {number} bgn.day - day of month [1-31]
*
* @param {object} end - end date of period
* @param {number} end.year - 4-digit year
* @param {number} end.month - month of year [1-12]
* @param {number} end.day - day of month [1-31]
*
*/
function diffInMonths( bgn , end ) {
const between = ( x , min , max ) => x >= min && x <= max;
// We'll need to add back the final month based on the following:
// - end.day >= bgn.day -- we've passed the month boundary, or
// - end.day is within the end-of-month window
// (when the end month is shorter than the start month)
const needAdjustment = end.day >= bgn.day
|| between( end.day, daysInMonth(bgn), daysInMonth(end) );
const finalMonthAdjustment = needsAdjustment ? 1 : 0;
const deltaM = 12 * ( end.year - bgn.year )
+ ( end.month - bgn.month )
- 1 // remove the final month from the equation
+ finalMonthAdjustment // add in the precomputed final month adjustment
;
return deltaM;
}
/**
*
* @param {object} dt - date
* @param {number} dt.year - 4-digit year
* @param {number} dt.month - month of year [1-12]
* @param {number} dt.day - day of month [1-31]
*
*/
function daysInMonth(dt) {
const leapYear = ( dt.year % 4 === 0 && dt.year % 100 !== 0 ) || dt.year % 400 === 0;
const monthDays = leapYear ? daysPerMonthLeap : daysPerMonth;
const days = monthDays[dt.month];
return days;
}
// jan feb mar apr may jun jul aug sep oct nov dec
// ---------- --- --- --- --- --- --- --- --- --- --- --- ---
const daysPerMonth = [ undefined, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ];
const daysPerMonthLeap = [ undefined, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ];
new Date(userDate.split('/').reverse())
sera presque certainement revenir à une Date non valide.