Różnica w miesiącach między dwiema datami w roku JavaScript


Jak obliczyć różnicę dla dwóch obiektów Date () w JavaScript i zwrócić tylko liczbę miesięcy różnicy?
Każda pomoc byłaby bardzo pomocna :)
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Definicja „liczby miesięcy różnicy” podlega wielu interpretacjom. :-)
Możesz pobrać rok, miesiąc i dzień miesiąca z obiektu daty JavaScript. W zależności od tego, jakich informacji szukasz, możesz ich użyć, aby dowiedzieć się, ile miesięcy dzieli się między dwoma punktami w czasie.
Na przykład, poza mankietem, to oblicza, ile

pełne miesiące

leży między dwiema datami, nie licząc niepełnych miesięcy (na przykład z wyłączeniem miesiąca, w którym znajduje się każda data):
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 2010monthDiff( 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 themmonthDiff( 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

(Zwróć uwagę, że wartości miesiąca w JavaScript zaczynają się od 0 = styczeń).
Uwzględnienie ułamkowych miesięcy w powyższym jest znacznie trudniejsze, ponieważ trzy dni w typowym lutym to więcej tego miesiąca (~ 10,714%) niż trzy dni w sierpniu (~ 9,677%), a oczywiście nawet luty jest celem ruchomym w zależności od tego, czy to rok przestępny.
Jest też kilka

biblioteki daty i czasu
http://www.datejs.com/
dostępne dla JavaScript, co prawdopodobnie ułatwi to zadanie.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli nie liczysz dnia miesiąca, to jest to znacznie prostsze rozwiązanie.
<div class="snippet-code">
<div class="snippet" data-babel="false" data-console="true" data-hide="false" data-lang="js">
<pre class="snippet-code-js lang-js prettyprint-override">
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

Zauważ, że indeks miesiąca jest liczony od zera, co oznacza
styczeń = 0
i
grudzień = 11
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Czasami można uzyskać tylko liczbę 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 dbałeś tylko o części 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;

Jeśli potrzebujesz tylko liczby miesięcy między dwiema datami, z wyłączeniem miesiąca1 i miesiąca2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;

2. Jeśli chcesz uwzględnić którykolwiek z miesięcy
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);

3. Jeśli chcesz uwzględnić oba miesiące
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Oto funkcja, która dokładnie określa liczbę miesięcy między dwiema datami.

Domyślne zachowanie liczy tylko całe miesiące, na przykład 3 miesiące i 1 dzień spowoduje różnicę 3 miesięcy. Możesz temu zapobiec, ustawiając
roundUpFractionalMonths
na
true
, aby różnica 3 miesięcy i 1 dnia została zwrócona jako 4 miesiące.

Przyjęta powyżej odpowiedź (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 ewidentnie niepoprawne. Prawidłowa różnica to zaokrąglenie do 1 całego miesiąca lub 2 miesięcy.
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);
};
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli musisz liczyć pełne miesiące, bez względu na to, który miesiąc to 28, 29, 30 lub 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
https://stackoverflow.com/a/4312956/1987208
ale rozwiązuje przypadek, w którym oblicza 1 miesiąc dla sprawy od 31 stycznia do 1 lutego (1 dzień).
Obejmuje to następujące;
  • Od 1 stycznia do 31 stycznia - - - & > 30 dni - - - & > da wynik 0 (logiczne, ponieważ nie jest to pełny miesiąc)
  • 1 lutego do 1 marca - - - & > 28 lub 29 dni - - - & > da wynik 1 (logiczne, ponieważ jest to pełny miesiąc)
  • 15 lutego do 15 marca - - - & > 28 lub 29 dni - - - & > da wynik 1 (logiczne, ponieważ minął miesiąc)
  • 31 stycznia do 1 lutego - - - & > 1 dzień - - - & > da wynik 0 (oczywiście, ale wspomniana odpowiedź w poście to 1 miesiąc)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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

łączna liczba miesięcy między datą_początkową a datą_końcową:
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wiem, że to naprawdę późno, ale i tak publikuję to na wypadek, gdyby to pomogło innym. Oto funkcja, którą wymyśliłem, która wydaje się dobrze radzić sobie z obliczaniem różnicy w miesiącach między dwiema datami. Jest wprawdzie znacznie bardziej szorstki niż ten pana Crowdera, ale daje dokładniejsze wyniki podczas przechodzenia przez obiekt daty. Jest w AS3, ale powinieneś być w stanie porzucić mocne pisanie i masz JS. Nie krępuj się, aby było ładniej, patrząc na kogoś!
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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Aby rozwinąć odpowiedź @ T.J., jeśli szukasz prostych miesięcy zamiast pełnych miesięcy kalendarzowych, możesz po prostu sprawdzić, czy data d2 jest większa lub równa dacie d1. to znaczy, jeśli d2 przypada później w swoim miesiącu niż d1 w swoim miesiącu, czyli o 1 miesiąc dłużej. Więc powinieneś być w stanie zrobić to po prostu:
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 w pełni problemów z synchronizacją (np. 3 marca o 16:00 i 3 kwietnia o 15:00), ale jest dokładniejsze i obejmuje tylko kilka wierszy kodu.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Rozważ 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ę w miesiącach między dwiema datami, z pominięciem dni.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Istnieją dwa podejścia: matematyczne & amp; szybkie, ale kapryśne w kalendarzu lub iteracyjne & amp; powolny, ale radzący sobie ze wszystkimi osobliwościami (lub przynajmniej delegujący przetwarzanie do dobrze przetestowanej biblioteki).
Jeśli przejrzysz kalendarz, zwiększ datę początkową o jeden miesiąc i sprawdź, czy minęła data końcowa. To deleguje obsługę anomalii do wbudowanych klas Date (), ale może być powolne

