werlox
werlox

Reputation: 63

Get next day, skip weekends

I want to generate next working day using JavaScript.

This is my code as of now

var today = new Date();
    today.setDate(today.getDate());
    var tdd = today.getDate();
    var tmm = today.getMonth()+1;
    var tyyyy = today.getYear();

    var date = new Date();

    date.setDate(date.getDate()+3);

Problem is, on Fridays it returns Saturday's date whereas I want it to be Monday

Upvotes: 6

Views: 13782

Answers (6)

Jônathan
Jônathan

Reputation: 11

Attempting in two lines:

do date.setDate(date.getDate() + 1);
while ([0, 6].includes(date.getDay()));

Upvotes: 1

mplungjan
mplungjan

Reputation: 177685

This will choose the next working day when a date is passed to it.

I suggest you normalise the date you pass, so you will not be surprised around summertime/wintertime change

Updated in 2023

// update and return passed date object to next working day
const getNextWork = date => {
  let day = date.getDay(), add = 1;
  if (day === 6)           add = 2; else 
  if (day === 5)           add = 3;
  date.setDate(date.getDate() + add); // will correctly handle 31+1 > 32 > 1st next month
  return date;
};


// tests:
const dt = new Intl.DateTimeFormat("en-US", {
  weekday: "short",
  year: "numeric",
  month: "long",
  day: "numeric",
  timeZone: "UTC",
  timeZoneName: "short",
  hour: "numeric",
  minute: "numeric",
});
const aDay = 24 * 60 * 60 * 1000;
// 26th of March 2023 is daylight savings date in my country
let date = new Date(2023, 2, 24, 15, 0, 0, 0).getTime();

for (let i = 0; i < 7; i++) {
  const d = new Date(date + i * aDay);
  console.log(dt.format(d), "-->", dt.format(getNextWork(d)));
}

If you do not want to update the passed date object have this instead

// find next working day and return a new date for that date
const getNewNextWork = date => {
  const dateCopy = new Date(date);
  let day = dateCopy.getDay(), add = 1;
  if (day === 6)           add = 2; else 
  if (day === 5)           add = 3;
  dateCopy.setDate(dateCopy.getDate() + add); // Modifying the copy, not the original date
  return dateCopy;
};

Older code:

var today = new Date(2016, 7, 26,12,0,0,0,0); // Friday at noon
console.log("today, Monday",today,"day #"+today.getDay());
var next = new Date(today.getTime());
next.setDate(next.getDate()+1); // tomorrow
while (next.getDay() == 6 || next.getDay() == 0) next.setDate(next.getDate() + 1);
console.log("no change    ",next,"day #"+next.getDay());
console.log("-------");
// or without a loop:

function getNextWork(d) {
  d.setDate(d.getDate()+1); // tomorrow
  if (d.getDay()==0) d.setDate(d.getDate()+1);
  else if (d.getDay()==6) d.setDate(d.getDate()+2);
  return d;
}
next = getNextWork(today); // Friday
console.log("today, Friday",today);
console.log("next, Monday ",next);
console.log("-------");
today = new Date(2016, 7, 29,12,0,0,0); // Monday at noon
next = getNextWork(today);              // Still Monday at noon
console.log("today, Monday",today);
console.log("no change    ",next);
console.log("-------");

// Implementing Rob's comment

function getNextWork1(d) {
  var day = d.getDay(),add=1;
  if (day===5) add=3;
  else if (day===6) add=2;
  d.setDate(d.getDate()+add);  
  return d;
}
today = new Date(2016, 7, 26,12,0,0,0,0); // Friday at noon
next = getNextWork1(today);               // Friday
console.log("today, Friday",today);
console.log("next, Monday ",next);
console.log("-------");
today = new Date(2016, 7, 26,12,0,0,0,0); // Monday at noon
next = getNextWork1(today); // Monday
console.log("today, Monday",today);
console.log("no change    ",next);

Upvotes: 17

Reet Chowdhary
Reet Chowdhary

Reputation: 1

Thought I'd throw my hat in the ring here with:

