Разница в месяцах между двумя датами в JavaScript
Как бы я вычислил разницу для двух объектов Date() в JavaScript, при этом возвращая только количество месяцев в разнице?
Любая помощь будет отличной:)
31 ответ
Определение "количество месяцев в разнице" подлежит большой интерпретации.:-)
Вы можете получить год, месяц и день месяца из объекта даты в JavaScript. В зависимости от того, какую информацию вы ищете, вы можете использовать ее, чтобы выяснить, сколько месяцев проходит между двумя моментами времени.
Например, не по назначению это позволяет узнать, сколько полных месяцев лежит между двумя датами, не считая неполных месяцев (например, исключая месяц, в котором находится каждая дата):
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
(Обратите внимание, что значения месяца в JavaScript начинаются с 0 = января.)
Включение дробных месяцев в вышеприведенное намного сложнее, потому что три дня в типичном феврале - это большая доля этого месяца (~10,714%), чем три дня в августе (~9,677%), и, конечно, даже февраль является движущейся целью в зависимости от того, високосный ли это год.
Есть также некоторые библиотеки даты и времени, доступные для JavaScript, которые, вероятно, облегчают подобные вещи.
return DisplayTo.getMonth() - DisplayFrom.getMonth()
+ (12 * (DisplayTo.getFullYear() - DisplayFrom.getFullYear()));
Вот функция, которая точно обеспечивает количество месяцев между двумя датами.
Поведение по умолчанию учитывает только целые месяцы, например, 3 месяца и 1 день приведет к разнице в 3 месяца. Вы можете предотвратить это, установив roundUpFractionalMonths
парам как true
Таким образом, разница в 3 месяца и 1 день будет возвращена как 4 месяца.
Принятый ответ выше (ответ TJ Crowder) не точен, иногда он возвращает неправильные значения.
Например, 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);
};
Иногда вы можете захотеть получить только количество месяцев между двумя датами, полностью игнорируя часть дня. Так, например, если у вас было две даты - 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.Если вы хотите указать количество месяцев между двумя датами, исключая месяц1 и месяц2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2. Если вы хотите включить любой из месяцев
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);
3. Если вы хотите включить оба месяца
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
Если вам нужно сосчитать полные месяцы, независимо от того, был ли месяц 28, 29, 30 или 31 день. Ниже должно работать.
var months = to.getMonth() - from.getMonth()
+ (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
months--;
}
return months;
Это расширенная версия ответа /questions/9940244/raznitsa-v-mesyatsah-mezhdu-dvumya-datami-v-javascript/9940270#9940270 но исправляет случай, в котором он рассчитывает 1 месяц для случая с 31 января по 1 февраля (1 день).
Это будет охватывать следующее;
- 1 января - 31 января ---> 30 дней ---> приведет к 0 (логично, так как это не полный месяц)
- С 1 февраля по 1 марта ---> 28 или 29 дней ---> приведет к 1 (логично, так как это полный месяц)
- С 15 февраля по 15 марта ---> 28 или 29 дней ---> будет 1 (логично с прошедшего месяца)
- 31 января - 1 февраля ---> 1 день ---> приведет к 0 (очевидно, но упомянутый ответ в сообщении приводит к 1 месяцу)
Вы также можете рассмотреть это решение, это function
возвращает разницу месяцев в целых числах или числах
Передача даты начала как первого или последнего param
, отказоустойчив. Это означает, что функция все равно будет возвращать то же значение.
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);
Разница в месяцах между двумя датами в 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;
}
Рассмотрите каждую дату в месяцах, затем вычтите, чтобы найти разницу.
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());
Это даст вам разницу месяцев между двумя датами, игнорируя дни.
Чтобы расширить ответ @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 difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
Например:
дата1: 24.09.2015 (24 сентября 2015 г.)
дата2: 11.09.2015 (9 ноября 2015 г.)
разница: 2,5 месяца
Есть два подхода: математический и быстрый, но подверженный капризам в календаре, или итеративный и медленный, но он обрабатывает все странности (или, по крайней мере, делегаты обрабатывают их в хорошо проверенной библиотеке).
Если вы выполняете итерацию по календарю, увеличиваете дату начала на один месяц и смотрите, передаем ли мы дату окончания. Это делегирует обработку аномалий встроенным классам 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;
}
Количество месяцев, когда день и время не имеют значения
В данном случае меня не интересуют полные месяцы, неполные месяцы, длина месяца и т. Д. Мне просто нужно знать количество месяцев. Соответствующий случай из реальной жизни - это когда отчет должен представляться каждый месяц, и мне нужно знать, сколько отчетов должно быть.
Пример:
- Январь = 1 месяц
- Январь - февраль = 2 месяца
- Ноябрь - январь = 3 месяца
Это подробный пример кода, показывающий, куда идут числа.
Возьмем 2 отметки времени, которые должны дать 4 месяца.
- Метка времени 13 ноября 2019 г.: 1573621200000
- Отметка времени 20 февраля 2020 года: 1582261140000
Может немного отличаться от вашего часового пояса / времени. День, минуты и секунды не имеют значения и могут быть включены в метку времени, но мы проигнорируем их при наших фактических расчетах.
Шаг 1. Преобразуйте метку времени в дату JavaScript
let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);
Шаг 2: получите целочисленные значения месяцев / лет
let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();
Это дает нам
- Стартовый месяц: 11
- Год начала: 2019
- Конечный месяц: 2
- Год окончания: 2020
Шаг 3: Добавить (12 * (endYear - startYear)) + 1
до последнего месяца.
- Таким образом, наш начальный месяц остается в 11
- Таким образом, наш конечный месяц равен 15.
2 + (12 * (2020 - 2019)) + 1 = 15
Шаг 4: вычтите месяцы
15 - 11 = 4
; получаем результат за 4 месяца.
29 месяцев Пример Пример
С ноября 2019 года по март 2022 года - 29 месяцев. Если вы поместите их в электронную таблицу Excel, вы увидите 29 строк.
- Наш начальный месяц 11
- Наш последний месяц - 40
3 + (12 * (2022-2019)) + 1
40 - 11 = 29
Это должно работать нормально:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
Это самое простое решение, которое я смог найти. Это напрямую вернет количество месяцев. Хотя всегда дает абсолютное значение.
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;
}
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;
}
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;
}
Ниже логика будет получать разницу в месяцах
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
Следующий код возвращает полные месяцы между двумя датами, принимая во внимание также количество дней неполных месяцев.
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 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);
}
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;
}
Любое значение возвращается вместе с его абсолютным значением.
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;
}
Он также считает дни и конвертирует их в месяцы.
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 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;
}
Следующий фрагмент кода помог мне найти месяцы между двумя датами.
Найти количество месяцев между двумя датами JS
Месяцы Между двумя датами JS
Фрагмент кода
function diff_months_count(startDate, endDate) {
var months;
var d1 = new Date(startDate);
var d2 = new Date(endDate);
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
#Вот хороший фрагмент кода, который я написал для получения количества дней и месяцев от заданных дат
[1]: ссылка jsfiddle
Для процветания,
С Moment.js вы можете достичь этого, выполнив:
const monthsLeft = moment(endDate).diff(moment(startDate), 'month');
Мне нравится не изобретать колесо, делайте это просто (я имею в виду не заботиться о количестве дней в месяцах, високосном году и т. Д.) И используйте
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)))
})()
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));