IF

robisz to przez wiele randek. Odpowiedź Jamesa opiera się na tym podejściu. Chociaż bardzo mi się podoba ten pomysł, myślę, że jest to „najbezpieczniejsze” podejście i jeśli tylko to robisz

jeden

obliczenia, różnica w wydajności jest naprawdę znikoma. Staramy się nadmiernie optymalizować zadania, które zostaną uruchomione tylko raz.
Teraz,

Jeśli

obliczasz tę funkcję na zbiorze danych, prawdopodobnie nie chcesz uruchamiać tej funkcji na każdym wierszu (lub, nie daj Boże, wiele razy w rekordzie). W takim przypadku możesz użyć tutaj prawie wszystkich innych odpowiedzi.

Oprócz

zaakceptowanej odpowiedzi, która jest po prostu błędna (czy różnica między
new Date ()
a
new Date ()
wynosi -1)?
Oto mój hit w matematycznym i szybkim podejściu, które bierze pod uwagę różne długości miesięcy i lata przestępne. Takiej funkcji powinieneś używać tylko wtedy, gdy będziesz ją stosować do zbioru danych (wykonując te obliczenia więcej & amp; razy). Jeśli musisz to zrobić tylko raz, użyj iteracyjnego podejścia Jamesa powyżej, ponieważ delegujesz wszystkie (wiele) obsługi wyjątków do obiektu 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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Tutaj
http://ggomeze.com/2011/12/07/ ... cript
ty i inne podejście z mniejszą liczbą pętli:
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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz również rozważyć to rozwiązanie, ta
funkcja
zwraca różnicę miesięcy w wyrażeniu całkowitym lub liczbowym
Nadawanie


daty rozpoczęcia
jako pierwszy lub ostatni,
param
to przełączanie awaryjne. Oznacza to, że funkcja nadal zwraca tę samą wartość.
<div class="snippet-code">
<div class="snippet" data-babel="false" data-console="true" data-hide="false" data-lang="js">
<pre class="snippet-code-js lang-js prettyprint-override">
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);
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Oblicz różnicę między dwiema datami obejmującymi ułamki miesiąca (-ów).
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: 11.09.2015

(9 listopada 2015)

różnica: 2,5 (miesiące)

Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To powinno działać dobrze:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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);
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Poniższy kod zwraca pełne miesiące między dwiema datami, biorąc również pod uwagę liczbę dni niepełnych 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))
> 1monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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;

}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

poniżej logika przyniesie różnicę w miesiącach
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Zlicza również dni i zamienia je na miesiące.

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
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Liczba miesięcy, w których dzień & amp; czas nie ma znaczenia
>
W tym przypadku nie interesują mnie pełne miesiące, niepełne miesiące, jak długo trwa miesiąc itp. Muszę tylko znać liczbę miesięcy.

Istotnym przypadkiem w prawdziwym świecie byłoby to, że raport musi być gotowy co miesiąc, a ja muszę wiedzieć, ile powinno ich być.

Przykład:
  • Styczeń = 1 miesiąc
  • Styczeń - luty = 2 miesiące
  • Listopad - styczeń = 3 miesiące

To jest szczegółowy przykład kodu, aby pokazać, gdzie idą liczby.

Weźmy 2 znaczniki czasu, które powinny zająć 4 miesiące

  • Znacznik czasu 13 listopada 2019 roku: 1573621200000
  • 20 lutego 2020 sygnatura czasowa: 1582261140000
Może się nieco różnić w przypadku ściągania strefy czasowej/czasu. Dzień, minuty i sekundy nie mają znaczenia i mogą być uwzględnione w sygnaturze czasowej, ale zignorujemy je w naszych rzeczywistych obliczeniach.


Krok 1: Konwersja znacznika czasu na datę JavaScript
>
let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);


Krok 2: Uzyskaj wartości całkowite dla miesięcy/lat
>
let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();


To nam daje

  • Początek miesiąca: 11
  • Rok rozpoczęcia: 2019
  • Koniec miesiąca: 2
  • Rok końcowy: 2020


Krok 3: dodaj
(12 * (endYear - startYear)) + 1
do końca miesiąca.
>
  • To sprawia, że ​​nasz początkowy miesiąc pobytu to 11
  • To sprawia, że ​​nasz ostatni miesiąc to 15
    2 + (12 * (2020-2019)) + 1 = 15


Krok 4: odejmij miesiące
>
15 - 11 = 4
; otrzymujemy wynik za 4 miesiące.

Przykład 29 miesięcy
>
Listopad 2019-marzec 2022 to 29 miesięcy. Jeśli umieścisz je w arkuszu kalkulacyjnym programu Excel, zobaczysz 29 wierszy.
  • Nasz miesiąc początkowy to 11
  • Nasz ostatni miesiąc to 40
    3 + (12 * (2022-2019)) + 1


40 - 11 = 29
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

getMonthDiff(d1, d2) {
var year1 = dt1.getFullYear();
var year2 = dt2.getFullYear();
var month1 = dt1.getMonth();
var month2 = dt2.getMonth();
var day1 = dt1.getDate();
var day2 = dt2.getDate();
var months = month2 - month1;
var years = year2 -year1
days = day2 - day1;
if (days < 0) {
months -= 1;
}
if (months < 0) {
months += 12;
}
return months + years*!2;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jednym z podejść byłoby napisanie prostej usługi sieciowej Java (REST/JSON), która korzysta z biblioteki JODA
http://joda-time.sourceforge.net/faq.html#datediff
http://joda-time.sourceforge.net/faq.html#datediff
obliczyć różnicę między dwiema datami i zadzwonić do tej usługi z javascript.
Zakłada się, że Twoje zaplecze jest w Javie.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się