I was searching stackoverflow to find the exact match question and response on similar problem to solve in C#.
Though I found couple of similarities on the questions available, I would not find any particular question and response on how to calculate the sla in days, hours and minutes in c# excluding the public holidays, weekends and non working hours.
For example, I've the ticket raised datetime as 21/02/2019 10:00:00 pm and if I would like to add only n (say 21 in this example) number of working hours excluding non working hours, weekends and public holidays to find the sla datetime of that ticket in C#.
Though I've some logics implemented on calculating only working hours, weekends, but finding hard to exclude the public holidays. Also appreciate the better, simple and understandable way of doing (using linq probably) than long lines of functions. Appreciate any sample code from the community.
I've got a working solution refined from other stackoverflow link as below, but this needs more refinement towards simplifying and resolving any possibilities of bugs like this scenario didn't handle if we get 2 days of holiday continuously, then calculate sla from the 3rd day, etc.
The solution I've got so far is:
public virtual DateTime AddWithinWorkingHours(DateTime start, TimeSpan offset)
{
//Get publicholidaysList from holiday table to not to include in working hour calculation
var holidaysList = _holidayManager.GetHolidays().Result;
// Don't start counting hours until start time is during working hours
if (start.TimeOfDay.TotalHours > StartHour + HoursPerDay)
start = start.Date.AddDays(1).AddHours(StartHour);
if (start.TimeOfDay.TotalHours < StartHour)
start = start.Date.AddHours(StartHour);
if (start.DayOfWeek == DayOfWeek.Saturday)
start.AddDays(2);
//if it is a Sunday or holiday date, skip that date in workinghour calc
else if (start.DayOfWeek == DayOfWeek.Sunday || holidaysList.Exists(hd=>hd.Date == start.Date))
start.AddDays(1);
// Calculate how much working time already passed on the first day
TimeSpan firstDayOffset = start.TimeOfDay.Subtract(TimeSpan.FromHours(StartHour));
// Calculate number of whole days to add
int wholeDays = (int)(offset.Add(firstDayOffset).TotalHours / HoursPerDay);
// How many hours off the specified offset does this many whole days consume?
TimeSpan wholeDaysHours = TimeSpan.FromHours(wholeDays * HoursPerDay);
// Calculate the final time of day based on the number of whole days spanned and the specified offset
TimeSpan remainder = offset - wholeDaysHours;
// How far into the week is the starting date?
int weekOffset = ((int)(start.DayOfWeek + 7) - (int)DayOfWeek.Monday) % 7;
// How many weekends are spanned?
int weekends = (int)((wholeDays + weekOffset) / 5);
// Calculate the final result using all the above calculated values
return start.AddDays(wholeDays + weekends * 2).Add(remainder);
}