Функция Javascript, чтобы получить разницу между двумя датами [duplicate]

Реальный ответ: Нет, это невозможно.

Хорошо, я только что подумал о пути. Наложите свою страницу на div, который охватывает весь документ. Внутри этого, создайте (скажем) 2 000 x 2000 & lt; a & gt; элементов (так что псевдокласс класса : hover будет работать в IE 6, см.), Каждый 1 пиксель в размере. Создайте правило CSS : hover для тех элементов & lt; a & gt; , которые изменяют свойство (скажем, font-family ). В вашем обработчике нагрузки проведите цикл через каждый из 4 миллионов элементов & lt; a & gt; , проверив currentStyle / getComputedStyle () , пока не найдете тот с шрифтом наведения. Экстраполируйте назад из этого элемента, чтобы получить координаты внутри документа.

N.B. НЕ ДЕЛАЙТЕ ЭТО.

93
задан S.L. Barth 20 July 2012 в 16:06
поделиться

21 ответ

Определение «количество месяцев в разнице» подлежит многому толкованию. : -)

Вы можете получить год, месяц и день месяца из объекта даты 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, которые, вероятно, делают это проще .

176
ответ дан T.J. Crowder 16 August 2018 в 11:44
поделиться
  • 1
    @ T.J .: +1 для вашей функции, это хороший пример того, где OP может начаться, но я думаю, что по крайней мере "полный" месяц должен учитываться (например, с 1 февраля по 31 марта :-) – Andy E 29 March 2010 в 09:19
  • 2
    [geek_mode] Расширение по григорианской версии: JavaScript использует только экстраполированный григорианский календарь и игнорирует секунды прыжка. Это означает, среди прочего, что любая дата до 15 октября 1582 года будет ошибочной при запросе года, месяца или дня (например, когда она превращается в строку), поскольку JavaScript не обрабатывает настройку (за день до 15 октября 1582 года было 4 октября 1582 года, в этом году не было от 5-го по 14-й год). [/ geek_mode] – T.J. Crowder 29 March 2010 в 09:50
  • 3
    monthDiff (новая дата (), новая дата ()) return -1, которая действительно удивляет меня :-( – Petr 18 January 2013 в 17:03
  • 4
    Вы уверены, что +1 в «месяцах» = d1.getMonth () + 1; & quot; необходимо? При этом +1 разница между 2013-01-17 и 2013-02-16 равна 0. – Briganti 16 January 2014 в 11:00
  • 5
    Мне пришлось удалить +1 в months -= d1.getMonth() + 1;, чтобы точно определить количество месяцев между двумя датами, но большое спасибо за идеальную отправную точку! – bryan 20 August 2014 в 00:19

ниже логика будет извлекать разницу в месяцах

(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
1
ответ дан Anoop Isaac 16 August 2018 в 11:44
поделиться

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

0
ответ дан Aris Dela Rea 16 August 2018 в 11:44
поделиться

Чтобы расширить ответ на @ T.J., если вы ищете простые месяцы, а не полные календарные месяцы, вы можете просто проверить, больше ли дата d2 больше или равна, чем d1. То есть, если d2 позже в месяце, чем d1 в месяце, то еще месяц. Таким образом, вы должны просто сделать это:

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), но это более точно и всего лишь пару строк кода.

4
ответ дан calvin 16 August 2018 в 11:44
поделиться

Если вам нужно засчитывать полные месяцы, независимо от того, в течение месяца 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 день).

Это будет охватывать следующее:

  • с 1 января по 31 января ---> 30 дней ---> будет результат равен 0 (логический, поскольку он не полный месяц)
  • 1 февраля - 1 марта ---> 28 или 29 дней ---> приведет к 1 (логично, так как это полный месяц)
  • с 15 февраля по 15 марта ---> 28 или 29 дней ---> приведет к 1 (логический с месяца)
  • 31 января - 1 февраля --- > 1 день ---> приведет к 0 (очевидно, но упомянутый ответ в результатах статьи за 1 месяц)
