I have the following algorithm to calculate certain ratios of "work", "low work" and "no work" over a set date range (startDate
, endDate
). The algorithm works fine, but when I increase the date range it obviously runs slower because it has to loop over every day of that range for every minute. Is there a way to improve the performance with a different kind of loop or for the where clause to find the current date within the listWorkTime
.
private List<DateSharedWork> CalculateDateSharedWork(DateTime startDate, DateTime endDate, ICollection<WorkTime> listWorkTime)
{
List<DateSharedWork> listDateSharedWork = new List<DateSharedWork>();
// +1 to include last day at full
int range = endDate.Subtract(startDate).Days + 1;
// start at startDate
Parallel.For(0, range, i =>
{
DateTime currDate = startDate.AddDays(i);
//set minute interval
double everyNMinutes = 1.0;
double minutesADay = 1440.0;
// reset counter
int work_counter = 0;
int lowWork_counter = 0;
int noWork_counter = 0;
int l = (int)(minutesADay / everyNMinutes);
for (int j = 0; j < l; j++)
{
DateTime check15 = currDate.AddMinutes(j * everyNMinutes);
// check if listWorkTime includes current date
var foundTime = listWorkTime.Where(x => check15 >= x.FromDate && check15 <= x.ToDate).ToList();
if (foundTime.Count(x => x.TimeRangeId == 1) > 0)
{
// found interval that is within work hours
work_counter++;
noWork_counter++;
}
else
{
if (foundTime.Count(x => x.TimeRangeId == 2) > 0)
{
// found intervall that is within low work hours
lowWork_counter++;
noWork_counter++;
}
}
};
double work = everyNMinutes / minutesADay * work_counter;
double lowWork = everyNMinutes / minutesADay * lowWork_counter;
double noWork = 1.0 - (everyNMinutes / minutesADay * noWork_counter);
listDateSharedWork.Add(new DateSharedWork(currDate, work, lowWork, noWork));
});
listDateSharedWork.Sort((x, y) => DateTime.Compare(x.Date, y.Date));
return listDateSharedWork;
}
Edit
class definitions of DateSharedWork and WorkTime
public class DateSharedWork
{
public DateSharedWork(DateTime date, double? work = 0.0, double? lowWork = 0.0, double? noWork = 1.0)
{
this.Date = date;
this.Work = work.Value;
this.LowWork = lowWork.Value;
this.NoWork = noWork.Value;
}
public DateTime Date { get; private set; }
public double Work { get; private set; }
public double LowWork { get; private set; }
public double NoWork { get; private set; }
}
public class WorkTime
{
public int Id { get; set; }
public DateTime? FromDate{ get; set; }
public DateTime? ToDate{ get; set; }
public int? TimeRangeId{ get; set; }
}
Edit2
starting from the startDate
value as the first day and increasing on a minute scale for a the whole day, I get the ratios of normal work and low work for that day by the flag TimeRangeId
,
listWorkTime
contains information when a certain period was either work or low work, these periods can overlap and also beeing a duplicate, but normal work (TimeRangeId == 1
) dominates
WorkTime
andDateSharedWork
? \$\endgroup\$WorkTime
entries) is the performance becoming unreasonable by your standards? How long does it then take? How long are you expecting it to take? If not a hard line, how much are you willing to sacrifice readability/maintainability for squeezed performance? \$\endgroup\$