X 개월을 날짜에 추가하는 JavaScript 함수


209

JavaScript 날짜에 X 개월을 추가하는 가장 쉽고 깨끗한 방법을 찾고 있습니다.

차라리 연중 롤오버를 처리 하지 않거나 내 자신의 함수작성 해야 합니다 .

이것을 할 수있는 것이 내장되어 있습니까?


4
다음과 같이 날짜의 프로토 타입 객체에 메소드를 추가하십시오 .--------------- Date.prototype.addMonth = function (n) {return new Date (this.setMonth (this.getMonth ( ) + n)); };
Moises Hidalgo

1
@ kr37, Moises Hidalgo의 답변은 목표 월에 오늘의 요일 번호가 없으면 올바르게 작동하지 않습니다. bmpasini의 답변도이 문제를 처리합니다
Alexandru Severin

여기에 대한 답변은 좋지 않지만 더 나은 답변은 JavaScript의 날짜에 월을 추가하는 것 입니다.
RobG

답변:


278

다음 함수는 JavaScript ( source ) 의 날짜에 월을 추가합니다 . 연도 롤오버 및 다양한 월 길이를 고려합니다.

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

위의 솔루션은 한 달에서 목적지 월보다 일수가 더 많은 경우에 적용됩니다. 예.

  • 2020 년 2 월 29 일에 12 개월 추가 (2021 년 2 월 28 일이어야 함)
  • 2020 년 8 월 31 일에 1 개월 추가 (2020 년 9 월 30 일이어야 함)

를 적용 할 때 월의 날짜가 변경되면 setMonth월 길이의 차이로 인해 다음 달에 오버플로 된 것입니다. 이 경우 setDate(0)이전 달의 마지막 날로 되돌아갑니다.

참고 :이 답변 의이 버전은 다른 달 길이를 정상적으로 처리하지 않은 이전 버전 (아래)을 대체합니다.

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

130
주의-대부분의 달에 31 일을 추가하는 등의 경우에는 작동하지 않습니다. 예를 들어,이 방법을 사용하는 2011 년 10 월 31 일 + 1 개월은 Javascript의 표준 Date 객체를 사용하는 2011 년 12 월 1 일입니다.
tad

6
잘 잡아라. 나는 그것을 보지 못한 것에 놀랐습니다. T-SQL select DATEADD (month, 1, '2011-10-31')는 '2011-11-30'을 산출하므로 나에게 합리적입니다. 나는 나쁜 답변으로 10 표를 얻었습니다. 멋있는. :-)
Chad

2
또한 윤년을보십시오-윤년에 2 월 29 일에 1 년을 추가하면 사용하는 언어 (일반 답변)에 따라 예측할 수없는 결과를 얻을 수 있습니다. 2012 년에 몇 시간 동안 Microsoft Azure 클라우드 플랫폼을 중단 한 것입니다
Ben Walding

15
여기에는 월말을 존중 하는 addMonths기능이 있습니다 (예 : 2012-01-31 + 1 month = 2012-02-29등).
RobG

3
매월 첫 번째 날짜를 설정하려면 다음을 추가하십시오. today.setHours (0, 0, 0, 0); today.setDate (1);
Alexey Strakh

56

날짜-시간 조작에 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');

12
자신의 건강을 위해 moment.js를 사용하십시오.
Gaʀʀʏ

3
@garry에 동의하십시오 : moment.js를 사용하십시오.
Michel

2
나는 이것이 가장 깨끗한 방법이지만, 문제는 것을 동의한다 "뭔가가 내장 이이 작업을 수행 할 수 있습니까?" 순간은 페이지 크기에 수십 Kb를 추가합니다
Evgeny

이것은 좋았다. 이것보다 훨씬 더 잘 할 수있는 다른 플러그인은 인터넷에서 찾지 못했습니다.
Eraniichan

26

이 기능은 엣지 케이스를 처리하고 빠릅니다.

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"

여기에 유일한 합리적인 답변입니다. 그러나 비 UTC 날짜에는주의를 기울여야합니다. 예기치 않은 결과가 발생할 수 있습니다 (예 : UTC 1 월 1 일 자정의 경우 1 월 31 일 + 1 개월 = 3 월 1 일)
Antony Hatchkins

1
또 다른 문제는 원래 날짜를 수정하고 수정 된 값을 반환한다는 것입니다. 날짜 프로토 타입에 추가하거나 함수의 변경된 날짜에 로컬 변수를 사용하는 것이 합리적입니까?
Antony Hatchkins

지역 변수가 의미가있는 Antony에게 감사합니다.
aMarCruz

1
"반환 날짜"줄을 제거하거나 지역 변수를 추가하는 것이 좋습니다.
Antony Hatchkins 16:19에

로컬 변수 및 분리 된 테스트를 사용하여 업데이트되었습니다.
aMarCruz

12

이 답변들 중 어느 것도 달이 바뀌는 현재 연도를 설명하지 않는다는 것을 고려할 때 아래에서 내가 처리 한 답변을 찾을 수 있습니다.

방법:

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

이 답변은 결과 월에 해당 날짜가없는 경우 월을 추가하는 것을 고려하지 않습니다 (예 : 1 월 31 일 + 1 개월 => 2 또는 3 월 3 월). 또한 날짜에 12 개월 이상을 추가하는 데 문제가 있다고 생각합니다. 13 개월을 추가 할 때 1 년 1 개월을 추가 할 필요가 없습니다. 13 개월 만 추가하면됩니다.
RobG

9

에서 촬영 @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

위의 답변에서 가장자리 사례를 처리하는 유일한 사람 (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')
);

3

대부분의 답변이 강조 표시 되었으므로 setMonth () 메소드를 getMonth () 메소드 와 함께 사용 하여 특정 날짜에 특정 개월 수를 추가 할 수 있습니다.

