Я бы посоветовал вам немного изменить представление времени, чтобы иметь свойство 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 равен нулю, то в начале интервала перекрытия нет. То же самое для endOverlap.
Если startOverlap == endOverlap, то новый интервал полностью связан внутри уже существующего интервала.
Я определил StartTime как тип DateTime, хотя меня интересует только часть времени, вы можете изменить это, если хотите, чтобы два поля назывались Hour и Minute или, возможно, одно единственное поле, которое представляет начальную минуту в неделя интервала.
EDIT
Как я уже упоминал в своем комментарии, я понял, что новый временной интервал может перекрывать несколько уже определенных интервалов. Например, если обычно операция идет с 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