我建议您对时间间隔表示稍作更改,以使用 Length 属性而不是 EndTime 属性。
class TimeInterval
{
public int Day { set; get; }
public DateTime StartTime { set; get; }
public int Length { set; get; }
}
由于我们对查找重叠间隔感兴趣,所以接下来的方法会很方便,我会将它们放在 TimeInterval 类中。
public int StartMinuteInWeek()
{
return Day * 24 * 60 + StartTime.Hour * 60 + StartTime.Minute;
}
public int EndMinuteInWeek()
{
return StartMinuteInWeek() + Length;
}
然后您只需要找到与您的新时间间隔重叠的任何 TimeInterval。您必须注意,新间隔可以扩展任何现有的间隔,甚至可以连接两个单独的间隔,或者只是包含在已定义的间隔中。
要获取在间隔开始时重叠的记录,请使用以下查询:
var startOverlap = (from rec in intervals
where rec.StartMinuteInWeek() <= timeInterval.StartMinuteInWeek() && rec.EndMinuteInWeek() >= timeInterval.StartMinuteInWeek()
select rec).FirstOrDefault();
timeInterval 是您尝试添加的新间隔。
对于末端重叠,请使用以下之一:
var endOverlap = (from rec in intervals
where rec.StartMinuteInWeek() <= timeInterval.EndMinuteInWeek() && rec.EndMinuteInWeek() >= timeInterval.EndMinuteInWeek()
select rec).FirstOrDefault();
如果 startOverlap 为 null,则间隔开始时没有重叠。 endOverlap 也是如此。
如果 startOverlap == endOverlap,则新区间完全包含在现有区间内。
我已将 StartTime 定义为 DateTime 类型,虽然我只对时间部分感兴趣,但如果您想要两个名为 Hour 和 Minute 的字段,或者可能只有一个表示开始分钟的字段,您可以更改它间隔的星期。
编辑
正如我在评论中提到的,我已经意识到一个新的时间间隔可以与几个已经定义的时间间隔重叠。例如,如果通常操作从 8:00 到 20:00 并在午餐时间停止,现在定义了一个新的时间间隔,该时间间隔贯穿整个一周 24x7,那么新的时间间隔将包含 14 个间隔。
一个安全的方法是先检测所有重叠的区间,然后调整新的区间以确保它完全包含任何重叠的区间,最后删除所有的重叠。
为了确定新间隔是否与旧间隔重叠,我将在 TimeInterval 类中定义这个方便的方法。
public bool IsInsideInterval(int minuteInWeek)
{
return minuteInWeek >= StartMinuteInWeek() &&
minuteInWeek <= EndMinuteInWeek();
}
现在我正在找出开始分钟或结束分钟的所有间隔都在新间隔内。
var overlaps = (from rec in intervals where
newInterval.IsInsideInterval(rec.StartMinuteInWeek()) ||
newInterval.IsInsideInterval(rec.EndMinuteInWeek())
select rec).ToList();
现在您必须确保新的间隔限制正常。
foreach (TimeInterval rec in overlaps)
{
if (rec.StartMinuteInWeek() < newInterval.StartMinuteInWeek())
{
newInterval.Day = rec.Day;
newInterval.StartTime = rec.StartTime;
}
if (rec.EndMinuteInWeek() > newInterval.EndMinuteInWeek())
{
// You have to calc the Length being careful to not count twice the minutes that overlaps.
newInterval.Length = newInterval.Length + rec.Length - (newInterval.EndMinuteInWeek() - rec.StartMinuteInWeek());
}
}
最后你可以删除overlaps中的所有区间,然后插入newInterval