Ответ 1
Вам нужно получить бизнес-правила для добавления месяцев. Простое решение:
function addMonths(dateObj, num) {
return dateObj.setMonth(dateObj.getMonth() + num);
}
Однако это изменится с 31 июля по 31 сентября, которое будет преобразовано в 1 октября. Кроме того, 31 января плюс 1 месяц - 31 февраля, который будет конвертирован в 2 или 3 марта в зависимости от того, является ли он високосным годом или нет.
Вы можете ожидать, что первым будет 30 сентября, а вторым будет 28 или 29 февраля (в зависимости от того, будет ли это високосный год или нет).
Итак, если вы хотите увидеть "конец месяца", вам нужно сделать что-то вроде:
function addMonths(dateObj, num) {
var currentMonth = dateObj.getMonth() + dateObj.getFullYear() * 12;
dateObj.setMonth(dateObj.getMonth() + num);
var diff = dateObj.getMonth() + dateObj.getFullYear() * 12 - currentMonth;
// If don't get the right number, set date to
// last day of previous month
if (diff != num) {
dateObj.setDate(0);
}
return dateObj;
}
Но проконсультируйтесь с тем, кто отвечает за бизнес-правила, что они хотят.
Изменить
Это хорошо работает, но в ответ на комментарий McShaman здесь представлена версия с более простой проверкой для перемотки месяца:
function addMonths(date, months) {
var d = date.getDate();
date.setMonth(date.getMonth() + +months);
if (date.getDate() != d) {
date.setDate(0);
}
return date;
}
// Add 12 months to 29 Feb 2016 -> 28 Feb 2017
console.log(addMonths(new Date(2016,1,29),12).toString());
// Subtract 1 month from 1 Jan 2017 -> 1 Dec 2016
console.log(addMonths(new Date(2017,0,1),-1).toString());
// Subtract 2 months from 31 Jan 2017 -> 30 Nov 2016
console.log(addMonths(new Date(2017,0,31),-2).toString());
// Add 2 months to 31 Dec 2016 -> 28 Feb 2017
console.log(addMonths(new Date(2016,11,31),2).toString());