JavaScript 날짜에 X 개월을 추가하는 가장 쉽고 깨끗한 방법을 찾고 있습니다.
차라리 연중 롤오버를 처리 하지 않거나 내 자신의 함수 를 작성 해야 합니다 .
이것을 할 수있는 것이 내장되어 있습니까?
JavaScript 날짜에 X 개월을 추가하는 가장 쉽고 깨끗한 방법을 찾고 있습니다.
차라리 연중 롤오버를 처리 하지 않거나 내 자신의 함수 를 작성 해야 합니다 .
이것을 할 수있는 것이 내장되어 있습니까?
답변:
다음 함수는 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());
위의 솔루션은 한 달에서 목적지 월보다 일수가 더 많은 경우에 적용됩니다. 예.
를 적용 할 때 월의 날짜가 변경되면 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);
날짜-시간 조작에 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 날짜 업데이트 : (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"
이 답변들 중 어느 것도 달이 바뀌는 현재 연도를 설명하지 않는다는 것을 고려할 때 아래에서 내가 처리 한 답변을 찾을 수 있습니다.
방법:
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);
에서 촬영 @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);
위의 답변에서 가장자리 사례를 처리하는 유일한 사람 (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')
);
대부분의 답변이 강조 표시 되었으므로 setMonth () 메소드를 getMonth () 메소드 와 함께 사용 하여 특정 날짜에 특정 개월 수를 추가 할 수 있습니다.
예 : (그의 대답에서 @ChadD가 언급 한대로)
var x = 12; //or whatever offset var CurrentDate = new Date(); CurrentDate.setMonth(CurrentDate.getMonth() + x);
그러나 에지 솔루션에 문제가 발생할 수 있으므로이 솔루션을 신중하게 사용해야합니다.
에지 사례를 처리하려면 다음 링크에 나와있는 답변이 도움이됩니다.
https://stackoverflow.com/a/13633692/3668866
간단한 해결책 : 2678400000
31 밀리 초입니다
var oneMonthFromNow = new Date((+new Date) + 2678400000);
최신 정보:
이 데이터를 사용하여 자체 기능을 빌드하십시오.
2678400000
-31 일2592000000
- 30 일2505600000
-29 일2419200000
-28 일수락 된 답변과 의견에 추가하기 만하면됩니다.
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);
나는 나에게 잘 작동하는이 대안 솔루션을 썼다. 계약 종료를 계산할 때 유용합니다. 예를 들어 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
다음은 양식 필드를 통해 날짜 입력 (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;
}
제시된 많은 복잡한 추악한 답변에서 알 수 있듯이 날짜 및 시간은 모든 언어를 사용하는 프로그래머에게 악몽이 될 수 있습니다. 내 접근 방식은 날짜와 '델타 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 );
이것은 약간 다른 사용 사례를 위해 작성되었지만 관련 작업에 쉽게 적용 할 수 있어야합니다.
편집 : 여기에 전체 소스 !
이 모든 것이 너무 복잡해 보이며 정확히 "한 달"을 추가하는 것이 무엇을 의미하는지에 대한 토론에 들어가는 것 같습니다. 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));
};
d.setMonth(d.getMonth()+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 );
}
BIRT 매개 변수 에서처럼 하나의 연산자로 날짜를 작성하는 것이 유용한 경우가 있습니다.
나는 1 개월 전에 다음과 같이 만들었습니다.
new Date(new Date().setMonth(new Date().getMonth()-1));