我有一个可用的课程
public class AvailabilityDto
{
public DateTime StartDateTime { get; set; }
public DateTime EndDateTime { get; set; }
}
我正在尝试创建一个报告,找出可用性中的差距。 给出可用性类的列表,以及在其间搜索的开始和结束日期。我试图在可用性中找到差距
这是为了看看是否有人在通常的办公时间9-5之外随叫随到。
这是我目前的实施,效率非常低,无效:
foreach(var entry in rota) {
//get all items from the list that are available out of office hours
//and order them by start time
var outOfHoursAvailibilities = entry.Availabilities
.Where(m => m.EndDateTime.Hour <= 9 || m.StartDateTime.Hour >= 17)
.OrderBy(m => m.StartDateTime)
.ToList();
var i = 0;
while (i < outOfHoursAvailibilities.Count) {
var currentStart = outOfHoursAvailibilities[i];
var next = outOfHoursAvailibilities[i + 1];
//if first ends before second starts,
if (currentStart.EndDateTime < next.StartDateTime)
{
//this means we have a gap -- until the next next one
currentStart = next;
i++;
next = outOfHoursAvailibilities[i + 1];
var missingAvailabilty = new AvailabilityDto {
StartDateTime = currentStart.EndDateTime,
EndDateTime = next.StartDateTime,
};
gaps.Add(missingAvailabilty);
}
i++;
}
}
答案 0 :(得分:0)
设置currentStart = next
时,会覆盖具有缺失可用性StartDateTime
的对象。当您实例化新AvailabilityDto
时,您将值设置为下一个可用性,而不是您找到的当前差距。我认为您不需要设置下一个当前的电流。
尝试此操作(未将next
设置为currentStart
):
if (currentStart.EndDateTime < next.StartDateTime)
{
var missingAvailabilty = new AvailabilityDto {
StartDateTime = currentStart.EndDateTime,
EndDateTime = next.StartDateTime,
};
gaps.Add(missingAvailabilty);
}
答案 1 :(得分:0)
我认为,如果您按StartDateTime
然后EndDateTime
订购可用性,只需跟踪最新结束时间,就可以轻松实现您想要的效果。如果您遇到的开始时间晚于当前最后结束时间,则表示您已找到差距。在这里,我将其作为扩展方法实现:
public static class EnumerableExtensions
{
public static IEnumerable<AvailabilityDto> FindAvailabilityGaps(this IEnumerable<AvailabilityDto> source)
{
if (source == null)
{
yield break;
}
var sorted = source.OrderBy(x => x.StartDateTime).ThenBy(x => x.EndDateTime);
using (var e = sorted.GetEnumerator())
{
if (!e.MoveNext())
{
yield break;
}
var latestEndTime = e.Current.EndDateTime;
while (e.MoveNext())
{
if (e.Current.StartDateTime > latestEndTime)
{
yield return new AvailabilityDto
{
StartDateTime = latestEndTime,
EndDateTime = e.Current.StartDateTime
};
}
if (e.Current.EndDateTime > latestEndTime)
{
latestEndTime = e.Current.EndDateTime;
}
}
}
}
}
你会这样称呼:
var outOfHoursAvailibilities =
entry
.Availabilities
.Where(m => m.EndDateTime.Hour <= 9 || m.StartDateTime.Hour >= 17)
.FindAvailabilityGaps();
我不清楚您是否在示例中使用Entity Framework或其他ORM。如果是这样,您将需要在调用扩展方法之前调用AsEnumerable
,因为LINQ提供程序将无法将FindAvailabilityGaps
转换为SQL。像这样:
var outOfHoursAvailibilities =
entry
.Availabilities
.Where(m => m.EndDateTime.Hour <= 9 || m.StartDateTime.Hour >= 17)
.AsEnumerable()
.FindAvailabilityGaps();
当然,如果您不想使用扩展方法,您可以采用上述方法的内容并以您喜欢的方式使用它。
顺便说一句,我不认为你排除办公时间的谓词会达到你想要的效果。我认为@ 5ar的评论是正确的:
m => !(m.StartDateTime.Hour >= 9 || m.EndDateTime.Hour <= 17)