2つの時間帯の重複チェック

公開:2020/11/05
更新:2020/11/23
3 min読了の目安(約3000字TECH技術記事

重複の有無のみを調べる

「重複があるかどうか」を調べるには、「重複がないかどうか」から考える方が簡単です。

この記事では、Aの終わり == Bの始まりまたはBの終わり == Aの始まりであるものは「重複がない」とします。
e.g.    A: 01:00 - 02:00
     B: 02:00 - 03:00

  1. パターンAABB A.end <= B.start
    A: |------------------|
    B:                        |------------------|
    
    A: |------------------|
    B:                    |------------------|
    
  2. パターンBBAA B.end <= A.start
    A:                        |------------------|
    B: |------------------|
    
    A:                    |------------------|
    B: |------------------|
    

A.end <= B.start || B.end <= A.startであれば重複なし。
すなわち、B.start < A.end && A.start < B.endであれば重複ありということになります。

重複している時間帯を調べる

  1. パターンABAB (A.start < B.start < A.end < B.end)
    A: |------------------|
    B:           |------------------|
    
    O.start = B.start
    O.end = A.end
    
  2. パターンABBA (A.start <= B.start < B.end <= A.end)
    A: |------------------------------|
    B:       |------------------|
    
    O.start = B.start
    O.end = B.end
    
  3. パターンBABA (B.start < A.start < B.end < A.end)
    A:           |------------------|
    B: |------------------|
    
    O.start = A.start
    O.end = B.end
    
  4. パターンBAAB (B.start <= A.start < A.end <= B.end)
    A:       |------------------|
    B: |------------------------------|
    
    O.start = A.start
    O.end = A.end
    

Dartで書くと

void main() {
  int aStart = DateTime(2020, 1, 1, 1, 0).millisecondsSinceEpoch;
  int aEnd = DateTime(2020, 1, 1, 3, 0).millisecondsSinceEpoch;
  int bStart = DateTime(2020, 1, 1, 2, 0).millisecondsSinceEpoch;
  int bEnd = DateTime(2020, 1, 1, 5, 0).millisecondsSinceEpoch;
  
  DateTime oStart;
  DateTime oEnd;
  
  // AABB or BBAA
  if (aEnd <= bStart || bEnd <= aStart) {
    print('No overlapping');
  }
  
  // ABAB
  if ((aStart < bStart) && (bStart < aEnd) && (aEnd < bEnd)) {
    oStart = DateTime.fromMillisecondsSinceEpoch(bStart);
    oEnd = DateTime.fromMillisecondsSinceEpoch(aEnd);
  } 
  // ABBA
  else if ((aStart <= bStart) && (bStart < bEnd) && (bEnd <= aEnd)) {
    oStart = DateTime.fromMillisecondsSinceEpoch(bStart);
    oEnd = DateTime.fromMillisecondsSinceEpoch(bEnd);
  } 
  // BABA
  else if ((bStart < aStart) && (aStart < bEnd) && (bEnd < aEnd)) {
    oStart = DateTime.fromMillisecondsSinceEpoch(aStart);
    oEnd = DateTime.fromMillisecondsSinceEpoch(bEnd);
  } 
  // BAAB
  else if ((bStart <= aStart) && (aStart < aEnd) && (aEnd <= bEnd)) {
    oStart = DateTime.fromMillisecondsSinceEpoch(aStart);
    oEnd = DateTime.fromMillisecondsSinceEpoch(aEnd);
  }
  
  print('$oStart - $oEnd');
}
2020-01-01 02:00:00.000 - 2020-01-01 03:00:00.000

日付なしの時間のみの比較

22:00 - 01:0003:00 - 02:00のようにendstartよりも早い時間になっている場合、endstartの次の日のその時間であると解釈できます。

endに24時間分追加して、計算します。

e.g.

A: 22:00 - 01:00 (= 22:00 - 25:00)
B: 23:00 - 02:00 (= 23:00 - 26:00)

=> 23:00 - 01:00 (= 23:00 - 25:00)

Dartでパッケージ化して公開しました

pub.devで公開しています。

https://pub.dev/packages/overlapping_time