21
ответ дан Community 16 August 2018 в 11:44
поделиться
  • 1
    Вот что я думал, что пришел сюда для проверки, и это единственный ответ, который имеет для меня смысл – Andreas 7 September 2014 в 07:19
  • 2
    Это не работает при сравнении двух месяцев, когда месяц короче. Например, с 31 марта по 30 апреля. Это all апреля, поэтому ответ должен быть «1.». – Michael Blackburn 27 February 2015 в 19:36

Следующий код возвращает полные месяцы между двумя датами, принимая во внимание также количество дней неполных месяцев.

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
ответ дан Delorean 16 August 2018 в 11:44
поделиться

Посмотрите, что я использую:

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
ответ дан Fayez Zalloum 16 August 2018 в 11:44
поделиться

Вот функция, которая точно определяет количество месяцев между двумя датами. Поведение по умолчанию рассчитано только на целые месяцы, например. 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);
};
19
ответ дан Francisc 16 August 2018 в 11:44
поделиться
  • 1
    Серьезно, хотя, кто проголосовал за это? Он прав, принятый ответ просто ... неправильный. – Michael Blackburn 6 August 2015 в 18:27
  • 2
    Это лучший ответ. – Kalyan Chavali 21 September 2016 в 06:23
  • 3
    Это неправильно, если датировать date1 22-го января, а date2 - 22-го августа. Затем он возвращает 7, что, очевидно, должно быть 8? – Nicolai Harbo 22 August 2017 в 11:09

Он также учитывает дни и конвертирует их в месяцы.

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
ответ дан Gaurav Jain 16 August 2018 в 11:44
поделиться
  • 1
    Можете ли вы добавить более подробное объяснение того, как это работает? Это сделало бы ответ лучше – serge1peshcoff 8 December 2017 в 13:24
  • 2
    Есть ли предположение, что у месяцев есть 30 дней? – Ben Taliadoros 13 July 2018 в 12:33

Здесь вы идете другим путем с меньшим циклом:

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
ответ дан ggomeze 16 August 2018 в 11:44
поделиться
  • 1
    остерегайтесь этого метода: он (довольно очевидно, когда вы внимательно его читаете) мутирует первую дату, которая возвращается обратно вызывающему (поскольку даты передаются по ссылке). – Andiih 15 July 2016 в 13:47

Рассматривайте каждую дату по месяцам, а затем вычитайте, чтобы найти разницу.

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

Это даст вам разницу между месяцами между двумя датами, игнорируя дни.

5
ответ дан internet-nico 16 August 2018 в 11:44
поделиться

Я знаю, что это действительно поздно, но выставлять его в любом случае на всякий случай, если это помогает другим. Вот функция, с которой я столкнулся, которая, похоже, хорошо разбирается в различиях между месяцами между двумя датами. Это, по общему признанию, намного бесполезнее, чем у мистера Коудера, но дает более точные результаты, пройдя через объект даты. Это в 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;
    }
5
ответ дан James 16 August 2018 в 11:44
поделиться
  • 1
    Публикация действительного javascript будет хорошим началом. – RobG 23 September 2015 в 14:14
  • 2
    В большинстве случаев это наиболее вероятный подход . В нашем календаре так много исключений и капризов, наилучшим подходом является делегирование их обработки в хорошо протестированную библиотеку, например Date (). Для большинства (коротких) интервалов это вернет тот же самый ответ, что и рассчитанные подходы, но когда вы имеете дело с длительными промежутками времени (включая високосные годы, високосные годы - это нерентабельные годы, секунды и т. д.), вы, скорее всего, столкнетесь с исключением, когда вычитание месяцев и добавление лет будет неправильным. См. Мой ответ за исключения, когда расчет будет лучшим. – Michael Blackburn 16 November 2016 в 16:39

Существует два подхода: математический & amp; быстрые, но подверженные капризам в календаре, или итеративные и amp; медленный, но обрабатывает все странности (или, по крайней мере, делегаты обрабатывают их в хорошо протестированной библиотеке).

Если вы перебираете календарь, увеличивая начальную дату на один месяц & amp; если мы пройдем дату окончания. Это делегирует обработку аномалий встроенным классам Date (), но может быть медленным IF , что вы делаете это для большого количества дат. Ответ Джеймса использует такой подход. Насколько мне не нравится эта идея, я думаю, что это «самый безопасный» подход, и если вы делаете только один расчет, разница в производительности действительно незначительна. Мы склонны пытаться переопределить задачи, которые будут выполняться только один раз.

