2010-07-07 5 views
5

Я ищу расширенного ответа на поставленный вопрос здесь:Диапазон дат перекрываться с Nullable Даты

Determine Whether Two Date Ranges Overlap

, где любой из дат в любом диапазоне дат может быть пустым. Я придумал следующее решение, но я не уверен, что его можно упростить дальше.

(StartA == NULL || StartA <= EndB) && 
(EndA == NULL || EndA >= StartB) && 
(StartB == NULL || StartB <= EndA) && 
(EndB == NULL || EndB >= StartA) 

Предполагая:

DateTime диапазоны Старта до End А и StartB к EndB

EDIT: Жаль, что я быстро бросил выше логику вместе, которая, кажется, не в состоянии, когда либо начало и конец диапазона в даты - NULL. См. Решение Дэвида ниже для лучшего объяснения &.

+0

вы получите сообщение об ошибке, если значение StartA равно null, поскольку оператор сравнения не работает с нулем. Преобразуйте все или Gate {Logic} в и {Logic}, затем реорганизуйте инструкции, поместив все значение null в начале, чтобы короткое замыкание и {Logic} работали. –

ответ

12

Этот вопрос может быть обработан небольшим обобщением Charles Bretana's excellent answer на этот вопрос.

Пусть Конда Среднее DateRange Полностью После DateRange B (True, если Старта> EndB) Пусть CondB Mean DateRange полностью Перед DateRange B (True, если EndA < StartB)

В этом случае, если предположить, вы хотите, чтобы нулевая дата представляла «никакую начальную/конечную границу», условия изменены.Например, для CondA, чтобы DateRange A был полностью после DateRange B, DateRange A должен иметь определенное время начала, DateRange B должен иметь определенное конечное время, и время начала A должно быть после окончания времени окончания из B:

CondA := (StartA != null) && (EndB != null) && (StartA > EndB) 

CondB То же самое с а и в переключаются:

CondB := (StartB != null) && (EndA != null) && (StartB > EndA) 

Продолжение,

Тогда Перекрытие существует, если ни А, ни В истинно

Overlap := !(CondA || CondB) 

и

Теперь закон де Моргана, я думаю, что это, говорит, что

Не (A или B) < = > Not 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 не имеет значения null, ваше первое условие закончится сравнением StartA <= NULL. На большинстве языков, с которыми я знаком, это условие ошибки.

+0

Спасибо за подробное объяснение, Дэвид! Да, я понял, что мое первоначальное решение довольно быстро развалится вскоре после того, как я разместил его. – Josh

+0

Хороший подход как закон deMorgan, но вы не можете реализовать вторую часть как инструкцию программирования, потому что если какой-либо из startA или EndB в качестве примера равен нулю, оператор сравнения завершится с ошибкой. Постарайтесь сохранить оператор And {&&}, потому что он будет работать как короткое замыкание в большинстве новых компиляторов. Правильно, как низко и как программирование. ! [(StartA! = Null) && (EndB! = Null) && (StartA> EndB)] && ! [(StartB! = Null) && (EndA! = Null) && (StartB> EndA)] –

+1

@Waleed : Если вы говорите о моих последних двух строках кода, это, безусловно, может быть реализовано как инструкция. Если 'startA' или' endB' равно «null», это будет застигнуто явными тестами для этого условия, и сравнение '<=' никогда не будет выполнено. '||' также использует оценку короткого замыкания. (Большинство компиляторов, вероятно, оптимизируют использование закона DeMorgan, чтобы две последние строки и две предыдущие строки сгенерировали один и тот же скомпилированный код.) –

0

Это, вероятно, так же просто, как вы можете это получить, хотя я на самом деле не доказал это.

Это, вероятно, не стоит упрощать, поскольку этот блок заканчивается примерно 8 операциями в худшем случае (в среднем 4 из-за оценки короткого замыкания).

0

Все ответы основаны, если условие истинно. Я хотел бы добавить здесь несколько примечаний.

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; 
       } 
      } 
0

Без учета аннулирует, ответ

(StartA <= EndB) and (EndA >= StartB) (см this для подробного объяснения)

с учетом аннулирует для начала и конец,
Использование синтаксиса оператора C Ternary:
(StartA != null? StartA: EndB <= EndB != null? EndB: StartA) && (EndA != null? EndA: StartB >= StartB != null? StartB: EndA)

или C# 4.x стиль нулевые операторы:

(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, но это проще).

Сделайте то же самое для других трех входных переменных.

Смежные вопросы