我正在尝试构建一个工具,根据员工计划工作的时间和他们的请求时间来计算名为配额的内容。
我的ShiftSet对象是一组Shift对象,由StartTime和EndTime组成(类型为time(7)。每个ShiftSet对应一天。
ScheduleExceptions是员工关闭的时间。一天中可以有任意数量的重叠或不重叠的ScheduleExceptions。它们属于日期时间数据类型。
ShiftSet的一个例子:
08:00-10:00
10:00-12:00
13:00-15:00
15:00-17:00
同一天的ScheduleExceptions示例:
07:30-10:30
14:35-16:00
我需要做的是找出员工一天工作的时间。我可以想象的方法是计算ShiftSet和ScheduleExceptions的反转的交集。
我如何随着时间的推移做到这一点?如果可能的话,我更愿意使用Linq。
答案 0 :(得分:3)
答案 1 :(得分:2)
正如InBetween所提到的那样,有些库已经解决了这个问题,但它们也解决了许多相关问题。如果您只想解决这个特定问题而不采取其他依赖关系,可以尝试以下方法。
// Finds ones with absolutely no overlap
var unmodified = shifts.Where(s => !exceptions.Any(e => s.Start < e.End && s.End > e.Start));
// Finds ones entirely overlapped
var overlapped = shifts.Where(s => exceptions.Any(e => e.End >= s.End && e.Start <= s.Start));
// Adjusted shifts
var adjusted = shifts.Where(s => !unmodified.Contains(s) && !overlapped.Contains(s))
.Select(s => new Shift
{
Start = exceptions.Where(e => e.Start <= s.Start && e.End > s.Start).Any() ? exceptions.Where(e => e.Start <= s.Start && e.End > s.Start).First().End : s.Start,
End = exceptions.Where(e => e.Start < s.End && e.End >= s.End).Any() ? exceptions.Where(e => e.Start < s.End && e.End >= s.End).First().Start : s.End
});
var newShiftSet = unmodified.Union(overlapped).Union(adjusted);
这是一个基本的例子,虽然它可以被压缩(虽然不太可读)并且有所改进。
答案 2 :(得分:0)
我没有测试下面的代码,可能是有一些bug,我在textpad中写的可能是有无效字符,Idea很简单,我尝试使用有意义的变量。
var orderedShifts = ShiftSets.OrderBy(x=>x.StartDate).ToList();
var compactShifts = new List<Shift>();
compactShifts.Add(orderedShifs[0]);
foreach (var item in orderedShift)
{
if (item.Start <= compactShifts[compactShifts.Count-1].End
&& item.End > compactShifts[compactShifts.Count-1].End)
{
compactShifts[compactShifts.Count-1].End = item.End;
}
else if (item.Start > compactShifts[compactShifts.Count-1].End)
compactShifts.Add(item);
}
//run similar procedure for schedule exceptions to create compact schedules.
var validShifts = new List<Shift>();
foreach (var item in compactShifts)
{
var shiftCheatingPart = compactExceptions
.FirstOrDefault(x=>x.Start < item.Start
&& x.End > item.End)
if (shiftCheatingPart != null)
{
if (item.End <= shiftCheatingPart.End)
continue;
validShifts.Add(new Shift{Start = shiftCheatingPart.End,End = item.End);
}
}
var totalTimes = validShifts.Sum(x=>x.End.Sunbtract(x.Start).TotalHours);
答案 3 :(得分:0)
非常粗略的解决方案就像是
void Main()
{
var workTime = new List<ShiftSet> {
new ShiftSet{StartTime= new TimeSpan(8,0,0),EndTime= new TimeSpan(10,0,0)},
new ShiftSet{StartTime= new TimeSpan(10,0,0),EndTime= new TimeSpan(12,0,0)},
new ShiftSet{StartTime= new TimeSpan(13,0,0),EndTime= new TimeSpan(15,0,0)},
new ShiftSet{StartTime= new TimeSpan(15,0,0),EndTime= new TimeSpan(17,0,0)}
};
var missingTime= new List<ShiftSet> {
new ShiftSet{StartTime= new TimeSpan(7,30,0),EndTime= new TimeSpan(10,30,0)},
new ShiftSet{StartTime= new TimeSpan(14,35,0),EndTime= new TimeSpan(16,0,0)}
};
Console.WriteLine(workTime.Sum(p=>p.Shift()) - missingTime.Sum(p=>p.Shift()));
}
public class ShiftSet
{
public TimeSpan StartTime {get;set;}
public TimeSpan EndTime {get;set;}
public double Shift() {return (EndTime-StartTime).TotalMinutes;}
}
我用分钟计算一个工作时间,所以我可以使用linq
更容易地求和我也缺少我认为不属于ShiftSet
类
Because the employee is not scheduled to work from 7:30 to 8:00, we would not include that time