function getNextBusinessDate(date) {
  // Create date array [S, M, T, W, T, F, S]
  const days = new Array(7);
  let nextDate = date;
  for(let i = 0; i < 7; i++) {
    days[nextDate.getDay()] = new Date(nextDate);
    nextDate.setDate(nextDate.getDate() + 1);
  }

  // Shift indices to index as though array was [M, T, W, T, F, S, S]
  // Then truncate with min to make F, S, S all yield M for next date
  return days[Math.min((date.getDay() + 6) % 7 + 1, 5) % 5 + 1];
}

Upvotes: 0

RobG
RobG

Reputation: 147343

You can add 1 day at at time until you get to a day that isn't Saturday or Sunday:

function getNextBusinessDay(date) {
  // Copy date so don't affect original
  date = new Date(+date);
  // Add days until get not Sat or Sun
  do {
    date.setDate(date.getDate() + 1);
  } while (!(date.getDay() % 6))
  return date;
}

// today,    Friday 26 Aug 2016
[new Date(), new Date(2016,7,26)].forEach(function(d) {
  console.log(d.toLocaleString() + ' : ' + getNextBusinessDay(d).toLocaleString());
});

You can also test the day and add extra to get over the weekend:

// Classic Mon to Fri
function getNextWorkDay(date) {
  let d = new Date(+date);
  let day = d.getDay() || 7;
  d.setDate(d.getDate() + (day > 4? 8 - day : 1));
  return d;
}

for (let i=0, d=new Date(); i<7; i++) {
  console.log(`${d.toDateString()} -> ${getNextWorkDay(d).toDateString()}`);
  d.setDate(d.getDate() + 1);
}

Here is another approach where the work week can be specified using ECMAScript weekday numbers (Sun = 0, Mon = 1, etc.). Dates outside the range are shifted to the start of the next work week.

This is useful where the week is not the classic Mon to Fri, such as the Middle East where Sat to Wed is common or for some who might work Fri to Mon (or whatever).

function getNext(start, end, date) {
  let d = new Date(+date);
  d.setDate(d.getDate() + 1);
  let day = d.getDay();

  // Adjust end and day if necessary
  // The order of tests and adjustment is important
  if (end < start) {
    if (day <= end) {
      day += 7;
    }
    end += 7;
  }

  // If day is before start, shift to start
  if (day < start) {
    d.setDate(d.getDate() + start - day);

    // If day is after end, shift to next start (treat Sunday as 7)
  } else if (day > end) {
    d.setDate(d.getDate() + 8 - (day || 7));
  }
  return d;
}

// Examples
let f = new Intl.DateTimeFormat('en-GB', {
  weekday:'short',day:'2-digit', month:'short'});
let d = new Date();

[{c:'Work days Mon to Fri',s:1,e:5},
 {c:'Work days Sat to Wed',s:6,e:3},
 {c:'Work days Fri to Mon',s:5,e:1}
].forEach(({c,s,e}) => {
  for (let i = 0; i < 7; i++) {
    !i? console.log(`\n${c}`) : null;
    console.log(`${f.format(d)} => ${f.format(getNext(s, e, d))}`);
    d.setDate(d.getDate() + 1);
  }
});

Upvotes: 5

William Stevens
William Stevens

Reputation: 552

The accepted answer will skip one day at a time, which answers the OPs question, but for anyone looking to add a variable number of days while still skipping weekends the function below may be helpful:

function addWorkDays(date, days) {   
  while (days > 0) {
    date.setDate(date.getDate() + 1);
    if (date.getDay() != 0 && date.getDay() != 6) {
      days -= 1;
    }
  }          
  return date;
}

Upvotes: 0

Martin Gottweis
Martin Gottweis

Reputation: 2739

Check this out: https://jsfiddle.net/e9a4066r/

function get_next_weekday (date) {
    var tomorrow = new Date(date.setDate(date.getDate() + 1))
    return tomorrow.getDay() % 6
        ? tomorrow
        : get_next_weekday(tomorrow)
}

Upvotes: 0

Related Questions