I need to get working hours (8 hours) in date range excluding weekends and holidays, and my code below works fine with excluding weekends, but I can’t wrap my head around how to make it work with holidays as well.
This is quite brute force-ish approach and freezes the tab on execution, ideally I’d want to make the year dynamic or even just only check the month and the day ignoring the year.
Another thing I will have to consider after solving this issue is what to do if the weekend and the holiday are on the same day. Usually in our country if that is the case the government will “postpone” the holiday, for example:
Holidays are on sunday and saturday, then the next week’s monday and tuesday are going to be work free days.
Or sometimes if the holiday on wednesday, then it will be postponed to friday, so people can have 3 weekend days consecutively.
function workingHoursBetweenDates(startDate : Date, endDate : Date, dayStart : number, dayEnd : number, includeWeekends : boolean) {
// Store minutes worked
var minutesWorked = 0;
// Validate input
if (endDate < startDate) { return 0; }
// Loop from your Start to End dates (by hour)
var current = startDate;
// Define work range
var workHoursStart = dayStart;
var workHoursEnd = dayEnd;
// Loop while currentDate is less than end Date (by minutes)
var holidays = ['2021-01-01', '2021-01-02', '2021-03-08', '2021-03-21', '2021-03-22', '2021-03-23',
'2021-05-01', '2021-05-07', '2021-05-09', '2021-07-06', '2021-08-30', '2021-12-01', '2021-12-16', '2021-12-17']
while(current <= endDate) {
// Store the current time (with minutes adjusted)
var currentTime = current.getHours() + (current.getMinutes() / 60);
// Is the current time within a work day (and if it
// occurs on a weekend or not)
for (var i = 0; i < holidays.length; i++) {
var tempDate1 = new Date(current.setHours(0, 0, 0, 0));
var tempDate = (new Date(holidays[i]));
var tempDate2 = new Date(tempDate.setHours(0, 0, 0, 0));
cd.console! += tempDate1.getTime() + 'n';
cd.console! += tempDate2.getTime() + 'n';
if (currentTime >= workHoursStart && currentTime < workHoursEnd
&& (includeWeekends ? current.getDay() !== 0
&& current.getDay() !== 6
&& tempDate1.getTime() === tempDate2.getTime() : true)) {
minutesWorked++;
}
// Increment current time
}
current.setTime(current.getTime() + 1000 * 60);
}
// Return the number of hours
return (minutesWorked / 60).toFixed(2);
}
I thought perhaps an abomination like this could work, putting this in an if statement:
(current.getMonth() !== 0 && current.getDate() !== 1)
&& (current.getMonth() !== 0 && current.getDate() !== 2)
/*Many many rows of the month and the day of the holiday*/
&& (current.getMonth() !== 11 && current.getDate() !== 17)
That didn’t work as well.