Ограничение диапазона дат с нулевыми датами
Я ищу расширенный ответ на вопрос, заданный здесь:
Определите, перекрываются ли два диапазона дат
где любая из дат в любом диапазоне дат может быть нулевой. Я придумал следующее решение, но я не уверен, что его можно упростить далее.
(StartA == NULL || StartA <= EndB) &&
(EndA == NULL || EndA >= StartB) &&
(StartB == NULL || StartB <= EndA) &&
(EndB == NULL || EndB >= StartA)
Предполагая:
Диапазоны DateTime от StartA до EndA и StartB до EndB
РЕДАКТИРОВАТЬ: Извините, что я быстро переместил вышеприведенную логику, которая, похоже, терпит неудачу, когда даты начала и окончания диапазона равны NULL. См. Решение David ниже для лучшего и хорошо объясненного подхода.
Ответы
Ответ 1
Этот случай может быть обработан небольшим обобщением замечательного ответа Шарля Бретаны на этот вопрос.
Пусть CondA Mean DateRange полностью после DateRange B (True, если StartA > EndB) Пусть CondB Mean DateRange A полностью перед DateRange B (True, если EndA < StartB)
В этом случае, если вы хотите, чтобы нулевая дата представляла "никакую начальную/конечную границу", условия изменяются. Например, для CondA
, чтобы DateRange A был полностью после DateRange B, DateRange A должен иметь определенное время начала, DateRange B должен иметь определенное конечное время, а время начала A должно быть после окончания времени окончания B:
CondA := (StartA != null) && (EndB != null) && (StartA > EndB)
CondB
совпадает с включенным A и B:
CondB := (StartB != null) && (EndA != null) && (StartB > EndA)
Продолжение,
Затем Overlap существует, если ни A Nor B истинно
Overlap := !(CondA || CondB)
и
Теперь закон deMorgan, я думаю, говорит, что
Не (A или B) <= > Не A, а не B
Overlap == !CondA && !CondB
== ![(StartA != null) && (EndB != null) && (StartA > EndB)] &&
![(StartB != null) && (EndA != null) && (StartB > EndA)]
== [(StartA == null) || (EndB == null) || (StartA <= EndB)] &&
[(StartB == null) || (EndA == null) || (StartB <= EndA)]
Я думаю, что это на самом деле немного более надежное, чем решение, которое вы разработали, потому что если EndB == NULL
, но StartA
не является нулевым, ваше первое условие приведет к сравнению StartA <= NULL
. На большинстве языков, с которыми я знаком, это условие ошибки.
Ответ 2
Это, вероятно, так же просто, как вы можете это получить, хотя я на самом деле не доказал этого.
Вероятно, не стоит этого упрощать, так как этот блок заканчивается примерно 8 операциями в худшем случае (4 в среднем благодаря оценке короткого замыкания).
Ответ 3
Все ответы основаны, если условие истинно. Здесь я хотел бы добавить примечание.
1- Тип переменной DateTime - это структура, и вы не можете установить ее в null, если только вы не используете тип с нулевым значением, например "DateTime?"
2- Чтобы найти диапазон перекрытия, выполните следующие шаги.
DateTime? StartOverLap = null,EndOverLap = null;
if (StartA != null && StartB != null)
{
StartOverLap = StartA > StartB ? StartA : StartB;
}
else if (StartA == null && StartB != null)
{
StartOverLap = StartB;
}
else if (StartA != null && StartB == null)
{
StartOverLap = StartA;
}
if (EndA != null && EndB != null)
{
EndOverLap = EndA < EndB ? EndA : EndB;
}
else if (EndA == null && EndB != null)
{
EndOverLap = EndB;
}
else if (EndA != null && EndB == null)
{
EndOverLap = EndA;
}
if (StartOverLap != null && EndOverLap == null)
{
if (EndOverLap < StartOverLap)
{
StartOverLap = null;
EndOverLap = null;
}
}
Ответ 4
Без учета нулей ответ
(StartA <= EndB) and (EndA >= StartB)
(подробнее см.
с учетом нулей для дат начала и окончания,
Использование синтаксиса оператора C Ternary:
(StartA != null? StartA: EndB <= EndB != null? EndB: StartA) &&
(EndA != null? EndA: StartB >= StartB != null? StartB: EndA)
Или операторы с нулевым стилем типа С#:
(StartA??EndB <= EndB??StartA) && (EndA??StartB >= StartB??EndA)
или в SQL:
(Coalesce(StartA, EndB) <= Coalesce(EndB, StartA))
And (Coalesce(EndA, StartB ) <= Coalesce(StartB , EndA))
Объяснение:
рассмотрите непустой ответ:
(StartA <= EndB) and (EndA >= StartB)
Теперь рассмотрим, что StartA имеет значение null, указывая, что диапазон дат A существует с начала времени (BOT). В этом случае DateRangeB никогда не может быть до DateRangeA. Поэтому первое условие (StartA (BOT) <= EndB) ВСЕГДА будет истинным, независимо от того, что такое EndB. Поэтому измените это выражение так, чтобы вместо сравнения null с EndB, когда StartA имеет значение null, сравните EndB с самим собой
Независимо от того, что такое EndB, выражение EndB <= EndB
будет истинным.
(Мы могли бы создавать переменные для представления BOT и EOT, но это проще).
Сделайте то же самое для других трех входных переменных.