1. ホーム
  2. datetime

[解決済み] 2つの日付範囲が重なっているかどうかを判定する

2022-03-16 09:17:22

質問

2つの日付範囲があるとき、その2つの日付範囲が重なっているかどうかを判断する最も簡単な方法、または最も効率的な方法は何ですか?

例として、DateTime変数で示される範囲があるとします。 StartDate1 から EndDate1 そして StartDate2 から EndDate2 .

解決方法は?

(StartA <= EndB) と (EndA >= StartB) です。

証明する。
条件Aは、日付範囲Aが日付範囲Bより完全に後であることを意味するとする

_                        |---- DateRange A ------|
|---Date Range B -----|                          _

(もし StartA > EndB )

条件Bは、日付範囲Aが日付範囲Bより完全に前にあることを意味するとする

|---- DateRange A -----|                        _ 
_                          |---Date Range B ----|

(もし EndA < StartB )

AもBも真でない場合、Overlapが存在する - 。
(ある範囲が完全にどちらにも属さない場合。
または完全に前にある。 の場合、それらは重なり合う必要があります)。

これで ド・モルガンの法則 にはこう書いてある。

Not (A Or B) <=> Not A And Not B

と訳される。 (StartA <= EndB) and (EndA >= StartB)


注:端がぴったり重なる状態も含まれます。 それを除外したい場合。
変更する >= 演算子を > であり、かつ <= から <


注2.バオダッド(@Baodad)に感謝し、以下を参照してください。 このブログ が、実際の重なりは一番少ないです。
{ endA-startA , endA - startB , endB-startA , endB - startB }

(StartA <= EndB) and (EndA >= StartB) (StartA <= EndB) and (StartB <= EndA)


注3. @tomosius のおかげで、短縮版が読めます。
DateRangesOverlap = max(start1, start2) < min(end1, end2)
これは、実際にはより長い実装のための構文上のショートカットであり、開始日が endDates の上または前にあることを確認するための特別なチェックが含まれています。 上記から派生したものです。

開始日と終了日が順番通りでない可能性がある場合、すなわち startA > endA または startB > endB の場合、それらが順番に並んでいることもチェックしなければならないので、2つの有効性ルールを追加することになります。
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB) または
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB) または
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB)) または
(Max(StartA, StartB) <= Min(EndA, EndB)

しかし、実装するためには Min()Max() のように、(C言語の3進数を用いて)コーディングする必要があります。
(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)