Jak wyliczyłbym różnicę dla dwóch obiektów Date () w JavaScript, zwracając tylko liczbę miesięcy różnicy?
Każda pomoc byłaby świetna :)
Jak wyliczyłbym różnicę dla dwóch obiektów Date () w JavaScript, zwracając tylko liczbę miesięcy różnicy?
Każda pomoc byłaby świetna :)
Odpowiedzi:
Definicja „liczby miesięcy różnicy” jest przedmiotem wielu interpretacji. :-)
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:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
(Zwróć uwagę, że wartości miesiąca w JavaScript zaczynają się od 0 = styczeń).
Uwzględnienie ułamków miesięcy w powyższym 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%) i oczywiście nawet luty jest celem ruchomym w zależności od tego, czy jest to rok przestępny.
Istnieją również biblioteki dat i godzin dostępne dla JavaScript, które prawdopodobnie ułatwiają tego rodzaju czynności.
Uwaga : + 1
w powyższym znajdował się znak , tutaj:
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();
To dlatego, że pierwotnie powiedziałem:
... to pokazuje, ile pełnych miesięcy przypada między dwiema datami, nie licząc częściowych miesięcy (np. z wyłączeniem miesiąca, w którym znajduje się każda data).
Usunąłem go z dwóch powodów:
Okazuje się, że nie liczenie niepełnych miesięcy nie jest tym, czego chce wiele (większość?) Osób przychodzących na odpowiedź, więc pomyślałem, że powinienem je oddzielić.
Nie zawsze działało, nawet w tej definicji. :-D (Przepraszam.)
Jeśli nie bierzesz pod uwagę dnia miesiąca, jest to zdecydowanie prostsze rozwiązanie
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
Należy pamiętać, że indeks miesiąca jest oparty na 0. Oznacza to, że January = 0
i December = 11
.
Czasami możesz chcieć uzyskać tylko liczbę miesięcy między dwiema datami, całkowicie ignorując część dzienną. Na przykład, jeśli miałeś dwie daty - 21.06.2013 i 21.10.2013 - i interesowały Cię tylko 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 chcesz podać tylko liczbę 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;
numberOfMonths=(year2-year1)*12+(month2-month1)+1;
Oto funkcja, która dokładnie podaje liczbę miesięcy między dwiema 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 roundUpFractionalMonths
parametr jako true
, więc różnica 3 miesięcy i 1 dnia zostanie zwrócona jako 4 miesiące.
Przyjęta powyżej odpowiedź (odpowiedź TJ Crowdera) nie jest dokładna, czasami zwraca nieprawidłowe wartości.
Na przykład monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015'))
zwraca, 0
co jest oczywiście błędne. Prawidłowa różnica to zaokrąglony w górę 1 cały miesiąc lub 2 miesiące.
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);
};
Jeśli musisz liczyć pełne miesiące, niezależnie od tego, czy miesiąc to 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 sprawy od 31 stycznia do 1 lutego (1 dzień).
Obejmuje to następujące;
Różnica w miesiącach 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)
łą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())
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 zliczać różnice w miesiącach między dwiema datami. Jest to co prawda o wiele bardziej sprośne niż ten pana Crowdera, ale zapewnia dokładniejsze wyniki, przechodząc przez obiekt daty. Jest w AS3, ale powinieneś być w stanie porzucić mocne pisanie i będziesz mieć JS. Nie krępuj się, aby każdy wyglądał ładniej!
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;
}
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());
Dzięki temu uzyskasz różnicę miesięcy między dwiema datami, ignorując dni.
Aby rozwinąć odpowiedź @ TJ, 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 d1. Oznacza to, że jeśli d2 jest później w swoim miesiącu niż d1 w swoim miesiącu, to jest o 1 miesiąc więcej. 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 wyjaśnia to całkowicie problemów czasowych (np. 3 marca o 16:00 i 3 kwietnia o 15:00), ale jest dokładniejsze i obejmuje tylko kilka linijek kodu.
Istnieją dwa podejścia, matematyczne i szybkie, ale podlegające kaprysom w kalendarzu lub iteracyjne i powolne, ale radzi sobie ze wszystkimi osobliwościami (lub przynajmniej delegaci zajmujący się nimi do dobrze przetestowanej biblioteki).
Jeśli przeglądasz kalendarz, zwiększając datę początkową o jeden miesiąc i sprawdzając, czy minęliśmy datę końcową. Spowoduje to delegowanie obsługi anomalii do wbudowanych klas Date (), ale może być powolne, JEŚLI robisz to dla dużej liczby dat. Odpowiedź Jamesa przyjmuje takie podejście. Chociaż nie podoba mi się ten pomysł, myślę, że jest to „najbezpieczniejsze” podejście, a jeśli wykonujesz tylko jedno obliczenie, różnica w wydajności jest naprawdę znikoma. Staramy się nadmiernie optymalizować zadania, które zostaną wykonane tylko raz.
Teraz, jeśli obliczasz tę funkcję na zbiorze danych, prawdopodobnie nie chcesz uruchamiać tej funkcji w każdym wierszu (lub nie daj Boże, wiele razy na rekord). W takim przypadku możesz użyć prawie wszystkich innych odpowiedzi tutaj, z wyjątkiem zaakceptowanej odpowiedzi, która jest po prostu błędna (różnica między new Date()
a new Date()
wynosi -1)?
Oto moje podejście do matematycznego i szybkiego podejścia, które uwzględnia różne długości miesięcy i lata przestępne. 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 to zrobić tylko raz, użyj iteracyjnego podejścia Jamesa powyżej, ponieważ delegujesz obsługę wszystkich (wielu) 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;
}
Oto inne podejście z mniejszą liczbą zapętleń:
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;
}
Możesz również rozważyć to rozwiązanie, które function
zwraca miesięczną różnicę w liczbie całkowitej lub liczbie
Przekazywanie daty rozpoczęcia jako pierwszej lub ostatniej param
jest odporne na błędy. Oznacza to, że funkcja nadal zwracałaby tę samą wartość.
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);
Oblicz różnicę między dwiema datami z uwzględnieniem ułamka miesiąca (dni).
var difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
Na przykład:
data1 : 24.09.2015 (24.09.2015)
data2 : 11.09.2015 (9.11.2015)
różnica: 2,5 (miesięcy)
To powinno działać dobrze:
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);
}
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))
> 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;
}
poniżej logika pokaże różnicę w miesiącach
(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;
}
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;
}
Zlicza 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
W tym przypadku nie interesują mnie pełne miesiące, część miesięcy, jak długi jest miesiąc itp. Po prostu muszę znać liczbę miesięcy. Odpowiednim przypadkiem w świecie rzeczywistym byłby przypadek składania sprawozdania co miesiąc, a ja muszę wiedzieć, ile powinno być zgłoszeń.
Przykład:
To jest rozbudowany przykład kodu, aby pokazać, dokąd zmierzają liczby.
Weźmy 2 znaczniki czasu, które powinny dać wynik za 4 miesiące
Może się nieznacznie różnić w zależności od wybranej strefy czasowej / czasu. Dzień, minuty i sekundy nie mają znaczenia i można je uwzględnić w sygnaturze czasowej, ale pominiemy to w naszych faktycznych obliczeniach.
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();
To nam daje
(12 * (endYear - startYear)) + 1
do miesiąca końcowego.2 + (12 * (2020 - 2019)) + 1 = 15
15 - 11 = 4
; otrzymujemy wynik za 4 miesiące.
Od listopada 2019 do marca 2022 trwa 29 miesięcy. Jeśli umieścisz je w arkuszu kalkulacyjnym programu Excel, zobaczysz 29 wierszy.
3 + (12 * (2022-2019)) + 1
40 - 11 = 29
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
Jednym z podejść byłoby napisanie prostej usługi WWW w języku Java (REST / JSON) korzystającej z biblioteki JODA
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.