예 : (그의 대답에서 @ChadD가 언급 한대로)

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

그러나 에지 솔루션에 문제가 발생할 수 있으므로이 솔루션을 신중하게 사용해야합니다.

에지 사례를 처리하려면 다음 링크에 나와있는 답변이 도움이됩니다.

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


3

간단한 해결책 : 267840000031 밀리 초입니다

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

최신 정보:

이 데이터를 사용하여 자체 기능을 빌드하십시오.

  • 2678400000 -31 일
  • 2592000000 - 30 일
  • 2505600000 -29 일
  • 2419200000 -28 일

8
몇 개월은 31 일이 없습니다
Alexandru Severin

동의하지만 기능을 쉽게 조정하거나 작성할 수 있습니다
dr.dimitru

2
사람들이 찾고있는 바로 그 기능은 자동으로 몇 달 만에 며칠을 걸리는 바로 그 기능입니다.
Alexander Bird

그런 다음 @AlexanderBird는 moment.js와 같은 다른 사람이 만든 방탄 도구를 사용합니다.
dr.dimitru

2
이 답변에는 모든 시간이 24 시간 (또는 8.64e7 밀리 초) 인 일광 절약 시간제를 사용할 수 없습니다.
RobG

2
d = new Date();

alert(d.getMonth()+1);

월은 0부터 시작하는 인덱스를 가지며, alert (4)는 5 (may)입니다.


이 메소드는 <0보다 큰 12보다 큰 값을 반환 할 수 있습니다.
Patrick

2

수락 된 답변과 의견에 추가하기 만하면됩니다.

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
Date (31)를 "2 월 1 일"로 설정하면 "3 Mar"가 표시됩니다. 당신이 정말로 원하는 것입니까?
Antony Hatchkins

2

나는 나에게 잘 작동하는이 대안 솔루션을 썼다. 계약 종료를 계산할 때 유용합니다. 예를 들어 start = 2016-01-15, months = 6, end = 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;
    var year = date.getFullYear() + parseInt(target_month / 12);
    var month = target_month % 12;
    var day = date.getDate();
    var last_day = daysInMonth(year, month);
    if (day > last_day)
    {
        day = last_day;
    }
    var 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

0

다음은 양식 필드를 통해 날짜 입력 (membershipssignup_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;
}

0

제시된 많은 복잡한 추악한 답변에서 알 수 있듯이 날짜 및 시간은 모든 언어를 사용하는 프로그래머에게 악몽이 될 수 있습니다. 내 접근 방식은 날짜와 '델타 t'값을 Epoch Time (ms)으로 변환하고 산술을 수행 한 다음 "인간 시간"으로 다시 변환하는 것입니다.

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

이것은 약간 다른 사용 사례를 위해 작성되었지만 관련 작업에 쉽게 적용 할 수 있어야합니다.

편집 : 여기에 전체 소스 !


3
쓸데없는 대답은 다른 일 수의 달을 처리하지 않기 때문에 문제입니다.
Benubird

1
@Benubird-정중하게 요청했기 때문에 전체 소스를 업로드했습니다. 이 게시물에 링크하십시오.
Dan Ahlquist

또한 모든 시간이 24 시간 (또는 8.64e7 밀리 초) 인 일광 절약 시간제를 수용하지 않습니다.
RobG

아닙니다. DST는 현지화 문제입니다.
Dan Ahlquist

0

이 모든 것이 너무 복잡해 보이며 정확히 "한 달"을 추가하는 것이 무엇을 의미하는지에 대한 토론에 들어가는 것 같습니다. 30 일을 의미합니까? 1 일에서 1 일을 의미합니까? 마지막 날부터 마지막 ​​날까지?

후자가 2 월 27 일에 한 달을 추가하면 3 월 27 일이되고 2 월 28 일에 한 달을 추가하면 3 월 31 일이됩니다 (윤년을 제외하고 3 월 28 일이됩니다). 그런 다음 3 월 30 일에서 한 달을 빼면 ... 2 월 27 일? 누가 알아...

간단한 솔루션을 찾는 사람들은 밀리 초를 추가하고 완료하십시오.

function getDatePlusDays(dt, days) {
  return new Date(dt.getTime() + (days * 86400000));
}

또는

Date.prototype.addDays = function(days) {
  this = new Date(this.getTime() + (days * 86400000));
};

"X 개월 추가"는 월이 X 증가한다는 것을 의미한다고 생각합니다. 귀하의 답변에 코딩 단계가 적다는 것은 사실이지만 불행히도 정확성이 단순성보다 우월하다고 생각합니다. 사람들이 답을 찾으면 '2016 년 7 월 31 일'이 '2016 년 8 월 31 일'이되기를 원할 것입니다. 그리고 이것은 그렇게하지 않을 것입니다. 게다가 정확성을 대가로 단순함을 원한다면 왜 고집하지 d.setMonth(d.getMonth()+1)않습니까? 따라서 이것은 가장 간단한 아이디어도 아닙니다.
Alexander Bird

또한 모든 시간이 24 시간 (또는 8.64e7 밀리 초) 인 일광 절약 시간제를 지원하지 않습니다.
RobG

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

}

1
대부분의 코드가 영어로되어 있지 않고 Deutsch에서 변수가되면 매우 verwirrend입니다. ;)
Bernhard Hofmann

-1

BIRT 매개 변수 에서처럼 하나의 연산자로 날짜를 작성하는 것이 유용한 경우가 있습니다.

나는 1 개월 전에 다음과 같이 만들었습니다.

new Date(new Date().setMonth(new Date().getMonth()-1));   

-3
var a=new Date();
a.setDate(a.getDate()+5);

위에서 언급 한 방법과 같이 월을 Date기능에 추가 할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.