Różnica miesięcy między dwoma datami w JavaScript

Jak obliczyć różnicę dla dwóch obiektów date () w JavaScript, zwracając tylko liczbę miesięcy różnicy?

Każda pomoc byłaby świetna:)

Author: S.L. Barth, 2010-03-29

21 answers

Definicja "liczby miesięcy w różnicy" jest przedmiotem wielu interpretacji. :-)

Możesz pobrać Rok, Miesiąc i dzień miesiąca z obiektu JavaScript date. W zależności od tego, jakich informacji szukasz, możesz ich użyć, aby dowiedzieć się, ile miesięcy dzieli dwa punkty w czasie.

Na przykład, off-the-cuff, to dowiaduje się, ile pełne miesiące leżą między dwiema datami, nie licząc częściowych miesięcy (np. z wyłączeniem miesiąca każdego Data jest w):

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

(zauważ, że wartości miesiąca w JavaScript zaczynają się od 0 = styczeń.)

Włączenie miesięcy ułamkowych do powyższego jest znacznie bardziej skomplikowane, ponieważ trzy dni w typowym lutym to większy ułamek tego miesiąca (~10,714%) niż trzy dni w sierpniu (~9,677%), a oczywiście nawet Luty jest ruchomym celem w zależności od tego, czy jest to rok przestępny.

Istnieje również kilka bibliotek daty i czasu dostępnych dla JavaScript, które prawdopodobnie sprawiają, że łatwiej.

 179
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-18 15:15:20
return DisplayTo.getMonth() - DisplayFrom.getMonth()
       + (12 * (DisplayTo.getFullYear() - DisplayFrom.getFullYear()));
 53
Author: Tom Gullen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-05 16:39:21

Czasami możesz chcieć uzyskać tylko ilość miesięcy między dwiema datami całkowicie ignorując część dnia. Na przykład, jeśli miałeś dwie daty - 2013/06/21 i 2013/10/18-i zależało Ci tylko na częściach 2013/06 i 2013/10, oto scenariusze i możliwe rozwiązania: {]}

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.Jeśli chcesz tylko liczbę miesięcy między dwoma datami z wyłączeniem month1 i month2

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

2.Jeśli chcesz dołączyć jeden z miesięcy

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

3.Jeśli chcesz dołączyć oba miesiące

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
 26
Author: Mikayil Abdullayev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 11:59:45

Jeśli musisz policzyć pełne miesiące, niezależnie od tego, czy miesiąc jest 28, 29, 30 czy 31 dni. Poniżej powinno działać.

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

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

To jest rozszerzona wersja odpowiedzi https://stackoverflow.com/a/4312956/1987208 ale rozwiązuje przypadek, w którym oblicza 1 miesiąc dla przypadku od 31 stycznia do 1 lutego(1 dzień).

To będzie obejmować następujące;

  • od 1 stycznia do 31 stycznia - - - > 30 dni - - - > spowoduje 0 (logiczne, ponieważ nie jest pełne miesiąc)
  • od 1 lutego do 1 marca - - - > 28 lub 29 dni - - - > spowoduje 1 (logiczne, ponieważ jest to pełny miesiąc)
  • od 15 lutego do 15 marca - - - > 28 lub 29 dni - - - > spowoduje 1 (logiczny od miesiąca minął)
  • 31st Jan to 1st Feb - - - > 1 day - - - > will result in 0 (oczywista ale wspomniana odpowiedź w poście daje za 1 miesiąc)
 21
Author: harun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:09

Oto funkcja, która dokładnie podaje liczbę miesięcy między 2 datami.
Domyślne zachowanie liczy tylko całe miesiące, np. 3 miesiące i 1 dzień spowoduje różnicę 3 miesięcy. Możesz temu zapobiec, ustawiając {[1] } param jako true, więc różnica 3 miesięcy i 1 dni zostanie zwrócona jako 4 miesiące.

Zaakceptowana odpowiedź powyżej (odpowiedź T. J. Crowdera) nie jest dokładna, czasami zwraca błędne wartości.

Na przykład, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015')) zwraca 0 co jest oczywiście złe. Prawidłowa różnica to jeden cały miesiąc lub dwa miesiące zaokrąglone w górę.

Oto funkcja, którą napisałem:

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);
};
 19
Author: Francisc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-30 22:08:46

Różnica miesięcy między dwiema datami w 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)

Suma miesięcy między datą początkową i datą końcową:

 total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
 7
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-15 13:41:08

