Approaching O(1) (without init time)
If you really want an O(1) solution, I hope you do not take into account the initialization fase.
To initialize:
- Build sorted list of all dates in queryable range that are valid return values. (using something like the code in the answer from Rik Garner)
- Build hashtable with dates from the above list, with the date as key, index in the list as value
The initialization code, you need only once, and you cache the result.
To query/calculate
List<DateTime> validWorkdays = // ;
Dictionary<DateTime, int> lookupIndexOfValidWorkday = // ;
DateTime AddWorkdays(DateTime start, int count) {
var startIndex = lookupIndexOfValidWorkday[start];
return validWorkDays[startIndex + count];
}
Concerning the retrieve from the dictionary:
Getting or setting the value of this property approaches an O(1) operation.
O(n) on number of holidays
Under the assumption that the list of holidays is sorted from oldest to newest. (Credits for weekdays formula)
DateTime AddBusinessDay(DateTime start, int count, IEnumerable<DateTime> holidays) {
int daysToAdd = count + ((count/ 5) * 2) + ((((int)start.DayOfWeek + (count % 5)) >= 5) ? 2 : 0);
var end = start.AddDays(daysToAdd);
foreach(var dt in holidays) {
if (dt >= start && dt <= end) {
end = end.AddDays(1);
if (end.DayOfWeek == DayOfWeek.Saterday) {
end = end.AddDays(2);
}
}
}
return end;
}
This method can be optimized.
It's very hard to create a simple formula that just calculates the result, like the answers in the question you linked to. Because when you adjust for holidays you need to take into account new holidays that might fall into your range. For weekends, you know there is a fixed interval between them.