Как мне определить разницу для двух объектов Date () в JavaScript, возвращая только количество месяцев в разнице?
Любая помощь была бы замечательной :)
Как мне определить разницу для двух объектов Date () в JavaScript, возвращая только количество месяцев в разнице?
Любая помощь была бы замечательной :)
Определение «количество месяцев в разнице» допускает множество толкований. :-)
Вы можете получить год, месяц и день месяца из объекта даты JavaScript. В зависимости от того, какую информацию вы ищете, вы можете использовать ее, чтобы выяснить, сколько месяцев проходит между двумя точками времени.
Например, без манжета:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
function test(d1, d2) {
var diff = monthDiff(d1, d2);
console.log(
d1.toISOString().substring(0, 10),
"to",
d2.toISOString().substring(0, 10),
":",
diff
);
}
test(
new Date(2008, 10, 4), // November 4th, 2008
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 16
test(
new Date(2010, 0, 1), // January 1st, 2010
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 2
test(
new Date(2010, 1, 1), // February 1st, 2010
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 1
(Обратите внимание, что значения месяца в JavaScript начинаются с 0 = январь.)
Включение дробных месяцев в приведенное выше намного сложнее, потому что три дня в обычном феврале составляют большую часть этого месяца (~ 10,714%), чем три дня в августе (~ 9,677%), и, конечно, даже февраль является подвижной целью. в зависимости от того, високосный ли год.
Есть также несколько библиотек даты и времени для JavaScript, которые, вероятно, упрощают подобные вещи.
Примечание. Раньше здесь был + 1
:
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();
Это потому, что изначально я сказал:
... это определяет, сколько полных месяцев лежит между двумя датами, не считая неполных месяцев (например, исключая месяц, в котором находится каждая дата).
Я удалил его по двум причинам:
Оказалось, что не считать неполные месяцы - это не то, чего хотят многие (большинство?) Людей, приходящих к ответу, поэтому я подумал, что мне следует их разделить.
Это не всегда срабатывало даже по такому определению. :-D (извините.)
Если вы не учитываете день месяца, это намного более простое решение.
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
Имейте в виду, что индекс месяца отсчитывается от 0. Это означает, что January = 0
и December = 11
.
Иногда вам может понадобиться получить только количество месяцев между двумя датами, полностью игнорируя часть дня. Так, например, если у вас было две даты - 2013/06/21 и 2013/10/18 - и вас интересовали только части 2013/06 и 2013/10, вот сценарии и возможные решения:
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.Если вы хотите только количество месяцев между двумя датами, исключая как month1, так и month2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2. Если вы хотите включить любой из месяцев
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);
3.Если вы хотите включить оба месяца
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
numberOfMonths=(year2-year1)*12+(month2-month1)+1;
, который делает то же самое, но для меня более семантически верен
- person Natim; 05.09.2013
Вот функция, которая точно определяет количество месяцев между двумя датами.
По умолчанию учитываются только целые месяцы, например 3 месяца и 1 день дают разницу в 3 месяца. Вы можете предотвратить это, установив для параметра roundUpFractionalMonths
значение true
, поэтому разница в 3 месяца и 1 день будет возвращена как 4 месяца.
Принятый ответ выше (ответ Т.Дж. Краудера) неточен, иногда он возвращает неверные значения.
Например, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015'))
возвращает 0
, что явно неверно. Правильная разница - либо 1 целый месяц, либо 2 месяца, округленные в большую сторону.
Вот функция, которую я написал:
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);
};
Если вам нужно считать полные месяцы, независимо от того, в каком месяце 28, 29, 30 или 31 день. Ниже должно работать.
var months = to.getMonth() - from.getMonth()
+ (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
months--;
}
return months;
Это расширенная версия ответа https://stackoverflow.com/a/4312956/1987208, но исправляет случай, когда он рассчитывает 1 месяц для случая с 31 января по 1 февраля (1 день).
Это будет охватывать следующее;
Разница в месяцах между двумя датами в 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)
общее количество месяцев между start_date и end_date:
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
Я знаю, что это действительно поздно, но все равно размещаю его на всякий случай, если это поможет другим. Вот функция, которую я придумал, которая, кажется, хорошо справляется с подсчетом разницы в месяцах между двумя датами. По общему признанию, он намного грубее, чем у мистера Краудера, но дает более точные результаты, если переходить через объект даты. Это в AS3, но вы должны просто отказаться от строгой типизации, и у вас будет JS. Не стесняйтесь делать это красивее всех!
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;
}
Чтобы расширить ответ @TJ., если вы ищете простые месяцы, а не полные календарные месяцы, вы можете просто проверить, больше ли дата d2 или равна d1. То есть, если d2 позже в своем месяце, чем d1 в своем месяце, то есть еще 1 месяц. Итак, вы должны просто сделать это:
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
Это не полностью учитывает проблемы со временем (например, 3 марта в 16:00 и 3 апреля в 15:00), но это более точно и содержит всего пару строк кода.
Считайте каждую дату месяцами, а затем вычтите, чтобы найти разницу.
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());
Это даст вам разницу в месяцах между двумя датами без учета дней.
Вы также можете рассмотреть это решение, это function
возвращает разницу в месяцах в виде целых или числовых значений.
Передача даты начала в качестве первого или последнего param
является отказоустойчивым. Это означает, что функция все равно вернет то же значение.
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);
Есть два подхода: математический и быстрый, но с учетом капризов в календаре, или итеративный и медленный, но обрабатывает все странности (или, по крайней мере, делегирует их обработку хорошо протестированной библиотеке).
Если вы перебираете календарь, увеличивая дату начала на один месяц и проверяя, передаем ли мы дату окончания. Это делегирует обработку аномалий встроенным классам Date (), но может быть медленным, ЕСЛИ вы делаете это для большого количества дат. В ответе Джеймса используется такой подход. Как бы мне ни не нравилась эта идея, я считаю, что это «самый безопасный» подход, и если вы выполняете только одно вычисление, разница в производительности действительно незначительна. Мы стараемся чрезмерно оптимизировать задачи, которые будут выполняться только один раз.
Теперь, если вы вычисляете эту функцию для набора данных, вы, вероятно, не захотите запускать эту функцию для каждой строки (или не дай бог, несколько раз для каждой записи). В этом случае вы можете использовать почти любой из других ответов здесь кроме принятого ответа, который просто неверен (разница между new Date()
и new Date()
равна -1)?
Вот мой подход к математическому и быстрому подходу, который учитывает разную длину месяцев и високосные годы. Вам действительно следует использовать такую функцию, только если вы будете применять ее к набору данных (выполняя этот расчет снова и снова). Если вам просто нужно сделать это один раз, используйте итерационный подход Джеймса, описанный выше, поскольку вы делегируете обработку всех (многих) исключений объекту 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;
}
Вот,, пожалуйста другой подход с меньшим количеством циклов:
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;
}
Вычислите разницу между двумя датами, включая долю месяца (дней).
var difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
Например:
date1: 24.09.2015 (24 сентября 2015 г.)
date2: 09/11/2015 (9 ноября 2015 г.) < br> разница: 2,5 (мес)
Это должно работать нормально:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
Следующий код возвращает полные месяцы между двумя датами, учитывая также количество дней неполных месяцев.
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
ниже логика получит разницу в месяцах
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
В данном случае меня не интересуют полные месяцы, неполные месяцы, длина месяца и т. Д. Мне просто нужно знать количество месяцев. Подходящим случаем из реальной жизни может быть ситуация, когда отчет должен представляться каждый месяц, и мне нужно знать, сколько отчетов должно быть.
Пример:
Это тщательно продуманный пример кода, показывающий, куда идут числа.
Давайте возьмем 2 отметки времени, которые должны дать 4 месяца
Может немного отличаться от вашего часового пояса / времени. День, минуты и секунды не имеют значения и могут быть включены в метку времени, но мы проигнорируем их при наших фактических расчетах.
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();
Это дает нам
(12 * (endYear - startYear)) + 1
к конечному месяцу.2 + (12 * (2020 - 2019)) + 1 = 15
15 - 11 = 4
; получаем результат за 4 месяца.
С ноября 2019 года по март 2022 года - 29 месяцев. Если вы поместите их в электронную таблицу Excel, вы увидите 29 строк.
3 + (12 * (2022-2019)) + 1
40–11 = 29
Это самое простое решение, которое я смог найти. Это напрямую вернет количество месяцев. Хотя всегда дает абсолютное значение.
new Date(new Date(d2) - new Date(d1)).getMonth();
Для неабсолютных значений вы можете использовать следующее решение:
function diff_months(startDate, endDate) {
let diff = new Date( new Date(endDate) - new Date(startDate) ).getMonth();
return endDate >= startDate ? diff : -diff;
}
(diff.getFullYear() - 1970) * 12
- person Datz; 20.07.2021
Посмотрите, что я использую:
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;
}
Он также считает дни и переводит их в месяцы.
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
Любое значение возвращается вместе с его абсолютным значением.
function differenceInMonths(firstDate, secondDate) {
if (firstDate > secondDate) [firstDate, secondDate] = [secondDate, firstDate];
let diffMonths = (secondDate.getFullYear() - firstDate.getFullYear()) * 12;
diffMonths -= firstDate.getMonth();
diffMonths += secondDate.getMonth();
return diffMonths;
}
firstDate
и secondDate
в параметры вашей функции.
- person Calculuswhiz; 09.11.2020
Мне нравится не изобретать колесо, делайте это просто (я имею в виду не заботиться о количестве дней в месяцах, високосном году и т. Д.) И использую date-fns
lib, поэтому
npm install -s date-fns
а также
const differenceInMonths = require('date-fns/differenceInMonths')
;(() => {
console.log(differenceInMonths(new Date(`2015-12-01`), new Date(`2013-12-01`)))
console.log(differenceInMonths(new Date(1582261140000), new Date(`2014-12-01`)))
console.log(differenceInMonths(new Date(1582261140000), new Date(1573621200000)))
})()
Один из подходов - написать простую веб-службу Java (REST / JSON), использующую библиотеку JODA.
http://joda-time.sourceforge.net/faq.html#datediff
чтобы вычислить разницу между двумя датами и вызвать эту службу из javascript.
Предполагается, что ваша серверная часть находится на Java.