Функция JavaScript для добавления X месяцев к дате - PullRequest
179 голосов
/ 25 апреля 2010

Я ищу самый простой и чистый способ добавить X месяцев к дате JavaScript.

Я бы не стал справляться с переносом года или мне пришлось бы написать собственную функцию .

Есть ли что-то встроенное, что может сделать это?

Ответы [ 17 ]

244 голосов
/ 25 апреля 2010

Я думаю, что это должно сделать это:

var x = 12; //or whatever offset
var CurrentDate = new Date();
console.log("Current date:", CurrentDate);
CurrentDate.setMonth(CurrentDate.getMonth() + x);
console.log("Date after " + x + " months:", CurrentDate);

Я считаю, что он должен автоматически обрабатывать приращение к соответствующему году и переход к соответствующему месяцу.

52 голосов
/ 04 мая 2015

Я использую moment.js библиотеку для манипуляции с датой и временем . Пример кода для добавления одного месяца:

var startDate = new Date(...);
var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format
endDateMoment.add(1, 'months');
22 голосов
/ 09 февраля 2016

Эта функция обрабатывает крайние случаи и работает быстро:

function addMonthsUTC (date, count) {
  if (date && count) {
    var m, d = (date = new Date(+date)).getUTCDate()

    date.setUTCMonth(date.getUTCMonth() + count, 1)
    m = date.getUTCMonth()
    date.setUTCDate(d)
    if (date.getUTCMonth() !== m) date.setUTCDate(0)
  }
  return date
}

тест:

> d = new Date('2016-01-31T00:00:00Z');
Sat Jan 30 2016 18:00:00 GMT-0600 (CST)
> d = addMonthsUTC(d, 1);
Sun Feb 28 2016 18:00:00 GMT-0600 (CST)
> d = addMonthsUTC(d, 1);
Mon Mar 28 2016 18:00:00 GMT-0600 (CST)
> d.toISOString()
"2016-03-29T00:00:00.000Z"

Обновление для не-UTC дат: (от A.Hatchkins)

function addMonths (date, count) {
  if (date && count) {
    var m, d = (date = new Date(+date)).getDate()

    date.setMonth(date.getMonth() + count, 1)
    m = date.getMonth()
    date.setDate(d)
    if (date.getMonth() !== m) date.setDate(0)
  }
  return date
}

тест:

> d = new Date(2016,0,31);
Sun Jan 31 2016 00:00:00 GMT-0600 (CST)
> d = addMonths(d, 1);
Mon Feb 29 2016 00:00:00 GMT-0600 (CST)
> d = addMonths(d, 1);
Tue Mar 29 2016 00:00:00 GMT-0600 (CST)
> d.toISOString()
"2016-03-29T06:00:00.000Z"
13 голосов
/ 03 апреля 2016

Учитывая, что ни один из этих ответов не будет учитывать текущий год, когда меняется месяц, вы можете найти ответ, который я сделал ниже:

Метод:

Date.prototype.addMonths = function (m) {
    var d = new Date(this);
    var years = Math.floor(m / 12);
    var months = m - (years * 12);
    if (years) d.setFullYear(d.getFullYear() + years);
    if (months) d.setMonth(d.getMonth() + months);
    return d;
}

Использование:

return new Date().addMonths(2);
8 голосов
/ 31 марта 2016

Взяты из @ bmpsini и @ Jazaret ответов, но не расширяют прототипы: использование простых функций ( Почему расширение собственных объектов - плохая практика? ):

function isLeapYear(year) { 
    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); 
}

function getDaysInMonth(year, month) {
    return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}

function addMonths(date, value) {
    var d = new Date(date),
        n = date.getDate();
    d.setDate(1);
    d.setMonth(d.getMonth() + value);
    d.setDate(Math.min(n, getDaysInMonth(d.getFullYear(), d.getMonth())));
    return d;
}

Используйте это:

var nextMonth = addMonths(new Date(), 1);
4 голосов
/ 03 октября 2015

Простое решение: 2678400000 - это 31 день в миллисекундах

var oneMonthFromNow = new Date((+new Date) + 2678400000);

Обновление:

Используйте эти данные для построения нашей собственной функции:

  • 2678400000 - 31 день
  • 2592000000 - 30 дней
  • 2505600000 - 29 дней
  • 2419200000 - 28 дней