Теперь, если вы вычисляете эту функцию в наборе данных, вы, вероятно, не хотите запускать эту функцию в каждой строке ( или не дай бог, несколько раз за запись). В этом случае вы можете использовать почти любой из других ответов здесь , кроме принятого ответа, который просто неверен (разница между new Date() и new Date() равна -1)?

Вот мой удар по математическому и быстрому подходу, который учитывает разные месяцы и високосные годы. Вы действительно должны использовать только такую ​​функцию, если вы будете применять ее к набору данных (выполняя этот расчет над & amp; over). Если вам просто нужно сделать это один раз, используйте итеративный подход Джеймса выше, поскольку вы делегируете обработку всех (многих) исключений для объекта 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;
}
4
ответ дан Michael Blackburn 16 August 2018 в 11:44
поделиться

Иногда вы можете получить только количество месяцев между двумя датами, полностью игнорирующими дневную часть. Например, если у вас были две даты - 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;
25
ответ дан OrangeDog 16 August 2018 в 11:44
поделиться
  • 1
    Хороший! Работала идеально для меня. – user 23 August 2013 в 05:20
  • 2
    Для последнего я порекомендую: numberOfMonths=(year2-year1)*12+(month2-month1)+1;, который делает то же самое, но более семантически правильно для меня – Natim 5 September 2013 в 18:09
  • 3
    Да, приятный и элегантный подход. – Mikayil Abdullayev 6 September 2013 в 05:24
  • 4
    Это был лучший ответ. Благодаря! – marienke 29 May 2017 в 14:47
  • 5
    Это просто и чисто. Спасибо, что написал отличный код. – zeros-and-ones 23 February 2018 в 00:08

Один из подходов заключался бы в написании простой веб-службы Java (REST / JSON), которая использует библиотеку JODA

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

, чтобы вычислить разницу между двумя датами и вызвать эту службу из javascript.

Это предполагает, что ваш конец на Java.

-6
ответ дан Ravi Chinoy 16 August 2018 в 11:44
поделиться

Вычисление разницы между двумя датами включает в себя долю месяца (дней).


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 г.) разница: 2.5 (месяцы)

1
ответ дан Shneor 16 August 2018 в 11:44
поделиться
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
ответ дан shoaib fazlani 16 August 2018 в 11:44
поделиться
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
ответ дан Tariq 16 August 2018 в 11:44
поделиться

Это должно работать нормально:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months += d2.getMonth() - d1.getMonth();
    return months;
}
2
ответ дан Thiago Jordan 16 August 2018 в 11:44
поделиться
return DisplayTo.getMonth() - DisplayFrom.getMonth()
       + (12 * (DisplayTo.getFullYear() - DisplayFrom.getFullYear()));
51
ответ дан Tom Gullen 16 August 2018 в 11:44
поделиться
  • 1
    Это самый короткий и простой способ понять код, который я видел до сих пор! – Omar 18 September 2012 в 01:26
  • 2
    Ничего сложного в этом нет, кроме того, что каждый месяц начинается. 31/03/2011 - & gt; 01/05/2011 будет составлять два месяца, а также 01/03/2011 - & gt; 31/05/2011, но это должно быть три, чтобы быть точным. – Natim 5 September 2013 в 18:05
  • 3
    Этот ответ более полный: stackoverflow.com/a/15158873/186202 – Natim 5 September 2013 в 18:07
  • 4
    Если вы просто хотите узнать количество месяцев, то это PERFECT !!!!! Если вам нужно знать, основываясь на днях в месяце, это не сработает. – OSDM 5 October 2015 в 06:56
  • 5
    Начните с того, что 2018/01 и 2017/01 составляют 12 месяцев. Отправляйтесь оттуда назад. Этот ответ получает. ;) – Gerard ONeill 21 June 2018 в 23:20

Разница в месяцах между двумя датами в 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())
7
ответ дан user 16 August 2018 в 11:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: