Comment calculer la différence pour deux objets Date () en JavaScript, tout en ne renvoyant que le nombre de mois de la différence?
Toute aide est la bienvenue :)
Comment calculer la différence pour deux objets Date () en JavaScript, tout en ne renvoyant que le nombre de mois de la différence?
Toute aide est la bienvenue :)
Réponses:
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 combien de mois s'écoulent entre deux moments.
Par exemple, tout de suite:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
(Notez que les valeurs de mois dans JavaScript commencent par 0 = janvier.)
Inclure des fractions de mois dans ce qui précède est beaucoup plus compliqué, car trois jours en février typique représentent une plus grande fraction 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 que c'est une année bissextile.
Il existe également des bibliothèques de date et d'heure disponibles pour JavaScript qui facilitent probablement ce genre de chose.
Remarque : il y avait un + 1
dans ce qui précède, 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 de mois entiers se trouvent entre deux dates, sans compter les mois partiels (par exemple, en excluant le mois de chaque date).
Je l'ai supprimé pour deux raisons:
Ne pas compter les mois partiels ne s'avère pas être ce que veulent beaucoup (la plupart?) Des personnes qui viennent à la réponse, alors j'ai pensé que je devrais les séparer.
Cela n'a pas toujours fonctionné même selon cette définition. :-D (Désolé.)
Si vous ne considérez pas le jour du mois, c'est de loin la solution 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
Sachez que l'indice mensuel est basé sur 0. Cela signifie que January = 0
et December = 11
.
Parfois, vous voudrez peut-être obtenir juste 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 ne vous souciez que des 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, à l'exclusion du mois1 et du mois2
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;
numberOfMonths=(year2-year1)*12+(month2-month1)+1;
qui fait la même chose mais est plus sémantiquement correct pour moi
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 entraîneront une différence de 3 mois. Vous pouvez éviter cela en définissant le paramètre roundUpFractionalMonths
sur true
, donc une différence de 3 mois et 1 jour sera renvoyée comme 4 mois.
La réponse acceptée ci-dessus (réponse de TJ 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'))
renvoie0
ce qui est manifestement faux. La différence correcte est soit 1 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);
};
Si vous devez compter des mois entiers, quel que soit le mois qui est 28, 29, 30 ou 31 jours. 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 les éléments suivants;
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)
mois au total entre start_date et end_date:
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
Je sais que c'est vraiment tard, mais le poster quand même au cas où cela aiderait les autres. Voici une fonction que j'ai inventée qui semble faire un bon travail de comptage des différences en mois entre deux dates. Il est certes beaucoup plus torride que celui de Mr.Crowder, mais fournit des résultats plus précis en parcourant l'objet de date. Il est en AS3 mais vous devriez simplement pouvoir supprimer le typage fort et vous aurez JS. N'hésitez pas à le rendre plus agréable à regarder n'importe qui là-bas!
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;
}
Pour développer la réponse de @ TJ, 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 à d1. Autrement dit, si d2 est plus tard dans son mois que d1 est dans son mois, alors il y a 1 mois de plus. Vous devriez donc pouvoir 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 à 16h00 et le 3 avril à 15h00), mais c'est plus précis et pour seulement quelques lignes de code.
Considérez chaque date en mois, puis soustrayez 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.
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 du 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 voyez si nous dépassons la date de fin. Cette délégués de traitement anomalie des classes intégrées Date (), mais pourrait être lent SI vous faites cela pour un grand nombre de dates. La réponse de James adopte cette approche. Autant je n'aime pas l'idée, je pense que c'est l'approche la plus "sûre", et si vous ne faites qu'un seul calcul, la différence de performance est vraiment négligeable. Nous avons tendance à essayer de sur-optimiser les tâches qui ne seront exécutées qu'une seule fois.
Maintenant, si vous calculez cette fonction sur un ensemble de données, vous ne voulez probablement pas exécuter cette fonction sur chaque ligne (ou Dieu nous en préserve, 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 erronée (différence entre new Date()
et new Date()
est -1)?
Voici ma tentative d'une approche mathématique et rapide, qui tient compte des différentes longueurs de mois et des années bissextiles. Vous ne devriez vraiment utiliser une fonction comme celle-ci que si vous allez l'appliquer à un ensemble de données (faire ce calcul encore et encore). 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;
}
Voici une autre approche avec moins de boucles:
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;
}
Vous pouvez également envisager cette solution, cela function
renvoie la différence du mois en entier ou en nombre
Passer la date de début comme premier ou dernier param
est tolérant aux pannes. Cela signifie que la fonction renverrait toujours la même valeur.
const diffInMonths = (end, start) => {
var timeDiff = Math.abs(end.getTime() - start.getTime());
return Math.round(timeDiff / (2e3 * 3600 * 365.25));
}
const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));
// shows month difference as integer/number
console.log(result);
Calculez la différence entre deux dates en incluant une 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 novembre 2015)
la différence: 2,5 (mois)
Cela devrait fonctionner correctement:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
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);
}
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
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;
}
sous la logique va chercher la différence en mois
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
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;
}
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;
}
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
Dans ce cas, je ne suis pas concerné par les mois complets, les mois partiels, la durée d'un mois, etc. J'ai juste besoin de connaître le nombre de mois. Un cas réel pertinent serait celui où un rapport est dû chaque mois, et j'ai besoin de savoir combien de rapports il devrait y avoir.
Exemple:
Ceci est un exemple de code élaboré pour montrer où vont les nombres.
Prenons 2 horodatages qui devraient résulter en 4 mois
Peut être légèrement différent avec votre fuseau horaire / heure tiré. Le jour, les minutes et les secondes n'ont pas d'importance et peuvent être inclus dans l'horodatage, mais nous ne le tiendrons pas compte dans notre calcul réel.
let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);
let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();
Cela nous donne
(12 * (endYear - startYear)) + 1
au mois de fin.2 + (12 * (2020 - 2019)) + 1 = 15
15 - 11 = 4
; nous obtenons notre résultat de 4 mois.
De novembre 2019 à mars 2022, la durée est de 29 mois. Si vous les mettez dans une feuille de calcul Excel, vous verrez 29 lignes.
3 + (12 * (2022-2019)) + 1
40 - 11 = 29
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
Une approche serait d'écrire un simple service Web Java (REST / JSON) qui utilise la bibliothèque JODA
http://joda-time.sourceforge.net/faq.html#datediff
pour calculer la différence entre deux dates et appeler ce service à partir de javascript.
Cela suppose que votre back-end est en Java.