Related
I have an date, i need to add no. of days to get future date but weekends should be excluded.
i.e
input date = "9-DEC-2011";
No. of days to add = '13';
next date should be "28-Dec-2011"
Here weekends(sat/sun) are not counted.
Try this
var startDate = "9-DEC-2011";
startDate = new Date(startDate.replace(/-/g, "/"));
var endDate = "", noOfDaysToAdd = 13, count = 0;
while(count < noOfDaysToAdd){
endDate = new Date(startDate.setDate(startDate.getDate() + 1));
if(endDate.getDay() != 0 && endDate.getDay() != 6){
//Date.getDay() gives weekday starting from 0(Sunday) to 6(Saturday)
count++;
}
}
alert(endDate);//You can format this date as per your requirement
Working Demo
#ShankarSangoli
Here's a newer version which avoid recreating a Date object on each loop, note that it's wrapped in a function now.
function calcWorkingDays(fromDate, days) {
var count = 0;
while (count < days) {
fromDate.setDate(fromDate.getDate() + 1);
if (fromDate.getDay() != 0 && fromDate.getDay() != 6) // Skip weekends
count++;
}
return fromDate;
}
alert(calcWorkingDays(new Date("9/DEC/2011"), 13));
Here is an elegant solution without any looping or external library:
function addBusinessDaysToDate(date, days) {
var day = date.getDay();
date = new Date(date.getTime());
date.setDate(date.getDate() + days + (day === 6 ? 2 : +!day) + (Math.floor((days - 1 + (day % 6 || 1)) / 5) * 2));
return date;
}
var date = "9-DEC-2011";
var newDate = addBusinessDaysToDate(new Date(date.replace(/-/g, "/")), 13);
console.log(newDate.toString().replace(/\S+\s(\S+)\s(\d+)\s(\d+)\s.*/, '$2-$1-$3')); // alerts "28-Dec-2011"
or you can be like this
function addWeekdays(date, weekdays) {
var newDate = new Date(date.getTime());
var i = 0;
while (i < weekdays) {
newDate.setDate(newDate.getDate() + 1);
var day = newDate.getDay();
if (day > 1 && day < 7) {
i++;
}
}
return newDate;
}
var currentDate = new Date('10/31/2014');
var targetDate = addWeekdays(currentDate, 45);
alert(targetDate);
Using moment.js:
const DATE_FORMAT = 'D-MMM-YYYY';
const SUNDAY = 0; // moment day index
const SATURDAY = 6; // moment day index
const WEEKENDS = [SATURDAY, SUNDAY];
function addBusinessDays(stringDate, numberOfDays, dateFormat = DATE_FORMAT) {
const date = moment(stringDate, dateFormat);
let count = 0;
while (count < numberOfDays) {
date.add(1, 'day');
// Skip weekends
if (WEEKENDS.includes(date.day())) {
continue;
}
// Increment count
count++;
}
return date.format(dateFormat);
}
// Test cases
console.log(addBusinessDays('3-Mar-2021', 1)); // 4-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 2)); // 5-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 3)); // 8-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 4)); // 9-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 5)); // 10-Mar-2021
console.log(addBusinessDays('9-Dec-2011', 13)); // 28-Dec-2011
console.log(addBusinessDays('10-Dec-2011', 13)); // 28-Dec-2011 (Saturday, so remain on Friday)
console.log(addBusinessDays('11-Dec-2011', 13)); // 28-Dec-2011 (Sunday, so remain on Friday)
console.log(addBusinessDays('12-Dec-2011', 13)); // 29-Dec-2011
console.log(addBusinessDays('13-Dec-2011', 13)); // 30-Dec-2011
console.log(addBusinessDays('14-Dec-2011', 13)); // 2-Jan-2012
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
This question is quite old, but all the previous answers are iterating over the days one by one. That could be inefficient for a large number of days. This works for me, assuming days is a positive int and the startDate is a working day:
function addWorkingDates(startDate, days) {
const current_day = startDate.getDay() - 1; // Week day, starting on Monday
const weekend_days = 2 * parseInt((current_day + days) / 5);
startDate.setDate(changed_to.getDate() + days + weekend_days);
}
addWorkingDates(new Date(),5)
For some reason it was more intuitive to me to try this recursively. This version doesn't account for holidays, but you could change the isValid function to check whatever.
function addWeekdaysToDate(date, numberToAdd) {
var isValid = function(d) { return d.getDay() !== 0 && d.getDay() !== 6 }
if(Math.abs(numberToAdd) > 1) {
return addWeekdaysToDate(
addWeekdaysToDate(date, Math.sign(numberToAdd)),
numberToAdd - Math.sign(numberToAdd)
)
} else if(Math.abs(numberToAdd) === 1) {
var result = new Date(date)
result.setDate(result.getDate() + Math.sign(numberToAdd))
if(isValid(result)) {
return result
} else {
return addWeekdaysToDate(result, Math.sign(numberToAdd))
}
} else if(numberToAdd === 0) {
return date
}
return false
}
console.log(addWeekdaysToDate(new Date(), 1))
console.log(addWeekdaysToDate(new Date(), 5))
console.log(addWeekdaysToDate(new Date(), -7))
In certain browsers you may need a polyfill for Math.sign:
Math.sign = Math.sign || function(x) {
x = +x; // convert to a number
if (x === 0 || isNaN(x)) {
return Number(x);
}
return x > 0 ? 1 : -1;
}
try this solution
<script language="javascript">
function getDateExcludeWeekends(startDay, startMonth, startYear, daysToAdd) {
var sdate = new Date();
var edate = new Date();
var dayMilliseconds = 1000 * 60 * 60 * 24;
sdate.setFullYear(startYear,startMonth,startDay);
edate.setFullYear(startYear,startMonth,startDay+daysToAdd);
var weekendDays = 0;
while (sdate <= edate) {
var day = sdate.getDay()
if (day == 0 || day == 6) {
weekendDays++;
}
sdate = new Date(+sdate + dayMilliseconds);
}
sdate.setFullYear(startYear,startMonth,startDay + weekendDays+daysToAdd);
return sdate;
}
</script>
If you want to get the next working day, from a specific date, use the following code...
function getNextWorkingDay(originalDate) {
var nextWorkingDayFound = false;
var nextWorkingDate = new Date();
var dateCounter = 1;
while (!nextWorkingDayFound) {
nextWorkingDate.setDate(originalDate.getDate() + dateCounter);
dateCounter++;
if (!isDateOnWeekend(nextWorkingDate)) {
nextWorkingDayFound = true;
}
}
return nextWorkingDate;
}
function isDateOnWeekend(date) {
if (date.getDay() === 6 || date.getDay() === 0)
return true;
else
return false;
}
Try this
function calculate() {
var noOfDaysToAdd = 13;
var startDate = "9-DEC-2011";
startDate = new Date(startDate.replace(/-/g, "/"));
var endDate = "";
count = 0;
while (count < noOfDaysToAdd) {
endDate = new Date(startDate.setDate(startDate.getDate() + 1));
if (endDate.getDay() != 0 && endDate.getDay() != 6) {
count++;
}
}
document.getElementById("result").innerHTML = endDate;
}
<div>
Date of book delivery: <span id="result"></span><br /><br />
<input type="button" onclick="calculate();" value="Calculate" />
<br>
<br>
</div>
I receive a start and end date and I want to extract all the dates that are between these two dates, but only on specified weekdays.
I wrote a small code that calculate the dates for "Tuesday, Wednesday and Friday" between the dates:
start_date = "2019-12-31"
end_date = "2020-01-31"
it works ok but the problem is that it start to calculate from 'Tuesday 07-01-2020' and I want to start to get the date from 'Tuesday 31-12-2019'. The code is as follows:
function nextWeekdayDate(date, day_in_week) {
var ret = new Date(date || new Date());
ret.setDate(ret.getDate() + (day_in_week - 1 - ret.getDay() + 7) % 7 + 1);
return ret;
}
var delivery_dates = []
var day_num = { "Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5 };
var days_of_week = ["Tue", "Wed", "Fri"];
start_date = new Date('2019-12-31');
end_date = new Date('2020-01-31');
var new_dates = []
while (start_date < end_date) {
for (var i = 0; i <= 2; i++) {
start_date = nextWeekdayDate(start_date, day_num[days_of_week[i]]);
delivery_dates.push(start_date)
}
}
console.log(delivery_dates);
Any idea what is wrong with my code? here is a jsfiddle:
https://jsfiddle.net/mpe49hun/8/
Since the first date is a Tuesday, the function
function nextWeekdayDate(date, day_in_week) {
var ret = new Date(date || new Date());
ret.setDate(ret.getDate() + (day_in_week - 1 - ret.getDay() + 7) % 7 + 1);
return ret;
}
adds seven days to ret when it should be zero
changing the "maths" to ret.setDate(ret.getDate() + ((7 + day_in_week - ret.getDay())) % 7); will fix this
function nextWeekdayDate(date, day_in_week) {
var ret = new Date(date || new Date());
ret.setDate(ret.getDate() + ((7 + day_in_week - ret.getDay())) % 7);
return ret;
}
var delivery_dates = []
var day_num = {
"Mon": 1,
"Tue": 2,
"Wed": 3,
"Thu": 4,
"Fri": 5
};
var days_of_week = ["Tue", "Wed", "Fri"];
start_date = new Date('2019-12-31');
end_date = new Date('2020-01-31');
var new_dates = []
while (start_date < end_date) {
for (var i = 0; i <= 2; i++) {
start_date = nextWeekdayDate(start_date, day_num[days_of_week[i]]);
delivery_dates.push(start_date)
}
}
console.log(delivery_dates);
However, given a start date of 2019-12-25, for example, the wednesday 25/12 and friday 27/12 wont' be included in the output - if it should be included, then the following code is probably what you want
var delivery_dates = []
var day_num = { "Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5 };
var days_of_week = ["Tue", "Wed", "Fri"];
var includedDays = days_of_week.map(d => day_num[d]);
start_date = new Date('2019-12-25');
end_date = new Date('2020-01-31');
while (start_date <= end_date) {
if (includedDays.includes(start_date.getDay())) {
delivery_dates.push(new Date(start_date));
}
start_date.setDate(start_date.getDate() + 1);
}
console.log(delivery_dates)
I'm very new to javascript and moment.js. I'm working on a site where we need to list out the next 5 possible pickup dates for a product, excluding weekends and holidays. I have a start on this, using a function I found online. It works well at skipping the weekends, however I can't get the holidays working. Any help would be appreciated. http://jsfiddle.net/rLjQx/940/
moment.fn.addWorkdays = function(days) {
var increment = days / Math.abs(days);
var date = this.clone().add(Math.floor(Math.abs(days) / 5) * 7 * increment, 'days');
var remaining = days % 5;
while (remaining != 0) {
date.add(increment, 'days');
// Check for weekends and a static date
if (!(date.isoWeekday() === 6) && !(date.isoWeekday() === 7) && !(date.date() === 1 && date.month() === 4)) {
remaining -= increment;
}
}
return date;
};
for (count = 0; count < 5; count++) {
var test = moment().addWorkdays(count + 1).format('dddd, MMMM Do YYYY');
document.write("Pickup date : " + test);
document.write("<br />");
}
Here's a quick and easy solution using my moment-holiday plugin. :)
function getNextWorkDays(count, format) {
if (!count) { count = 5; }
if (!format) { format = 'dddd, MMMM Do YYYY'; }
var days = [];
var d = moment().startOf('day');
for (i = 0; i < count; i++) {
d.add(1, 'day');
if (d.day() === 0 || d.day() === 6 || d.isHoliday()) {
count++;
continue;
}
days.push(moment(d).format(format));
}
return days;
}
var days = getNextWorkDays();
alert("The following days are available for pickup:\n\n" + days.join("\n"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdn.rawgit.com/kodie/moment-holiday/v1.2.0/moment-holiday.js"></script>
I know this is an old post, but now that moment is deprecated using built-in date methods is a much better approach. Here is a gist I created doing just that and is copied below for reference.
function isHoliday(date: Date) {
const holidays = {
MD: {
// Month, Day
'1/1': "New Year's Day",
'7/4': 'Independence Day',
'11/11': "Veteran's Day",
'12/25': 'Christmas Day',
'12/31': "New Year's Eve"
},
MODW: {
// Month, Occurence, Day of Week
'1/3/1': 'Martin Luther King Jr. Day',
'2/3/1': 'Presidents Day',
'5/L/1': 'Memorial Day',
'9/1/1': 'Labor Day',
'10/2/1': 'Columbus Day',
'11/4/4': 'Thanksgiving Day'
}
};
const dayOfTheMonth = date.getDate();
const month = date.getMonth() + 1;
const dayOfTheWeek = date.getDay(); // 0 - 6, Su -> Sa
const lastDayOfTheMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
const isLastOccurrence = dayOfTheMonth + 7 > lastDayOfTheMonth;
let currentOccurrenceDay = dayOfTheMonth,
occurrence = 0;
for (currentOccurrenceDay; currentOccurrenceDay > 0; currentOccurrenceDay -= 7) occurrence++;
return !!(
holidays.MD?.[`${month}/${dayOfTheMonth}`] ||
(isLastOccurrence && holidays.MODW?.[`${month}/L/${dayOfTheWeek}`]) ||
holidays.MODW?.[`${month}/${occurrence}/${dayOfTheWeek}`]
);
}
Hello I am trying to use the following code which is a mish mash of "lifted code" but it keeps pumping out todays date and time.
I am trying to get the date for the first Tuesday of every month at 19:00.
I am using W3C School Try-it for testing purposes.
<!DOCTYPE html>
<html>
<head>
<script>
function displayDate()
{
var myDate = new Date();
myDate.setHours(19, 00, 0, 0);
myDate.setYear(2013);
myDate.setDate(1);
myDate.setMonth();
//Find Tuesday
var tue = 2;
while(myDate.getDay() != tue) {
myDate.setDate(myDate.getDate() + 1);
}
document.write(myDate);
</script>
</head>
<body>
<h1>My First JavaScript</h1>
<p id="demo">This is a paragraph.</p>
<button type="button" onclick="displayDate()">Display Date</button>
</body>
</html>
Roy
<==Update==>
I have use your code which works well but need to factor in after the First Tuesday has happened for the next month, I have tried this if statement but breaks.
function getTuesday() {
var datenow = new Date();
var d = new Date(),
month = d.getMonth(),
tuedays= [];
d.setDate(1);
// Get the first Monday in the month
while (d.getDay() !== 2) {
d.setDate(d.getDate() + 1);
}
// Get all the other Tuesdays in the month
while (d.getMonth() === month) {
tuedays.push(new Date(d.setHours(17,00,00,00)));
d.setDate(d.getDate() + 7);
}
If (d.getDate() >= datenow.getDate)
{
d.setMonth(d.getMonth() + 1);
document.write(tuedays[1]);
}
Else
{
document.write(tuedays[1]);
}
}
Use below function, that will give you current month Tuesdays.
function getTuesday() {
var d = new Date(),
month = d.getMonth(),
tuesdays= [];
d.setDate(1);
// Get the first Monday in the month
while (d.getDay() !== 2) {
d.setDate(d.getDate() + 1);
}
// Get all the other Tuesdays in the month
while (d.getMonth() === month) {
tuesdays.push(new Date(d.getTime()));
d.setDate(d.getDate() + 7);
}
return tuesdays;
}
I know that this is old but this is a function that i wrote based on what Sahal wrote that accepts a few additional features. Ill go through the arguments and returns below.
function getDates(dayString, month, year, first, allInYear) {
if (!dayString) { console.error('Missing required parameter: dayString is required.'); return; }
if (first === undefined || first === null) { first = false; }
if (allInYear === undefined || allInYear === null) { allInYear = false; }
if (year === undefined || year === null) { year = new Date().getFullYear(); }
var converted = false;
if (month === undefined || month === null) {
var temp = new Date();
if (temp.getDate() > 9) {
month = ((temp.getMonth() + 1) == 12) ? 11 : (temp.getMonth() + 1);
} else {
month = temp.getMonth();
}
converted = true;
}
if (typeof month === "string" && isNaN(parseInt(month))) {
month = month.toLowerCase().substring(0, 3);
switch (month) {
case "jan":
month = 0;
break;
case "feb":
month = 1;
break;
case "mar":
month = 2;
break;
case "apr":
month = 3;
break;
case "may":
month = 4;
break;
case "jun":
month = 5;
break;
case "jul":
month = 6;
break;
case "aug":
month = 7;
break;
case "sep":
month = 8;
break;
case "oct":
month = 9;
break;
case "nov":
month = 10;
break;
case "dec":
month = 11;
break;
default:
var temp = new Date();
if (temp.getDate() > 9) {
month = ((temp.getMonth() + 1) == 12) ? 11 : (temp.getMonth() + 1);
} else {
month = temp.getMonth();
}
converted = true;
break;
}
} else if (typeof month === "number" || (typeof month === "string" && !isNaN(parseInt(month)))) {
month = (!converted) ? parseInt(month) - 1 : month;
}
if (typeof year === "string" && !isNaN(parseInt(year)) || typeof year === "number") {
if (parseInt(year) / 1000 > 2) {
year = parseInt(year);
} else if (parseInt(year) / 10 >= 0 && parseInt(year) / 10 < 10) {
var temp2 = new Date().getFullYear();
year = (parseInt(Math.floor(temp2 / 100)) * 100) + parseInt(year);
}
} else if (typeof year === "string" && isNaN(parseInt(year))) {
if (year === "this") {
year = new Date().getFullYear();
} else if (year === "last") {
year = new Date().getFullYear() - 1;
} else if (year === "next") {
year = new Date().getFullYear() + 1;
} else {
console.warn('Year string not recognized, falling back to current year. (this, last, next).');
year = new Date().getFullYear();
}
}
var dates = [];
//hang in there this is going to get a doosie
var d = new Date(),
dow = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"],
getDow = function(sd, dowa) {
for (var i = 0; i < dowa.length; i++) {
var day = dowa[i];
if (sd.toLowerCase().substring(0, 3) == day) {
return i;
}
}
return -1;
},
di = getDow(dayString, dow),
getDIM = function(year, mon) {
var isLeap = ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0));
return [31, (isLeap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][mon];
};
d.setFullYear(year);
d.setMonth(month, 1);
if (di == -1) { console.error('Range Error: Day of the week should be between sunday and saturday'); return; }
if (first && !allInYear) {
while (d.getDay() !== di) {
d.setDate(d.getDate() + 1);
}
return d;
} else if (first && allInYear) {
var tm = 0;
d.setMonth(tm, 1);
for (var i = tm; i <= 11; i++) {
while (d.getDay() !== di) {
d.setDate(d.getDate() + 1);
}
dates.push(new Date(d));
tm += 1;
d.setMonth(tm, 1);
}
return dates;
} else if (!first && !allInYear) {
var eom = getDIM(d.getFullYear(), d.getMonth());
for (var x = 1; x <= eom; x++) {
if (d.getDay() === di) {
dates.push(new Date(d));
}
d.setDate(d.getDate() + 1);
}
return dates;
} else if (!first && allInYear) {
var tm = 0;
for (var i = 0; i <= 11; i++) {
var eom = getDIM(d.getFullYear(), i),
dim = [];
d.setMonth(i, 1);
for (var x = 1; x <= eom && d.getMonth() == i; x++) {
if (d.getDay() === di) {
dim.push(new Date(d));
}
d.setDate(d.getDate() + 1);
}
dates.push(dim);
}
return dates;
} else {
return [];
}
}
So the only required argument is the day string, optionally you can set month,year,first or all in a month and all in a year or not, month and year default to current, and first and allInYear default to false, But you can set first in moth, by passing null or undefined to the month and year parameter.
month parameter accepts: null|undefined, number, or string eg 'July'
year parameter accepts: null|undefined, number 2 or 4 digit, string eg '19' or '2019' also 'last', 'this', 'next'
returns Date object,Array[Date object...], or Array[Array[Date object...]...]
This has been tested and should cover most situations...
Well, it's been over 8 years since I asked this question, and it showed up at the top result on Google for 'The first Tuesday of every month'. The original project is dead now, but I've gained more experience, I feel better placed to provide an answer.
First thing to note, is the original question wasn't obvious, and the title was just as ambiguous. The original goal, was to get the next occurrence of a first Tuesday of the month, so could be the current month, or next month depending on where you are in the month.
Because of the ambiguity in the question, I have tried to cover for those differences in interpretation in the answer.
My first function, is to get the occurrence of a specific day of the week for a given month and year. Thank you to #Amadan in the comments on one of the answers.
function GetFirstDayOfMonth(dayOfTheWeek, month, year){
const date = new Date(year, month, 1);
date.setDate(date.getDate() + ((7 + dayOfTheWeek) - date.getDay()) % 7)
return date;
}
The next function, gets the next occurrence of a first specified day of the week given a date.
function GetFirstNextFirstDayOfTheWeek(currentDate, day){
const returnValue = GetFirstDayOfMonth(day, currentDate.getMonth(), currentDate.getFullYear());
if(returnValue.getDate() < currentDate.getDate()){
return GetFirstNextFirstDayOfTheWeek(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1), day);
}
return returnValue;
}
So to achieve the original question I can run the following example
const tuesday = 2;
function GetFirstNextFirstTuesday(){
return GetFirstNextFirstDayOfTheWeek(new Date(), tuesday);
}
To achieve getting the first Tuesday of a Month
const tuesday = 2;
function GetFirstTuesday(month, year){
return GetFirstDayOfMonth(tuesday, month, year);
}
And to finish getting all the first Tuesdays of a given year.
const tuesday = 2;
function GetFirstTuesdayOfEveryMonth(year){
const dates = [];
for (let index = 0; index < 12; index++) {
dates.push(GetFirstDayOfMonth(tuesday, index, year));
}
return dates;
}
function GetFirstDayOfMonth(dayOfTheWeek, month, year){
// Get the first day of the month
const date = new Date(year, month, 1);
// Set the date based on the day of the week.
date.setDate(date.getDate() + ((7 + dayOfTheWeek) - date.getDay()) % 7)
return date;
}
function GetFirstNextFirstDayOfTheWeek(currentDate, day){
const returnValue = GetFirstDayOfMonth(day, currentDate.getMonth(), currentDate.getFullYear());
if(returnValue.getDate() < currentDate.getDate()){
return GetFirstNextFirstDayOfTheWeek(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1), day);
}
return returnValue;
}
const tuesday = 2;
function GetFirstTuesday(month, year){
return GetFirstDayOfMonth(tuesday, month, year);
}
function GetFirstNextFirstTuesday(){
return GetFirstNextFirstDayOfTheWeek(new Date(), tuesday);
}
function GetFirstTuesdayOfEveryMonth(year){
const dates = [];
for (let index = 0; index < 12; index++) {
dates.push(GetFirstDayOfMonth(tuesday, index, year));
}
return dates;
}
console.log(GetFirstNextFirstTuesday());
console.log(GetFirstTuesday(09, 2021));
console.log(GetFirstTuesdayOfEveryMonth(2022));
Hopefully, this can help anyone who may seem to stubble on this old post, and thank you to the people that did answer.
I have an date, i need to add no. of days to get future date but weekends should be excluded.
i.e
input date = "9-DEC-2011";
No. of days to add = '13';
next date should be "28-Dec-2011"
Here weekends(sat/sun) are not counted.
Try this
var startDate = "9-DEC-2011";
startDate = new Date(startDate.replace(/-/g, "/"));
var endDate = "", noOfDaysToAdd = 13, count = 0;
while(count < noOfDaysToAdd){
endDate = new Date(startDate.setDate(startDate.getDate() + 1));
if(endDate.getDay() != 0 && endDate.getDay() != 6){
//Date.getDay() gives weekday starting from 0(Sunday) to 6(Saturday)
count++;
}
}
alert(endDate);//You can format this date as per your requirement
Working Demo
#ShankarSangoli
Here's a newer version which avoid recreating a Date object on each loop, note that it's wrapped in a function now.
function calcWorkingDays(fromDate, days) {
var count = 0;
while (count < days) {
fromDate.setDate(fromDate.getDate() + 1);
if (fromDate.getDay() != 0 && fromDate.getDay() != 6) // Skip weekends
count++;
}
return fromDate;
}
alert(calcWorkingDays(new Date("9/DEC/2011"), 13));
Here is an elegant solution without any looping or external library:
function addBusinessDaysToDate(date, days) {
var day = date.getDay();
date = new Date(date.getTime());
date.setDate(date.getDate() + days + (day === 6 ? 2 : +!day) + (Math.floor((days - 1 + (day % 6 || 1)) / 5) * 2));
return date;
}
var date = "9-DEC-2011";
var newDate = addBusinessDaysToDate(new Date(date.replace(/-/g, "/")), 13);
console.log(newDate.toString().replace(/\S+\s(\S+)\s(\d+)\s(\d+)\s.*/, '$2-$1-$3')); // alerts "28-Dec-2011"
or you can be like this
function addWeekdays(date, weekdays) {
var newDate = new Date(date.getTime());
var i = 0;
while (i < weekdays) {
newDate.setDate(newDate.getDate() + 1);
var day = newDate.getDay();
if (day > 1 && day < 7) {
i++;
}
}
return newDate;
}
var currentDate = new Date('10/31/2014');
var targetDate = addWeekdays(currentDate, 45);
alert(targetDate);
Using moment.js:
const DATE_FORMAT = 'D-MMM-YYYY';
const SUNDAY = 0; // moment day index
const SATURDAY = 6; // moment day index
const WEEKENDS = [SATURDAY, SUNDAY];
function addBusinessDays(stringDate, numberOfDays, dateFormat = DATE_FORMAT) {
const date = moment(stringDate, dateFormat);
let count = 0;
while (count < numberOfDays) {
date.add(1, 'day');
// Skip weekends
if (WEEKENDS.includes(date.day())) {
continue;
}
// Increment count
count++;
}
return date.format(dateFormat);
}
// Test cases
console.log(addBusinessDays('3-Mar-2021', 1)); // 4-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 2)); // 5-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 3)); // 8-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 4)); // 9-Mar-2021
console.log(addBusinessDays('3-Mar-2021', 5)); // 10-Mar-2021
console.log(addBusinessDays('9-Dec-2011', 13)); // 28-Dec-2011
console.log(addBusinessDays('10-Dec-2011', 13)); // 28-Dec-2011 (Saturday, so remain on Friday)
console.log(addBusinessDays('11-Dec-2011', 13)); // 28-Dec-2011 (Sunday, so remain on Friday)
console.log(addBusinessDays('12-Dec-2011', 13)); // 29-Dec-2011
console.log(addBusinessDays('13-Dec-2011', 13)); // 30-Dec-2011
console.log(addBusinessDays('14-Dec-2011', 13)); // 2-Jan-2012
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
This question is quite old, but all the previous answers are iterating over the days one by one. That could be inefficient for a large number of days. This works for me, assuming days is a positive int and the startDate is a working day:
function addWorkingDates(startDate, days) {
const current_day = startDate.getDay() - 1; // Week day, starting on Monday
const weekend_days = 2 * parseInt((current_day + days) / 5);
startDate.setDate(changed_to.getDate() + days + weekend_days);
}
addWorkingDates(new Date(),5)
For some reason it was more intuitive to me to try this recursively. This version doesn't account for holidays, but you could change the isValid function to check whatever.
function addWeekdaysToDate(date, numberToAdd) {
var isValid = function(d) { return d.getDay() !== 0 && d.getDay() !== 6 }
if(Math.abs(numberToAdd) > 1) {
return addWeekdaysToDate(
addWeekdaysToDate(date, Math.sign(numberToAdd)),
numberToAdd - Math.sign(numberToAdd)
)
} else if(Math.abs(numberToAdd) === 1) {
var result = new Date(date)
result.setDate(result.getDate() + Math.sign(numberToAdd))
if(isValid(result)) {
return result
} else {
return addWeekdaysToDate(result, Math.sign(numberToAdd))
}
} else if(numberToAdd === 0) {
return date
}
return false
}
console.log(addWeekdaysToDate(new Date(), 1))
console.log(addWeekdaysToDate(new Date(), 5))
console.log(addWeekdaysToDate(new Date(), -7))
In certain browsers you may need a polyfill for Math.sign:
Math.sign = Math.sign || function(x) {
x = +x; // convert to a number
if (x === 0 || isNaN(x)) {
return Number(x);
}
return x > 0 ? 1 : -1;
}
try this solution
<script language="javascript">
function getDateExcludeWeekends(startDay, startMonth, startYear, daysToAdd) {
var sdate = new Date();
var edate = new Date();
var dayMilliseconds = 1000 * 60 * 60 * 24;
sdate.setFullYear(startYear,startMonth,startDay);
edate.setFullYear(startYear,startMonth,startDay+daysToAdd);
var weekendDays = 0;
while (sdate <= edate) {
var day = sdate.getDay()
if (day == 0 || day == 6) {
weekendDays++;
}
sdate = new Date(+sdate + dayMilliseconds);
}
sdate.setFullYear(startYear,startMonth,startDay + weekendDays+daysToAdd);
return sdate;
}
</script>
If you want to get the next working day, from a specific date, use the following code...
function getNextWorkingDay(originalDate) {
var nextWorkingDayFound = false;
var nextWorkingDate = new Date();
var dateCounter = 1;
while (!nextWorkingDayFound) {
nextWorkingDate.setDate(originalDate.getDate() + dateCounter);
dateCounter++;
if (!isDateOnWeekend(nextWorkingDate)) {
nextWorkingDayFound = true;
}
}
return nextWorkingDate;
}
function isDateOnWeekend(date) {
if (date.getDay() === 6 || date.getDay() === 0)
return true;
else
return false;
}
Try this
function calculate() {
var noOfDaysToAdd = 13;
var startDate = "9-DEC-2011";
startDate = new Date(startDate.replace(/-/g, "/"));
var endDate = "";
count = 0;
while (count < noOfDaysToAdd) {
endDate = new Date(startDate.setDate(startDate.getDate() + 1));
if (endDate.getDay() != 0 && endDate.getDay() != 6) {
count++;
}
}
document.getElementById("result").innerHTML = endDate;
}
<div>
Date of book delivery: <span id="result"></span><br /><br />
<input type="button" onclick="calculate();" value="Calculate" />
<br>
<br>
</div>