2 голосов
/ 30 мая 2014

Просто добавить к принятому ответу и комментариям.

var x = 12; //or whatever offset
var CurrentDate = new Date();

//For the very rare cases like the end of a month
//eg. May 30th - 3 months will give you March instead of February
var date = CurrentDate.getDate();
CurrentDate.setDate(1);
CurrentDate.setMonth(CurrentDate.getMonth()+X);
CurrentDate.setDate(date);
2 голосов
/ 25 апреля 2010
d = new Date();

alert(d.getMonth()+1);

Месяцы имеют индекс на основе 0, он должен выдавать предупреждение (4), которое равно 5 (май);

2 голосов
/ 27 октября 2014

Поскольку большинство ответов выделены, мы можем использовать метод setMonth () вместе с методом getMonth () , чтобы добавить определенное количество месяцев к определенной дате.

Пример: (как упомянуто @ChadD в своем ответе.)

var x = 12; //or whatever offset 
var CurrentDate = new Date();
CurrentDate.setMonth(CurrentDate.getMonth() + x);

Но мы должны осторожно использовать это решение, так как у нас возникнут проблемы с крайними случаями.

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

https://stackoverflow.com/a/13633692/3668866

2 голосов
/ 20 августа 2015

Из ответов, приведенных выше, единственная, которая обрабатывает крайние случаи (bmpasini из библиотеки datejs), имеет проблему:

var date = new Date("03/31/2015");
var newDate = date.addMonths(1);
console.log(newDate);
// VM223:4 Thu Apr 30 2015 00:00:00 GMT+0200 (CEST)

хорошо, но:

newDate.toISOString()
//"2015-04-29T22:00:00.000Z"

хуже:

var date = new Date("01/01/2015");
var newDate = date.addMonths(3);
console.log(newDate);
//VM208:4 Wed Apr 01 2015 00:00:00 GMT+0200 (CEST)
newDate.toISOString()
//"2015-03-31T22:00:00.000Z"

Это происходит из-за того, что время не установлено, и поэтому возвращается к 00:00:00, что может привести к сбою предыдущего дня из-за изменений часового пояса или экономии времени или чего-то еще ...

Вот мое предлагаемое решение, которое не имеет этой проблемы, и, я думаю, более элегантно, поскольку оно не опирается на жестко заданные значения.

/**
* @param isoDate {string} in ISO 8601 format e.g. 2015-12-31
* @param numberMonths {number} e.g. 1, 2, 3...
* @returns {string} in ISO 8601 format e.g. 2015-12-31
*/
function addMonths (isoDate, numberMonths) {
    var dateObject = new Date(isoDate),
        day = dateObject.getDate(); // returns day of the month number

    // avoid date calculation errors
    dateObject.setHours(20);

    // add months and set date to last day of the correct month
    dateObject.setMonth(dateObject.getMonth() + numberMonths + 1, 0);

    // set day number to min of either the original one or last day of month
    dateObject.setDate(Math.min(day, dateObject.getDate()));

    return dateObject.toISOString().split('T')[0];
};

Устройство успешно протестировано с:

function assertEqual(a,b) {
    return a === b;
}
console.log(
    assertEqual(addMonths('2015-01-01', 1), '2015-02-01'),
    assertEqual(addMonths('2015-01-01', 2), '2015-03-01'),
    assertEqual(addMonths('2015-01-01', 3), '2015-04-01'),
    assertEqual(addMonths('2015-01-01', 4), '2015-05-01'),
    assertEqual(addMonths('2015-01-15', 1), '2015-02-15'),
    assertEqual(addMonths('2015-01-31', 1), '2015-02-28'),
    assertEqual(addMonths('2016-01-31', 1), '2016-02-29'),
    assertEqual(addMonths('2015-01-01', 11), '2015-12-01'),
    assertEqual(addMonths('2015-01-01', 12), '2016-01-01'),
    assertEqual(addMonths('2015-01-01', 24), '2017-01-01'),
    assertEqual(addMonths('2015-02-28', 12), '2016-02-28'),
    assertEqual(addMonths('2015-03-01', 12), '2016-03-01'),
    assertEqual(addMonths('2016-02-29', 12), '2017-02-28')
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...