Day of Year does not update in JavaScript? - javascript

I have JavaScript Code that calculates the day of the year (for example, January 1 would be 1 and October 30 would be 304):
var now = new Date();
//leap year rules:
// The year must be evenly divisible by 4;
// If the year can also be evenly divided by 100, it is not a leap year
// Unless the year is also evenly divisible by 400. Then it is a leap year.
if(now.getUTCFullYear() % 4 == 0){
//if the year is a leap year:
if(now.getUTCFullYear() % 100 != 0){
var day = Math.ceil((now - new Date(now.getFullYear(),0,1)) / 86400000);
document.getElementById('dayOfYear').innerHTML = day;
}
else if(now.getUTCFullYear() % 100 == 0 && now.getUTCFullYear() % 400 == 0){
var day = Math.ceil((now - new Date(now.getFullYear(),0,1)) / 86400000);
document.getElementById('dayOfYear').innerHTML = day;
}
else{
var day = Math.ceil((now - new Date(now.getFullYear(),0, 0)) / 86400000);
document.getElementById('dayOfYear').innerHTML = day;
}
}
else{
//if the year is NOT a leap year
var day = Math.ceil((now - new Date(now.getFullYear(),0, 0)) / 86400000);
document.getElementById('dayOfYear').innerHTML = day;
}
The code gets refreshed every second, since it is a clock app. However, when the clock hits 00:00:00 on the next day the Day of the Year does not update until hours later. What might be causing this?
Thanks!

You are creating a Date using local values, but counting UTC days so it ticks over at UTC midnight, not local midnight. Also, the algorithm is way too complex. Just use UTC for everything, e.g.
function getDayOfYear(d = new Date()) {
// Start of year
let yearStart = Date.UTC(d.getFullYear(), 0, 1);
// Get difference to now / ms in one day
return Math.floor(((Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) - yearStart)) / 8.64e7) + 1;
}
[new Date(2020,0,1), // 1 Jan 2020
new Date(), // today
new Date(2020,11,31) // 31 Dec 2020
].forEach(d => console.log(d.toDateString() + ' is day ' + getDayOfYear(d)));
PS (Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) could also be (+d + d.getTimezoneOffset() * 6e4), which is a little shorter but maybe less readable.
To have it tick over at UTC midnight:
function getUTCDayOfYear(d = new Date()) {
// Start of year
let yearStart = Date.UTC(d.getUTCFullYear(), 0, 1);
// Get difference to now / ms in one day
return Math.floor(((Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()) - yearStart)) / 8.64e7) + 1;
}
[new Date(Date.UTC(2020,0,1)), // 1 Jan 2020 UTC
new Date(Date.UTC(2020,11,31)) // 31 Dec 2020 UTC
].forEach(d => console.log(d.toString() + ' is on UTC day ' + getUTCDayOfYear(d)));

Related

Convert decimal year to date in javascript in format mm/dd/yyyy