Wiem, że jest bardzo późno, ale publikowanie go i tak na wypadek, gdyby pomogło innym. Oto funkcja wymyśliłem, że wydaje się zrobić dobrą robotę liczenia różnic w miesiącach między dwoma datami. Jest to wprawdzie o wiele bardziej raunchier niż pana Crowdera, ale zapewnia dokładniejsze wyniki, przechodząc przez obiekt daty. Jest w AS3, ale powinieneś po prostu być w stanie rzucić silne typowanie i będziesz miał JS. Nie krępuj się, aby było ładniej wygląda ktoś tam!

    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;
    }
 5
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 21:28:35

Rozważmy każdą datę w kategoriach miesięcy, a następnie odejmij, aby znaleźć różnicę.

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

To da Ci różnicę miesięcy między dwiema datami, ignorując dni.

 5
Author: internet-nico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-22 06:17:32

Aby rozwinąć odpowiedź @T. J., jeśli szukasz prostych miesięcy, a nie pełnych miesięcy kalendarzowych, możesz po prostu sprawdzić, czy data d2 jest większa lub równa niż d1. to znaczy, jeśli d2 jest później w swoim miesiącu niż d1 jest w swoim miesiącu, to jest jeszcze 1 miesiąc. Więc powinieneś być w stanie po prostu to zrobić:

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

Nie uwzględnia to całkowicie problemów czasowych (np. 3 marca o 16:00 i 3 kwietnia o 15: 00), ale jest bardziej dokładny i dotyczy tylko kilku linijek kodu.

 4
Author: calvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-20 21:39:44

Istnieją dwa podejścia, matematyczne i szybkie, ale podlegające kaprysom w kalendarzu, lub iteracyjne i powolne, ale obsługujące wszystkie dziwactwa (lub przynajmniej deleguje obsługę ich do dobrze przetestowanej biblioteki).

Jeśli iterujesz kalendarz, zwiększając datę rozpoczęcia o jeden miesiąc i sprawdzając, czy mijamy datę końcową. To deleguje obsługę anomalii do wbudowanych klas date (), ale może być powolne , Jeśli robisz to przez dużą liczbę dat. James ' answer takes takie podejście. Chociaż nie podoba mi się ten pomysł, myślę, że jest to "najbezpieczniejsze" podejście, a jeśli robisz tylko jedną kalkulację, różnica wydajności naprawdę jest znikoma. Staramy się nadmiernie optymalizować zadania, które będą wykonywane tylko raz.

Teraz, jeśli obliczasz tę funkcję na zbiorze danych, prawdopodobnie nie chcesz uruchamiać tej funkcji w każdym wierszu(lub broń Boże, wiele razy na rekord). W takim przypadku możesz użyć prawie każdej z pozostałych odpowiedzi tutaj z wyjątkiem akceptowana odpowiedź, która jest po prostu zła (różnica między new Date() i new Date() wynosi -1)?

Oto moje podejście matematyczne i szybkie, które uwzględnia różne długości miesięcy i lat przestępnych. Naprawdę powinieneś używać takiej funkcji tylko wtedy, gdy będziesz ją stosować do zbioru danych(wykonując te obliczenia w kółko). Jeśli musisz zrobić to tylko raz, użyj iteracyjnego podejścia Jamesa powyżej, ponieważ delegujesz obsługę wszystkich (wielu) wyjątków od daty() obiekt.
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
Author: Michael Blackburn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 15:27:13

Tutaj idziesz inne podejście z mniejszym zapętleniem:

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
Author: ggomeze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-23 23:21:35

To powinno działać dobrze:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months += d2.getMonth() - d1.getMonth();
    return months;
}
 2
Author: Thiago Jordan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-06 22:06:26
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
Author: shoaib fazlani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-29 06:07:14

Oblicz różnicę między dwoma datami obejmują ułamek miesiąca (dni).


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

Na przykład:
Data 1: 24/09/2015 (24 września 2015)
Data 2: 09/11/2015 (9th Nov 2015)
różnica: 2,5 (miesiące)

 1
Author: Shneor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-03 16:44:59

Następujący kod zwraca pełne miesiące między dwoma datami, biorąc pod uwagę również nr dni częściowych miesięcy.

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
Author: Delorean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 22:07:57
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
Author: Tariq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-16 13:17:44

Poniżej logika pobierze różnicę w miesiącach

(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
 1
Author: Anoop Isaac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-16 00:10:22

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

 0
Author: Aris Dela Rea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-11 06:03:12

Zobacz czego używam:

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
Author: Fayez Zalloum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 12:31:11

Liczy również dni i konwertuje je w miesiącach.

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
Author: Gaurav Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-11 11:12:37

Jednym z rozwiązań byłoby napisanie prostej usługi Java Web Service (REST/JSON) wykorzystującej bibliotekę JODA

Http://joda-time.sourceforge.net/faq.html#datediff

Aby obliczyć różnicę między dwoma datami i wywołać tę usługę z javascript.

Zakłada się, że Twój back end jest w Javie.

 -6
Author: Ravi Chinoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-19 02:00:39