Tôi đang tìm cách dễ nhất, sạch nhất để thêm X tháng vào một ngày JavaScript.
Tôi thà không xử lý việc lăn lộn trong năm hoặc phải viết chức năng của riêng mình .
Có một cái gì đó được xây dựng trong đó có thể làm điều này?
Tôi đang tìm cách dễ nhất, sạch nhất để thêm X tháng vào một ngày JavaScript.
Tôi thà không xử lý việc lăn lộn trong năm hoặc phải viết chức năng của riêng mình .
Có một cái gì đó được xây dựng trong đó có thể làm điều này?
Câu trả lời:
Hàm sau thêm tháng vào một ngày trong JavaScript ( nguồn ). Nó đưa vào tài khoản cuộn qua năm và độ dài tháng khác nhau:
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());
Giải pháp trên bao gồm trường hợp cạnh của việc di chuyển từ một tháng với số ngày lớn hơn tháng đích. ví dụ.
Nếu ngày trong tháng thay đổi khi đăng ký setMonth
, thì chúng tôi biết rằng chúng tôi đã tràn vào tháng tiếp theo do sự khác biệt về độ dài của tháng. Trong trường hợp này, chúng tôi sử dụng setDate(0)
để quay trở lại ngày cuối cùng của tháng trước.
Lưu ý: phiên bản của câu trả lời này thay thế một phiên bản trước đó (bên dưới) không xử lý một cách duyên dáng các độ dài tháng khác nhau.
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);
Tôi đang sử dụng thư viện Moment.js để thao tác thời gian . Mã mẫu để thêm một tháng:
var startDate = new Date(...);
var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format
endDateMoment.add(1, 'months');
Hàm này xử lý các trường hợp cạnh và nhanh:
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
}
kiểm tra:
> 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"
Cập nhật cho các ngày không thuộc UTC: (bởi 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
}
kiểm tra:
> 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"
Xem xét không có câu trả lời nào trong số những câu trả lời này sẽ giải thích cho năm hiện tại khi tháng thay đổi, bạn có thể tìm thấy câu trả lời tôi đưa ra dưới đây để xử lý nó:
Phương pháp:
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;
}
Sử dụng:
return new Date().addMonths(2);
Lấy từ @bmpsini và @Jazaret phản ứng, nhưng không kéo dài mẫu: sử dụng chức năng đơn giản ( Tại sao mở rộng đối tượng có nguồn gốc một thực tế xấu? ):
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;
}
Sử dụng nó:
var nextMonth = addMonths(new Date(), 1);
Từ các câu trả lời ở trên, người duy nhất xử lý các trường hợp cạnh (bmpasini từ thư viện datejs) có một vấn đề:
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)
Được rồi nhưng:
newDate.toISOString()
//"2015-04-29T22:00:00.000Z"
tệ hơn:
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"
Điều này là do thời gian không được đặt, do đó trở lại 00:00:00, sau đó có thể bị trục trặc sang ngày trước do thay đổi múi giờ hoặc tiết kiệm thời gian hoặc bất cứ điều gì ...
Đây là giải pháp đề xuất của tôi, không có vấn đề đó, và tôi nghĩ, thanh lịch hơn ở chỗ nó không dựa vào các giá trị được mã hóa cứng.
/**
* @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];
};
Đơn vị đã thử nghiệm thành công với:
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')
);
Như hầu hết các câu trả lời được tô sáng, chúng ta có thể sử dụng phương thức setMonth () cùng với phương thức getMonth () để thêm số tháng cụ thể vào một ngày nhất định.
Ví dụ: (như được đề cập bởi @ChadD trong câu trả lời của anh ấy.)
var x = 12; //or whatever offset var CurrentDate = new Date(); CurrentDate.setMonth(CurrentDate.getMonth() + x);
Nhưng chúng ta nên cẩn thận sử dụng giải pháp này vì chúng ta sẽ gặp rắc rối với các trường hợp cạnh.
Để xử lý các trường hợp cạnh, câu trả lời được đưa ra trong liên kết sau đây là hữu ích.
https://stackoverflow.com/a/13633692/3668866
Giải pháp đơn giản: 2678400000
là 31 ngày tính bằng mili giây
var oneMonthFromNow = new Date((+new Date) + 2678400000);
Cập nhật:
Sử dụng dữ liệu này để xây dựng chức năng của chúng ta:
2678400000
- 31 ngày2592000000
- 30 ngày2505600000
- 29 ngày2419200000
- 28 ngàyChỉ cần thêm vào câu trả lời được chấp nhận và các ý kiến.
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);
Tôi đã viết giải pháp thay thế này hoạt động tốt với tôi. Nó rất hữu ích khi bạn muốn tính kết thúc hợp đồng. Ví dụ: start = 2016-01-15, tháng = 6, end = 2016-7-14 (tức là ngày cuối cùng - 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>
Ví dụ:
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
Sau đây là một ví dụ về cách tính ngày trong tương lai dựa trên đầu vào ngày (thành viênsignup_date) + tháng được thêm (thành viên tháng) thông qua các trường mẫu.
Trường thành viên hàng tháng có giá trị mặc định là 0
Liên kết kích hoạt (có thể là một sự kiện trao đổi gắn liền với trường thuật ngữ thành viên):
<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;
}
Như đã được chứng minh bằng nhiều câu trả lời phức tạp, xấu xí được trình bày, Ngày và Giờ có thể là cơn ác mộng đối với các lập trình viên sử dụng bất kỳ ngôn ngữ nào. Cách tiếp cận của tôi là chuyển đổi ngày và giá trị 'delta t' thành Epoch Time (tính bằng ms), thực hiện bất kỳ số học nào, sau đó chuyển đổi lại thành "thời gian của con người".
// 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 );
Điều này đã được viết cho một trường hợp sử dụng hơi khác nhau, nhưng bạn sẽ có thể dễ dàng điều chỉnh nó cho các nhiệm vụ liên quan.
EDIT: Nguồn đầy đủ ở đây !
Tất cả những điều này dường như quá phức tạp và tôi đoán nó sẽ vướng vào một cuộc tranh luận về việc thêm chính xác "một tháng" nghĩa là gì. Có nghĩa là 30 ngày? Nó có nghĩa là từ 1 đến 1? Từ ngày cuối cùng đến ngày cuối cùng?
Nếu sau này, sau đó thêm một tháng vào ngày 27 tháng 2 sẽ đưa bạn đến ngày 27 tháng 3, nhưng thêm một tháng vào ngày 28 tháng 2 sẽ đưa bạn đến ngày 31 tháng 3 (ngoại trừ những năm nhuận, nơi bạn đưa bạn đến ngày 28 tháng 3). Sau đó trừ đi một tháng kể từ ngày 30 tháng 3, bạn có ... ngày 27 tháng 2 không? Ai biết...
Đối với những người tìm kiếm một giải pháp đơn giản, chỉ cần thêm mili giây và được thực hiện.
function getDatePlusDays(dt, days) {
return new Date(dt.getTime() + (days * 86400000));
}
hoặc là
Date.prototype.addDays = function(days) {
this = new Date(this.getTime() + (days * 86400000));
};
d.setMonth(d.getMonth()+1)
? Vì vậy, đây thậm chí không phải là ý tưởng đơn giản nhất.
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 );
}
Đôi khi hữu ích tạo ngày bởi một toán tử như trong các tham số BIRT
Tôi đã thực hiện 1 tháng trở lại với:
new Date(new Date().setMonth(new Date().getMonth()-1));