I figured out, after loooooooong research how to get my date into decimal years. Now, what I want to do is figure out is how to convert decimal years for example 2020.39123 into something like 11/24/2020.
My preferred output format is mm/dd/yyyy. Not the long Date() output of Wed Sep 02 2020 15:24 GMT-0300 (Time zone name).
My code so far is:
function myFunction() {
var d = Date.parse("March 21, 2012");
var minutes = 1000 * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
var y = Math.round(d / years);
document.getElementById("demo").innerHTML = y;
}
Get the month of your date add before the string "0" and take the last 2 chars to get the month as 2-digit-value. Don't forget to add 1 for month because JS counts 0-11. Same formatting procedure for the date. Just add at the end the fullyear.
function myFunction() {
let d = new Date("March 21, 2012");
let date = ('0' + (d.getMonth() +1)).slice(-2) + '/' + ('0' + d.getDate()).slice(-2) + '/' + d.getFullYear();
document.getElementById("demo").innerHTML = date;
}
myFunction();
<div id='demo'></div>
The algorithm in the OP is simplistic and doesn't account for days not being 24 hours long where daylight saving is observed. Also, not all years are 365 days long.
A more accurate algorithm would consider the actual number of milliseconds in a year and create a fraction from that. If the resolution is to be whole days, then the values should be rounded to the next whole day and 3 decimal places is sufficient. Otherwise, ECMAScript numbers don't have sufficient precision to preserve the value to millisecond accuracy and the decimal year won't be converted back to a date accurately (a variance of 1 ms can change the date to a different day).
E.g
// Conversion of a Date to decimal year
// Resolution is to day only
function toDecimalYear(date) {
// Copy date so don't affect original and set to start of day
let d = new Date(date);
d.setHours(0,0,0,0);
let year = d.getFullYear();
let yearStart = new Date(year, 0, 1);
let dayNum = Math.round((d - yearStart) / 8.64e7);
let daysInYear = Math.round((new Date(year + 1, 0, 1) - yearStart) / 8.64e7);
return +(year + dayNum / daysInYear).toFixed(3);
}
// Convert decimal year to Date
// Resolution is to nearest whole day
function fromDecimalYear(num) {
let year = parseInt(num);
let yearStart = new Date(year, 0, 1);
let daysInYear = Math.round((new Date(year + 1, 0, 1) - yearStart) / 8.64e7);
let dayNum = Math.round((num - year) * daysInYear)
yearStart.setDate(1 + dayNum);
return yearStart;
}
// Formatter
let f = date => date.toLocaleString('default',{
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
hour12: false,
minute: '2-digit',
second: '2-digit',
millisecond: 'numeric'
});
// OP example
console.log('2020.39123 => ' + f(fromDecimalYear(2020.39123)));
// Current date - set to start of day
let d = new Date();
d.setHours(0,0,0,0);
console.log(f(d) + ' = ' + toDecimalYear(d));
// Other test dates
[new Date(2012, 0, 1), // 01 Jan 2012
new Date(2012, 2, 12), // 12 Mar 2012
new Date(2012, 11, 31) // 31 Dec 2012
].forEach(date => {
let dy = toDecimalYear(date);
console.log(
'Start date : ' + f(date)
+ '\nAs decimal years: ' + dy
+ '\nBack to date : ' + f(fromDecimalYear(dy))
)
});
I think a better way to represent dates using years is to use year.dayNumber rather than fractional year. So 1 Jan 2020 is 2020.001, 1 Feb is 2020.032, etc. But then year month day is the same number of characters: 20200101, 20200201, etc.

How to calculate and check for a bi-weekly date

I really need your help,
Let's say my demarcation start date is: December 19, 2016 as defined by the variable x
How can I write a JavaScript function, such that it will check the present date against x and the present date against what the recurrence date will be (14) days from x as defined by the variable y.
var y = recurrence is every 14 days, thereafter from the date (x) with no end date specified (unlimited)
Ex.
function() {
if (present date == x) { alert(true) }
if (present date == y) { alert(true) }
}
You could get the number of days difference between your start date and the current date then check if that number is a multiple of 14.
function treatAsUTC(date) {
var result = new Date(date);
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
return result;
}
function daysBetween(startDate, endDate) {
var millisecondsPerDay = 24 * 60 * 60 * 1000;
return Math.floor((treatAsUTC(endDate) - treatAsUTC(startDate)) / millisecondsPerDay);
}
var demarcationdate = new Date("2016-12-19"),
today = new Date(),
days = daysBetween(demarcationdate,today),
daystill = 14 - days%14,
rec = days%14==0,
d = new Date();
d.setDate(today.getDate() + daystill);
var nextDate = (d.getDate() + "/" + (d.getMonth() + 1) + "/" + d.getFullYear());
console.log("Days diff = "+days+". Recurs today = "+rec+". Next in "+daystill+" days ("+nextDate.toString()+").");
jsFiddle
If Date.now() == 1482181410856, 14 days from now will be 1482181410856 + (14 * 24 * 60 * 60 * 1000) == 1483391010856.
let y = new Date(Date.now() + (14 * 24 * 60 * 60 * 1000));
console.log(y.toUTCString()); // "Mon, 02 Jan 2017 21:03:30 GMT"
Assuming you really want to compare precise dates, i.e. to the milliseconds, then:
var present_date = new Date();
if(present_date.getTime() === x.getTime()) alert("Today is the same date as x");
else {
var y = new Date(x.getTime());
y.setDate(y.getDate() + 14); // add 14 days
if(present_date.getTime() === y.getTime()) alert("Today is the same date as y");
}
But most of the time we want to compare dates as full days, not milliseconds, so you'd have to compare ranges instead (from midnight to 11:59PM)... In that case, I recommend using a library to make your life easier - like moment.js for instance...
Hope this helps!
This is probably a duplicate of Add +1 to current date.
If you have a start date, say 20 December, 2016, you can calculate 14 days after that by simply adding 14 days to the date. You can then check if today's date is either of those dates, e.g.
// Create a Date for 20 December, 2016 with time 00:00:00
var startDate = new Date(2016,11,20);
// Create a Date for the start + 14 days with time 00:00:00
var startPlus14 = new Date(startDate);
startPlus14.setDate(startPlus14.getDate() + 14);
// Get today and set the time to 00:00:00.000
var today = new Date();
today.setHours(0,0,0,0);
if (+today == +startDate) {
console.log('Today is the start date');
} else if (+today == +startPlus14) {
console.log('Today is 14 days after the start date');
} else {
console.log('Today is neither the start nor 14 days after the start');
}

