Функция JavaScript для добавления X месяцев к дате
Я ищу самый простой и чистый способ добавить X месяцев к дате JavaScript.
Я бы предпочел не заниматься переносом года или писать свою собственную функцию.
Есть ли что-то встроенное, что может сделать это?
24 ответа
Я думаю, что это должно сделать это:
var x = 12; //or whatever offset
var CurrentDate = new Date();
CurrentDate.setMonth(CurrentDate.getMonth() + x);
Я считаю, что он должен автоматически обрабатывать приращение к соответствующему году и переход к соответствующему месяцу.
попытайся
Я использую библиотеку 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');
Эта функция обрабатывает крайние случаи и работает быстро:
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: (А.Хаткинс)
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"
Взяты из ответов @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);
Учитывая, что ни один из этих ответов не будет учитывать текущий год, когда меняется месяц, вы можете найти ответ, который я сделал ниже:
Метод:
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);
Из приведенных выше ответов единственная проблема, которая обрабатывает крайние случаи (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')
);
Простое решение: 2678400000
31 день в миллисекундах
var oneMonthFromNow = new Date((+new Date) + 2678400000);
Обновить:
Используйте эти данные для построения нашей собственной функции:
2678400000
- 31 день2592000000
- 30 дней2505600000
- 29 дней2419200000
- 28 дней
d = new Date();
alert(d.getMonth()+1);
Месяцы имеют индекс, основанный на 0, он должен предупреждать (4), который равен 5 (май);
Как отмечалось в большинстве ответов, мы могли бы использовать метод setMonth() вместе с методом getMonth(), чтобы добавить определенное количество месяцев к определенной дате.
Пример: (как упомянуто @ChadD в своем ответе.)
var x = 12; //or whatever offset var CurrentDate = new Date(); CurrentDate.setMonth(CurrentDate.getMonth() + x);
Но мы должны осторожно использовать это решение, так как у нас возникнут проблемы с крайними случаями.
Для обработки крайних случаев полезен ответ, который приведен в следующей ссылке.
/questions/10013772/kak-dobavit-mesyatsyi-k-date-v-javascript/10013788#10013788
Я написал это альтернативное решение, которое прекрасно работает для меня. Это полезно, когда вы хотите рассчитать окончание контракта. Например, начало =2016-01-15, месяцы =6, конец =2016-7-14 (т.е. последний день - 1):
<script>
function daysInMonth(year, month)
{
return new Date(year, month + 1, 0).getDate();
}
function addMonths(date, months)
{
var target_month = date.getMonth() + months;
year = date.getFullYear() + parseInt(target_month / 12);
month = target_month % 12;
day = date.getDate();
last_day = daysInMonth(year, month);
if (day > last_day)
{
day = last_day;
}
new_date = new Date(year, month, day);
return new_date;
}
var endDate = addMonths(startDate, months);
</script>
Примеры:
addMonths(new Date("2016-01-01"), 1); // 2016-01-31
addMonths(new Date("2016-01-01"), 2); // 2016-02-29 (2016 is a leap year)
addMonths(new Date("2016-01-01"), 13); // 2017-01-31
addMonths(new Date("2016-01-01"), 14); // 2017-02-28
Я немного изменил принятый ответ, чтобы сохранить исходную дату нетронутой, как я думаю, это должно быть в такой функции.
function addMonths(date, months) {
let newDate = new Date(date);
var day = newDate.getDate();
newDate.setMonth(newDate.getMonth() + +months);
if (newDate.getDate() != day)
newDate.setDate(0);
return newDate;
}
Просто чтобы добавить к принятому ответу и комментариям.
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);
Это работает для всех крайних случаев. Странный расчет для newMonth обрабатывает отрицательные значения месяцев. Если новый месяц не совпадает с ожидаемым (например, 31 февраля), он установит день месяца на 0, что означает "конец предыдущего месяца":
function dateAddCalendarMonths(date, months) {
monthSum = date.getMonth() + months;
newMonth = (12 + (monthSum % 12)) % 12;
newYear = date.getFullYear() + Math.floor(monthSum / 12);
newDate = new Date(newYear, newMonth, date.getDate());
return (newDate.getMonth() != newMonth)
? new Date(newDate.setDate(0))
: newDate;
}
Ниже приведен пример расчета будущей даты на основе ввода даты (membersssignup_date) + добавленных месяцев (membershipsmonths) через поля формы.
Поле membershipsmonths имеет значение по умолчанию 0
Триггерная ссылка (может быть событием onchange, прикрепленным к полю членства):
<a href="#" onclick="calculateMshipExp()"; return false;">Calculate Expiry Date</a>
function calculateMshipExp() {
var calcval = null;
var start_date = document.getElementById("membershipssignup_date").value;
var term = document.getElementById("membershipsmonths").value; // Is text value
var set_start = start_date.split('/');
var day = set_start[0];
var month = (set_start[1] - 1); // January is 0 so August (8th month) is 7
var year = set_start[2];
var datetime = new Date(year, month, day);
var newmonth = (month + parseInt(term)); // Must convert term to integer
var newdate = datetime.setMonth(newmonth);
newdate = new Date(newdate);
//alert(newdate);
day = newdate.getDate();
month = newdate.getMonth() + 1;
year = newdate.getFullYear();
// This is British date format. See below for US.
calcval = (((day <= 9) ? "0" + day : day) + "/" + ((month <= 9) ? "0" + month : month) + "/" + year);
// mm/dd/yyyy
calcval = (((month <= 9) ? "0" + month : month) + "/" + ((day <= 9) ? "0" + day : day) + "/" + year);
// Displays the new date in a <span id="memexp">[Date]</span> // Note: Must contain a value to replace eg. [Date]
document.getElementById("memexp").firstChild.data = calcval;
// Stores the new date in a <input type="hidden" id="membershipsexpiry_date" value="" name="membershipsexpiry_date"> for submission to database table
document.getElementById("membershipsexpiry_date").value = calcval;
}
Ищете что-то в машинописном тексте?
export const addMonths = (inputDate: Date | string, monthsToAdd: number): Date => {
const date = new Date(inputDate);
if (!monthsToAdd) {
return date;
}
const dayOfMonth = date.getDate();
const endOfDesiredMonth = new Date(date.getTime());
endOfDesiredMonth.setMonth(date.getMonth() + monthsToAdd + 1, 0);
const daysInMonth = endOfDesiredMonth.getDate();
if (dayOfMonth >= daysInMonth) {
return endOfDesiredMonth;
} else {
date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);
return date;
}
}
Легкий, самый простой
function addMonths(date, months) {date.setMonth(date.getMonth() + months); return date;};
Используйте его как
alert(new Date().toLocaleString()); //will say today
alert(addMonths(new Date(),12).toLocaleString()); //will say next year, same day and month
Простой ответ может быть:
function addMonthsToDate(date, numMonths){
// Add months
date.setMonth(date.getMonth() + numMonths);
// Zero the time component
date.setHours(0, 0, 0, 0);
return date;
}
Это можно назвать - добавить два месяца:
console.log(addMonthsToDate(new Date(),2));
Как показывают многие из сложных, безобразных ответов, "Даты и времена" могут стать кошмаром для программистов, использующих любой язык. Мой подход заключается в том, чтобы преобразовать даты и значения "delta t" в Epoch Time (в мс), выполнить любую арифметику, а затем преобразовать обратно в "человеческое время".
// Given a number of days, return a Date object
// that many days in the future.
function getFutureDate( days ) {
// Convert 'days' to milliseconds
var millies = 1000 * 60 * 60 * 24 * days;
// Get the current date/time
var todaysDate = new Date();
// Get 'todaysDate' as Epoch Time, then add 'days' number of mSecs to it
var futureMillies = todaysDate.getTime() + millies;
// Use the Epoch time of the targeted future date to create
// a new Date object, and then return it.
return new Date( futureMillies );
}
// Use case: get a Date that's 60 days from now.
var twoMonthsOut = getFutureDate( 60 );
Это было написано для немного другого варианта использования, но вы должны быть в состоянии легко адаптировать его для связанных задач.
РЕДАКТИРОВАТЬ: Полный источник здесь!
Иногда полезно создать дату одним оператором, как в параметрах BIRT
Я сделал 1 месяц назад с:
new Date(new Date().setMonth(new Date().getMonth()-1));
Самое простое решение:
const todayDate = Date.now();
return new Date(todayDate + 1000 * 60 * 60 * 24 * 30* X);
where X is the number of months we want to add.
Все это кажется слишком сложным, и я предполагаю, что он вступает в дискуссию о том, что именно означает "месяц". Это значит 30 дней? Это означает с 1-го по 1-е? С последнего дня до последнего дня?
Если последнее, то если добавить месяц к 27 февраля, вы получите 27 марта, а если добавить месяц к 28 февраля, то получите 31 марта (кроме високосных годов, когда вы получите 28 марта). Затем вычитая месяц с 30 марта, вы получаете... 27 февраля? Кто знает...
Для тех, кто ищет простое решение, просто добавьте миллисекунды и все готово.
function getDatePlusDays(dt, days) {
return new Date(dt.getTime() + (days * 86400000));
}
или же
Date.prototype.addDays = function(days) {
this = new Date(this.getTime() + (days * 86400000));
};
addDateMonate : function( pDatum, pAnzahlMonate )
{
if ( pDatum === undefined )
{
return undefined;
}
if ( pAnzahlMonate === undefined )
{
return pDatum;
}
var vv = new Date();
var jahr = pDatum.getFullYear();
var monat = pDatum.getMonth() + 1;
var tag = pDatum.getDate();
var add_monate_total = Math.abs( Number( pAnzahlMonate ) );
var add_jahre = Number( Math.floor( add_monate_total / 12.0 ) );
var add_monate_rest = Number( add_monate_total - ( add_jahre * 12.0 ) );
if ( Number( pAnzahlMonate ) > 0 )
{
jahr += add_jahre;
monat += add_monate_rest;
if ( monat > 12 )
{
jahr += 1;
monat -= 12;
}
}
else if ( Number( pAnzahlMonate ) < 0 )
{
jahr -= add_jahre;
monat -= add_monate_rest;
if ( monat <= 0 )
{
jahr = jahr - 1;
monat = 12 + monat;
}
}
if ( ( Number( monat ) === 2 ) && ( Number( tag ) === 29 ) )
{
if ( ( ( Number( jahr ) % 400 ) === 0 ) || ( ( Number( jahr ) % 100 ) > 0 ) && ( ( Number( jahr ) % 4 ) === 0 ) )
{
tag = 29;
}
else
{
tag = 28;
}
}
return new Date( jahr, monat - 1, tag );
}
testAddMonate : function( pDatum , pAnzahlMonate )
{
var datum_js = fkDatum.getDateAusTTMMJJJJ( pDatum );
var ergebnis = fkDatum.addDateMonate( datum_js, pAnzahlMonate );
app.log( "addDateMonate( \"" + pDatum + "\", " + pAnzahlMonate + " ) = \"" + fkDatum.getStringAusDate( ergebnis ) + "\"" );
},
test1 : function()
{
app.testAddMonate( "15.06.2010", 10 );
app.testAddMonate( "15.06.2010", -10 );
app.testAddMonate( "15.06.2010", 37 );
app.testAddMonate( "15.06.2010", -37 );
app.testAddMonate( "15.06.2010", 1234 );
app.testAddMonate( "15.06.2010", -1234 );
app.testAddMonate( "15.06.2010", 5620 );
app.testAddMonate( "15.06.2010", -5120 );
}
Я сделал это, используя Moment Js LibraryRefs: https://momentjs.com/
startDate = new Date()
endDate = moment(startDate).add(2, "Months").format("YYYY-MM-DD")
endDate= new Date (endDate)
var a=new Date();
a.setDate(a.getDate()+5);
Как указано выше, вы можете добавить месяц к Date
функция.