Мой совет - создать класс Appointment, который имеет TimeFrame. TimeFrame имеет StartTime / EndTime / Duration:
interface ITimeFrame
{
DateTime StartTime {get;}
DateTime EndTime {get;}
TimeSpan Duration {get;}
}
Возможные реализации:
class TimeFrame : ITimeFrame
{
public DateTime StartTime {get; set;}
public DateTime EndTime {get; set;}
public TimeSpan Duration => EndTime - StartTime;
}
Но вы также можете выбрать реализацию, где EndTime => StartTime + Duration
interface AppointMent
{
int Id {get; }
IReadOnlyCollection<Person> Attendees {get;}
ITimeFrame TimeFrame {get; }
}
Вы хотите знать, перекрываются ли два Назначения. Я создаю его как методы расширения ITimeFrame и IAppointment:
public static bool Overlaps(this ITimeFrame timeFrameA, ITimeFrame timeFrameB)
{
// assuming startTime of a TimeFrame is always smaller than EndTime
// there is an overlap if
// frameA starts before frameB ends AND frameA ends after frameB starts
return timeFrameA.StartTime < timeFrameB.EndTime
&& timeFrameA.EndTime > timeFrame.StartTime;
}
public static bool Overlaps(this IAppointment appointmentA, IAppontment appointmentB)
{
return appointmentA.TimeFrame.Overlaps(appointmentB.TimeFrame);
}
Использование:
IAppointment a = ...
IAppointment b = ...
bool overlaps = a.Overlaps(b);
Для LINQ мы делаем то же самое с последовательностями:
public static bool Overlaps(
this IEnumerable<IAppointment> appointments,
IAppointment otherAppointment)
{
return appointments.Where(appointment => appointment.Overlaps(otherAppointment)).Any();
}
Использование :
IEnumerable<IAppointment> existingAppointment = ...
IAppointment requestedAppointment = ...
var hasOverlappingAppointments = existingAppointment
.Overlaps(requestedAppointment)
.Any();
if (hasOverlappingAppointments)
{
WriteMessage("Can't make this appointment, it overlaps with existing appointments");
}
else
{
AcceptAppointment(requestedAppointment);
}