JavaScript function that calculates how many year, month and days between two dates

I am looking to calculate the age in years, months and days using JavaScript. This code works for some dates, however it doesn't work if the date is less than 1 year away or anytime in the past at all.
function age(year, month, day) {
var today = new Date();
var endDate = new Date(year, month, day).getTime();
var dayDiff = Math.floor((endDate - today) / 86400000);
if (dayDiff >= 365) {
var year = Math.floor(dayDiff / 365);
var remainder = Math.floor(dayDiff) - (year * 365);
var months = Math.floor(remainder / 30);
}
var days = Math.floor(remainder) - (months * 30);
return year + " years" + " " + months + " months" + " " + days + " days";
}
console.log(age(2017, 11, 17));
console.log(age(2015, 3, 6));
however it doesn't work if the date is less than 1 year away or anytime in the past at all.
Look at the conditional of your code:
if (dayDiff >= 365) {
...
}
That would explain why it's not triggering when the date is less than 1 year (365 days) away.
You have 2 options : either strip the if (dayDiff >= 365) condition altogether or write an else statement to your if to handle cases where dayDiff < 365.
Following your logic:
function age(year, month, day) {
var today = new Date();
var endDate = new Date(year, month, day).getTime();
var dayDiff = Math.floor((endDate - today) / 86400000);
if (dayDiff >= 365) {
var year = Math.floor(dayDiff / 365);
var remainder = Math.floor(dayDiff) - (year * 365);
var months = Math.floor(remainder / 30);
} else {
var year = 0;
var remainder = Math.floor(dayDiff) - (year * 365);
var months = Math.floor(remainder / 30);
}
var days = Math.floor(remainder) - (months * 30);
return year + " years" + " " + months + " months" + " " + days + " days";
}
document.write("<p>" + age(2017, 11, 17) + "</p>");
document.write("<p>" + age(2016, 7, 11) + "</p>");
I would suggest this function to get the "natural" number of years, months and days between two dates:
function interval(date1, date2) {
if (date1 > date2) { // swap
var result = interval(date2, date1);
result.years = -result.years;
result.months = -result.months;
result.days = -result.days;
return result;
}
result = {
years: date2.getYear() - date1.getYear(),
months: date2.getMonth() - date1.getMonth(),
days: date2.getDate() - date1.getDate()
};
if (result.days < 0) {
result.months--;
// days = days left in date1's month,
// plus days that have passed in date2's month
var copy1 = new Date(date1.getTime());
copy1.setDate(32);
result.days = 32-date1.getDate()-copy1.getDate()+date2.getDate();
}
if (result.months < 0) {
result.years--;
result.months+=12;
}
return result;
}
// Be aware that the month argument is zero-based (January = 0)
var date1 = new Date(2015, 4-1, 6);
var date2 = new Date(2015, 5-1, 9);
document.write(JSON.stringify(interval(date1, date2)));
This solution will treat leap years (29 February) and month length differences in a way we would naturally do (I think).
So for example, the interval between 28 February 2015 and 28 March 2015 will be considered exactly one month, not 28 days. If both those days are in 2016, the difference will still be exactly one month, not 29 days.
Dates with exactly the same month and day, but different year, will always have a difference of an exact number of years. So the difference between 2015-03-01 and 2016-03-01 will be exactly 1 year, not 1 year and 1 day (because of counting 365 days as 1 year).

