Давайте начнем с одного value
private static bool WithinSpan(DateTime value, TimeSpan from, TimeSpan to) =>
value >= value.Date.Add(from) && value <= value.Date.Add(to);
Теперь мы можем реализовать то же самое с двумя value
с:
private static bool WithinSpan(DateTime startDate, DateTime endDate,
TimeSpan from, TimeSpan to) =>
// startDate <= endDate && // you may want to add this condition as well
startDate >= startDate.Date.Add(from) && startDate <= startDate.Date.Add(to) &&
endDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);
Демонстрация:
TimeSpan allowedStart = new TimeSpan(08, 00, 0);
TimeSpan allowedEnd = new TimeSpan(20, 00, 0);
(DateTime, DateTime)[] tests = new (DateTime, DateTime)[] {
(new DateTime(2020, 1, 30, 19, 10, 0), new DateTime(2020, 1, 30, 19, 20, 0)),
(new DateTime(2020, 1, 30, 19, 50, 0), new DateTime(2020, 1, 30, 20, 15, 0)),
(new DateTime(2020, 1, 30, 20, 10, 0), new DateTime(2020, 1, 30, 20, 35, 0)),
(new DateTime(2020, 1, 30, 23, 50, 0), new DateTime(2020, 1, 31, 0, 35, 0)),
(new DateTime(2020, 1, 31, 7, 50, 0), new DateTime(2020, 1, 31, 8, 15, 0)),
};
Func<DateTime, DateTime, string> within =
(t1, t2) => $"{(WithinSpan(t1, t2, allowedStart, allowedEnd) ? "Yes" : "No")}";
string report = string.Join(Environment.NewLine, tests
.Select(test => $"{test.Item1:yyyy-MM-dd HH:mm:ss} .. {test.Item2:yyyy-MM-dd HH:mm:ss} : {within(test.Item1, test.Item2)}"));
Console.Write(report);
Результат:
2020-01-30 19:10:00 .. 2020-01-30 19:20:00 : Yes
2020-01-30 19:50:00 .. 2020-01-30 20:15:00 : No
2020-01-30 20:10:00 .. 2020-01-30 20:35:00 : No
2020-01-30 23:50:00 .. 2020-01-31 00:35:00 : No
2020-01-31 07:50:00 .. 2020-01-31 08:15:00 : No
Редактировать:
Разработанная версия
private static bool WithinSpan(DateTime startDate, DateTime endDate,
TimeSpan from, TimeSpan to) {
// Empty Period
if (startDate > endDate)
return false;
// [from..to] within single day
if (to >= from)
return startDate >= startDate.Date.Add(from) && startDate <= startDate.Date.Add(to) &&
endDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);
// [from..midnight..to]
if (startDate.Day == endDate.Day)
return startDate >= startDate.Date.Add(from) || endDate <= endDate.Date.Add(to);
else {
to = to.Add(TimeSpan.FromDays(1));
return startDate >= startDate.Date.Add(from) && startDate <= startDate.Date.Add(to) &&
endDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);
}
}
который удаляет пустые периоды и обрабатывает from > to
TimeSpan
как содержащий полночь.
Демонстрация:
// from 22:00 to midnight and then up to 06:00
TimeSpan allowedStart = new TimeSpan(22, 00, 00);
TimeSpan allowedEnd = new TimeSpan(06, 00, 00);
(DateTime, DateTime)[] tests = new (DateTime, DateTime)[] {
(new DateTime(2020, 1, 30, 19, 10, 0), new DateTime(2020, 1, 30, 19, 20, 0)),
(new DateTime(2020, 1, 30, 19, 50, 0), new DateTime(2020, 1, 30, 20, 15, 0)),
(new DateTime(2020, 1, 30, 20, 10, 0), new DateTime(2020, 1, 30, 20, 35, 0)),
(new DateTime(2020, 1, 30, 23, 50, 0), new DateTime(2020, 1, 31, 0, 35, 0)),
(new DateTime(2020, 1, 30, 23, 00, 0), new DateTime(2020, 1, 30, 23, 35, 0)),
(new DateTime(2020, 1, 30, 3, 00, 0), new DateTime(2020, 1, 30, 4, 00, 0)),
(new DateTime(2020, 1, 31, 4, 50, 0), new DateTime(2020, 1, 31, 8, 15, 0)),
};
Func<DateTime, DateTime, string> within =
(t1, t2) => $"{(WithinSpan(t1, t2, allowedStart, allowedEnd) ? "Yes" : "No")}";
string report = string.Join(Environment.NewLine, tests
.Select(test => $"{test.Item1:yyyy-MM-dd HH:mm:ss} .. {test.Item2:yyyy-MM-dd HH:mm:ss} : {within(test.Item1, test.Item2)}"));
Console.Write(report);
Результат:
2020-01-30 19:10:00 .. 2020-01-30 19:20:00 : No
2020-01-30 19:50:00 .. 2020-01-30 20:15:00 : No
2020-01-30 20:10:00 .. 2020-01-30 20:35:00 : No
2020-01-30 23:50:00 .. 2020-01-31 00:35:00 : Yes
2020-01-30 23:00:00 .. 2020-01-30 23:35:00 : Yes
2020-01-30 03:00:00 .. 2020-01-30 04:00:00 : Yes
2020-01-31 04:50:00 .. 2020-01-31 08:15:00 : No
Следующее редактирование:
Сокращенная магическая версиона:
if (startDate > endDate) {
return false;
}
if (startDate.Day == endDate.Day && to < from) {
return startDate >= startDate.Date.Add(from) || endDate <= endDate.Date.Add(to);
}
if (to < from) {
to = to.Add(TimeSpan.FromDays(1));
}
return startDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);