Nishu Tayal
Nishu Tayal

Reputation: 20830

Add no. of days in a date to get next date(excluding weekends)

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.

Upvotes: 17

Views: 29829

Answers (11)

Harshit patel
Harshit patel

Reputation: 1

Function honouring weekends and also given holiday array

var startDate = "10/18/2023";
var endDate = "11/25/2023";

function isSameDate(date1, date2) {
  // Compare exact dates with miliseconds
  return date1.getTime() === date2.getTime();
}

function isWeekEnd(date) {
  //If Day of given date falls between Monday to Friday then return False
  day = date.getDay();
  if (day >= 1 && day <= 5) {
      return false;
  }
  //Else return true
  return true;
}

function isHoliday(date) {
  //List of holidays provided
  var usHolidays=["11/10/2023","11/23/2023","12/25/2023","01/02/2024","01/15/2024"];
  
  //Iterate through all holidays and check if given date falls on holiday
  for(i = 0; i < usHolidays.length; i++) {
    holiday = usHolidays[i];
    
    //Convert String to Date
    holiday = new Date(holiday);
    
    //normalize to beginning of the day 
    holiday.setHours(0,0,0,0);
    
    if (isSameDate(date, holiday)) {
      return true;
    }
  }
  return false;
}

function calculateBusinessDays(startDate, endDate) {
  // make copies we can normalize without changing passed in objects    
  var start = new Date(startDate);
  var end = new Date(endDate);

  // 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);
  
  // start from the next day
  var current = new Date(start);
  current.setDate(current.getDate() + 1);
  var day;
  // loop through each day, checking
  while (current <= end) {
      //add to business day if its not weekend or holiday
      if (!isWeekEnd(current) && !isHoliday(current)){
        ++totalBusinessDays;
      }
      //move one day forward
      current.setDate(current.getDate() + 1);
  }
  return totalBusinessDays;
}

var totalBusinessDays = calculateBusinessDays(startDate, endDate);
console.log(totalBusinessDays);

Upvotes: 0

Tejswita
Tejswita

Reputation: 1

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>

Upvotes: -1

Mois&#233;s Hiraldo
Mois&#233;s Hiraldo

Reputation: 378

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)

Upvotes: 2

Harish Ambady
Harish Ambady

Reputation: 13121

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"

Upvotes: 8

Jee Mok
Jee Mok

Reputation: 6556

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>

Upvotes: 4

Toph
Toph

Reputation: 2689

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

Upvotes: 1

Greg Quinn
Greg Quinn

Reputation: 2178

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

Upvotes: 0

lamer lamer
lamer lamer

Reputation: 345

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

Upvotes: 3

user3091762
user3091762

Reputation: 131

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

Upvotes: 13

SaQiB
SaQiB

Reputation: 639

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>

Upvotes: 0

ShankarSangoli
ShankarSangoli

Reputation: 69905

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

Upvotes: 30

Related Questions