exclude weekends in javascript date calculation

I have two sets of codes that work. Needed help combining them into one.
This code gets me the difference between two dates. works perfectly:
function test(){
var date1 = new Date(txtbox_1.value);
var date2 = new Date(txtbox_2.value);
var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff));
var days = Math.floor(diff/(24*60*60));
var leftSec = diff - days * 24*60*60;
var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;
var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;
txtbox_3.value = days + "." + hrs; }
source for the above code
The code below by #cyberfly appears to have the answer of excluding sat and sun which is what i needed. source. However, its in jquery and the above code is in JS. Therefore, needed help combining as i lacked that knowledge :(
<script type="text/javascript">
$("#startdate, #enddate").change(function() {
var d1 = $("#startdate").val();
var d2 = $("#enddate").val();
var minutes = 1000*60;
var hours = minutes*60;
var day = hours*24;
var startdate1 = getDateFromFormat(d1, "d-m-y");
var enddate1 = getDateFromFormat(d2, "d-m-y");
var days = calcBusinessDays(new Date(startdate1),new Date(enddate1));
if(days>0)
{ $("#noofdays").val(days);}
else
{ $("#noofdays").val(0);}
});
</script>
EDIT
Made an attempt at combining the codes. here is my sample. getting object expected error.
function test(){
var date1 = new Date(startdate.value);
var date2 = new Date(enddate.value);
var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff));
var days = Math.floor(diff/(24*60*60));
var leftSec = diff - days * 24*60*60;
var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;
var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;
var startdate1 = getDateFromFormat(startdate, "dd/mm/yyyy hh:mm");
var enddate1 = getDateFromFormat(enddate, "dd/mm/yyyy hh:mm");
days = calcBusinessDays(new Date(startdate1),new Date(enddate1));
noofdays.value = days + "." + hrs; }
start: <input type="text" id="startdate" name="startdate" value="02/03/2015 00:00">
end: <input type="text" id="enddate" name="enddate" value="02/03/2015 00:01">
<input type="text" id="noofdays" name="noofdays" value="">
When determining the number of days between two dates, there are lots of decisions to be made about what is a day. For example, the period 1 Feb to 2 Feb is generally one day, so 1 Feb to 1 Feb is zero days.
When adding the complexity of counting only business days, things get a lot tougher. E.g. Monday 2 Feb 2015 to Friday 6 February is 4 elapsed days (Monday to Tuesday is 1, Monday to Wednesday is 2, etc.), however the expression "Monday to Friday" is generally viewed as 5 business days and the duration Mon 2 Feb to Sat 7 Feb should also be 4 business days, but Sunday to Saturday should be 5.
So here's my algorithm:
Get the total number of whole days between the two dates
Divide by 7 to get the number of whole weeks
Multiply the number of weeks by two to get the number of weekend days
Subtract the number of weekend days from the whole to get business days
If the number of total days is not an even number of weeks, add the numbe of weeks * 7 to the start date to get a temp date
While the temp date is less than the end date:
if the temp date is not a Saturday or Sunday, add one the business days
add one to the temp date
That's it.
The stepping part at the end can probably be replaced by some other algorithm, but it will never loop for more than 6 days so it's a simple and reasonably efficient solution to the issue of uneven weeks.
Some consequences of the above:
Monday to Friday is 4 business days
Any day to the same day in a different week is an even number of weeks and therefore an even mutiple of 5, e.g. Monday 2 Feb to Monday 9 Feb and Sunday 1 Feb to Sunday 8 Feb are 5 business days
Friday 6 Feb to Sunday 7 Feb is zero business days
Friday 6 Feb to Monday 9 Feb is one business day
Sunday 8 Feb to: Sunday 15 Feb, Sat 14 Feb and Fri 13 Feb are all 5 business days
Here's the code:
// Expects start date to be before end date
// start and end are Date objects
function dateDifference(start, end) {
// Copy date objects so don't modify originals
var s = new Date(+start);
var e = new Date(+end);
// Set time to midday to avoid dalight saving and browser quirks
s.setHours(12,0,0,0);
e.setHours(12,0,0,0);
// Get the difference in whole days
var totalDays = Math.round((e - s) / 8.64e7);
// Get the difference in whole weeks
var wholeWeeks = totalDays / 7 | 0;
// Estimate business days as number of whole weeks * 5
var days = wholeWeeks * 5;
// If not even number of weeks, calc remaining weekend days
if (totalDays % 7) {
s.setDate(s.getDate() + wholeWeeks * 7);
while (s < e) {
s.setDate(s.getDate() + 1);
// If day isn't a Sunday or Saturday, add to business days
if (s.getDay() != 0 && s.getDay() != 6) {
++days;
}
}
}
return days;
}
I don't know how it compares to jfriend00's answer or the code you referenced, if you want the period to be inclusive, just add one if the start or end date are a business day.
Here's a simple function to calculate the number of business days between two date objects. As designed, it does not count the start day, but does count the end day so if you give it a date on a Tuesday of one week and a Tuesday of the next week, it will return 5 business days. This does not account for holidays, but does work properly across daylight savings changes.
function calcBusinessDays(start, end) {
// This makes no effort to account for holidays
// Counts end day, does not count start day
// make copies we can normalize without changing passed in objects
var start = new Date(start);
var end = new Date(end);
// initial total
var totalBusinessDays = 0;
// normalize both start and end to beginning of the day
start.setHours(0,0,0,0);
end.setHours(0,0,0,0);
var current = new Date(start);
current.setDate(current.getDate() + 1);
var day;
// loop through each day, checking
while (current <= end) {
day = current.getDay();
if (day >= 1 && day <= 5) {
++totalBusinessDays;
}
current.setDate(current.getDate() + 1);
}
return totalBusinessDays;
}
And, the jQuery + jQueryUI code for a demo:
// make both input fields into date pickers
$("#startDate, #endDate").datepicker();
// process click to calculate the difference between the two days
$("#calc").click(function(e) {
var diff = calcBusinessDays(
$("#startDate").datepicker("getDate"),
$("#endDate").datepicker("getDate")
);
$("#diff").html(diff);
});
And, here's a simple demo built with the date picker in jQueryUI: http://jsfiddle.net/jfriend00/z1txs10d/
const firstDate = new Date("December 30, 2020");
const secondDate = new Date("January 4, 2021");
const daysWithOutWeekEnd = [];
for (var currentDate = new Date(firstDate); currentDate <= secondDate; currentDate.setDate(currentDate.getDate() + 1)) {
// console.log(currentDate);
if (currentDate.getDay() != 0 && currentDate.getDay() != 6) {
daysWithOutWeekEnd.push(new Date(currentDate));
}
}
console.log(daysWithOutWeekEnd, daysWithOutWeekEnd.length);
#RobG has given an excellent algorithm to separate business days from weekends.
I think the only problem is if the starting days is a weekend, Saturday or Sunday, then the no of working days/weekends will one less.
Corrected code is below.
function dateDifference(start, end) {
// Copy date objects so don't modify originals
var s = new Date(start);
var e = new Date(end);
var addOneMoreDay = 0;
if( s.getDay() == 0 || s.getDay() == 6 ) {
addOneMoreDay = 1;
}
// Set time to midday to avoid dalight saving and browser quirks
s.setHours(12,0,0,0);
e.setHours(12,0,0,0);
// Get the difference in whole days
var totalDays = Math.round((e - s) / 8.64e7);
// Get the difference in whole weeks
var wholeWeeks = totalDays / 7 | 0;
// Estimate business days as number of whole weeks * 5
var days = wholeWeeks * 5;
// If not even number of weeks, calc remaining weekend days
if (totalDays % 7) {
s.setDate(s.getDate() + wholeWeeks * 7);
while (s < e) {
s.setDate(s.getDate() + 1);
// If day isn't a Sunday or Saturday, add to business days
if (s.getDay() != 0 && s.getDay() != 6) {
++days;
}
//s.setDate(s.getDate() + 1);
}
}
var weekEndDays = totalDays - days + addOneMoreDay;
return weekEndDays;
}
JSFiddle link is https://jsfiddle.net/ykxj4k09/2/
First Get the Number of Days in a month
totalDays(month, year) {
return new Date(year, month, 0).getDate();
}
Then Get No Of Working Days In A Month By removing Saturday and Sunday
totalWorkdays() {
var d = new Date(); // to know present date
var m = d.getMonth() + 1; // to know present month
var y = d.getFullYear(); // to knoow present year
var td = this.totalDays(m, y);// to get no of days in a month
for (var i = 1; i <= td; i++) {
var s = new Date(y, m - 1, i);
if (s.getDay() != 0 && s.getDay() != 6) {
this.workDays.push(s.getDate());// working days
}else {
this.totalWeekDays.push(s.getDate());//week days
}
}
this.totalWorkingDays = this.workDays.length;
}
I thought the above code snippets others shared are lengthy.
I am sharing a concise snippet that gives date after considering the total number of days specified. we can also customize dates other than Saturdays and Sundays.
function getBusinessDays(dateObj, days) {
for (var i = 0; i < days; i++) {
if (days > 0) {
switch (dateObj.getDay()) {
// 6 being Saturday and 0 being Sunday.
case 6, 0:
dateObj.setDate(dateObj.getDate() + 2)
break;
//5 = Friday.
case 5:
dateObj.setDate(dateObj.getDate() + 3)
break;
//handle Monday, Tuesday, Wednesday and Thursday!
default:
dateObj.setDate(dateObj.getDate() + 1)
//console.log(dateObj)
break;
}
}
}
return dateObj;
}
console.log(getBusinessDays(new Date(), 11))
//Mon Dec 20 2021 18:56:01 GMT+0530 (India Standard Time)

