FUNCTION
workDay
Computes the working date from the specified date plus or minus \a days - excluding holidays. <span align="right" style="background-color:99FF99"><strong>Excel: WORKDAY</strong></span>
Interface
#include <codecogs/units/date/workday.h>
using namespace Units::Date;
Calculates the next work day that is a number days from nDate. holidays and weekends are assumed not to be workdays and are excluded.
If days is set to zero then this function will simply return nDate regardless of weather is lies on a holiday (or weekend). This functionality may seem strange, however, without some directional bias, it is impossible to know if you should move forward to Monday or backward to Friday. This emulates Excel's interpretation of the function.
In solving this problem you could iterate through each day until you had counted a sufficient number of workable days. For example:
while(days>0)
{
int h;
for(h=0;h<holidays && holidayDates[h]!=nDate;h++); // check against holiday list
if(h==holidays) days--; // only decrement if not a holiday
nDate=nextWeekDay(nDate); // find next week day
}This approach is applied by certain spreadsheet applications we emulate, unfortunately the time taken by this function scales linearly with size of days. We have opted for a constant time method, which although more involved, works in the following fashion:
s=daysOfWeek(nDate)
nDate-= s; // move to beginning of current week.
...
days+=s;
nDate+= (days/5) * 7; // add whole weeks
nDate+= d%5; // add remainder within weekWe then count the number of holidays within this new date range, and advance forward using the slow method shown above (in C++). However, the majority of the work has been done by this point - so the overall scheme is far faster.
Example 1
workDay(date("1 jan 5"), 0); // returns Saturday 1 January 2005
workDay(date("1 jan 5"), 1); // returns Monday 3 January 2005
workDay(date("1 jan 5"), 1, 1); // returns Tuesday 4 January 2005 (Monday is assumed a holiday)
workDay(date("1 jan 5"), 2); // returns Monday 3 January 2005A more detailed example that catches holidays around Christmas and New year:
#include <stdio.h>
#include <codecogs/units/date/workday.h>
#include <codecogs/units/date/dateymd.h>
#include <codecogs/units/date/date.h>
#include <codecogs/units/date/nextweekday.h>
using namespace Units::Date;
void main()
{
int holidays[3];
holidays[0]=date(2005, 1, 1); // New years day
holidays[1]=date(2004,12,25); // Christmas day
holidays[2]=nextWeekDay(holidays[2]); // Boxing day or first weekday after Christmas
printf("\n StartDate days newDate");
int startdate=date("1 jan 2005");
for(int i=-50;i<50;i+=10)
{
int d,m,y;
dateYMD(startdate,y,m,d);
printf("\n %2d-%2d-%d",d,m,y);
dateYMD(workDay(startdate, i, 3, holidays),y,m,d);
printf(" %2d %2d-%2d-%d", i, d,m,y);
}
}Output:
StartDate days newDate
1- 1-2005 -50 22-10-2004
1- 1-2005 -40 5-11-2004
1- 1-2005 -30 19-11-2004
1- 1-2005 -20 3-12-2004
1- 1-2005 -10 17-12-2004
1- 1-2005 0 1- 1-2005
1- 1-2005 10 14- 1-2005
1- 1-2005 20 28- 1-2005
1- 1-2005 30 11- 2-2005
1- 1-2005 40 1- 3-2005