JavaScript function to add X months to a date

I’m looking for the easiest, cleanest way to add X months to a JavaScript date.
I’d rather not handle the rolling over of the year or have to write my own function.
Is there something built in that can do this?
The following function adds months to a date in JavaScript (source). It takes into account year roll-overs and varying month lengths:
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());
The above solution covers the edge case of moving from a month with a greater number of days than the destination month. eg.
Add twelve months to February 29th 2020 (should be February 28th 2021)
Add one month to August 31st 2020 (should be September 30th 2020)
If the day of the month changes when applying setMonth, then we know we have overflowed into the following month due to a difference in month length. In this case, we use setDate(0) to move back to the last day of the previous month.
Note: this version of this answer replaces an earlier version (below) that did not gracefully handle different month lengths.
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);
I'm using moment.js library for date-time manipulations.
Sample code to add one month:
var startDate = new Date(...);
var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format
endDateMoment.add(1, 'months');
This function handles edge cases and is fast:
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
}
test:
> 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"
Update for non-UTC dates: (by 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
}
test:
> 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"
Taken from #bmpsini and #Jazaret responses, but not extending prototypes: using plain functions (Why is extending native objects a bad practice?):
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;
}
Use it:
var nextMonth = addMonths(new Date(), 1);
Considering none of these answers will account for the current year when the month changes, you can find one I made below which should handle it:
The method:
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;
}
Usage:
return new Date().addMonths(2);
From the answers above, the only one that handles the edge cases (bmpasini's from datejs library) has an issue:
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)
ok, but:
newDate.toISOString()
//"2015-04-29T22:00:00.000Z"
worse :
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"
This is due to the time not being set, thus reverting to 00:00:00, which then can glitch to previous day due to timezone or time-saving changes or whatever...
Here's my proposed solution, which does not have that problem, and is also, I think, more elegant in that it does not rely on hard-coded values.
/**
* #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];
};
Unit tested successfully with:
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')
);
d = new Date();
alert(d.getMonth()+1);
Months have a 0-based index, it should alert(4) which is 5 (may);
Simple solution: 2678400000 is 31 day in milliseconds
var oneMonthFromNow = new Date((+new Date) + 2678400000);
Update:
Use this data to build our own function:
2678400000 - 31 day
2592000000 - 30 days
2505600000 - 29 days
2419200000 - 28 days
As most of the answers highlighted, we could use setMonth() method together with getMonth() method to add specific number of months to a given date.
Example: (as mentioned by #ChadD in his answer. )
var x = 12; //or whatever offset
var CurrentDate = new Date();
CurrentDate.setMonth(CurrentDate.getMonth() + x);
But we should carefully use this solution as we will get trouble with edge cases.
To handle edge cases, answer which is given in following link is helpful.
https://stackoverflow.com/a/13633692/3668866
Just to add on to the accepted answer and the comments.
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);
I wrote this alternative solution which works fine to me. It is useful when you wish calculate the end of a contract. For example, start=2016-01-15, months=6, end=2016-7-14 (i.e. last day - 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>
Examples:
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
This works for all edge cases. The weird calculation for newMonth handles negative months input. If the new month does not match the expected month (like 31 Feb), it will set the day of month to 0, which translates to "end of previous month":
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;
}
I changed the accepted answer a bit to keep the original date intact, as I think it should in a function like this.
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;
}
The following is an example of how to calculate a future date based on date input (membershipssignup_date) + added months (membershipsmonths) via form fields.
The membershipsmonths field has a default value of 0
Trigger link (can be an onchange event attached to membership term field):
Calculate Expiry Date
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;
}
Sometimes useful create date by one operator like in BIRT parameters
I made 1 month back with:
new Date(new Date().setMonth(new Date().getMonth()-1));
As demonstrated by many of the complicated, ugly answers presented, Dates and Times can be a nightmare for programmers using any language. My approach is to convert dates and 'delta t' values into Epoch Time (in ms), perform any arithmetic, then convert back to "human 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 );
This was written for a slightly different use case, but you should be able to easily adapt it for related tasks.
EDIT: Full source here!
Easiest solution is:
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.
Easy, simplest
function addMonths(date, months) {date.setMonth(date.getMonth() + months); return date;};
Use it as
alert(new Date().toLocaleString()); //will say today
alert(addMonths(new Date(),12).toLocaleString()); //will say next year, same day and month
Looking for something in typescript?
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;
}
}
A simple answer can be :
function addMonthsToDate(date, numMonths){
// Add months
date.setMonth(date.getMonth() + numMonths);
// Zero the time component
date.setHours(0, 0, 0, 0);
return date;
}
This can be called - to add two months:
console.log(addMonthsToDate(new Date(),2));
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 );
}
All these seem way too complicated and I guess it gets into a debate about what exactly adding "a month" means. Does it mean 30 days? Does it mean from the 1st to the 1st? From the last day to the last day?
If the latter, then adding a month to Feb 27th gets you to March 27th, but adding a month to Feb 28th gets you to March 31st (except in leap years, where it gets you to March 28th). Then subtracting a month from March 30th gets you... Feb 27th? Who knows...
For those looking for a simple solution, just add milliseconds and be done.
function getDatePlusDays(dt, days) {
return new Date(dt.getTime() + (days * 86400000));
}
or
Date.prototype.addDays = function(days) {
this = new Date(this.getTime() + (days * 86400000));
};
I have done by using Moment Js Library
Refs: 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);
As above stated method, you can add month to Date function.

Categories