【完全ガイド】date-fnsのInterval Helpers: areIntervalsOverlappingの使い方から応用例まで


areIntervalsOverlappingは、date-fnsライブラリが提供するInterval Helpersの一つで、2つの時間間隔が重なっているかどうかを判定する関数です。隣接する間隔は重なりとみなされず、inclusiveオプションをtrueに設定した場合のみ考慮されます。

構文

areIntervalsOverlapping(intervalLeft, intervalRight, [options])

引数

  • options: オプションオブジェクト(省略可)
    • inclusive: 比較が包含的かどうかを指定(デフォルトはfalse
  • intervalRight: 比較対象となる2番目の時間間隔
  • intervalLeft: 比較対象となる最初の時間間隔

戻り値

2つの時間間隔が重なっているかどうかを示すブーリアン値

// 重なる時間間隔の場合
const interval1 = { start: new Date(2024, 6, 1), end: new Date(2024, 6, 20) };
const interval2 = { start: new Date(2024, 6, 17), end: new Date(2024, 6, 21) };
const isOverlapping = areIntervalsOverlapping(interval1, interval2);
console.log(isOverlapping); // true

// 重ならない時間間隔の場合
const interval3 = { start: new Date(2024, 6, 1), end: new Date(2024, 6, 10) };
const interval4 = { start: new Date(2024, 6, 21), end: new Date(2024, 6, 30) };
const isNotOverlapping = areIntervalsOverlapping(interval3, interval4);
console.log(isNotOverlapping); // false
  • endプロパティは、時間間隔の終了時刻を表すDateオブジェクトである必要があります。
  • startプロパティは、時間間隔の開始時刻を表すDateオブジェクトである必要があります。
  • 引数に渡される時間間隔は、startendプロパティを持つオブジェクトである必要があります。
  • inclusiveオプションをtrueに設定すると、隣接する間隔も重なりとみなされます。


import { areIntervalsOverlapping } from 'date-fns';

// 重なる時間間隔
const interval1 = { start: new Date(2024, 5, 1), end: new Date(2024, 6, 20) };
const interval2 = { start: new Date(2024, 6, 15), end: new Date(2024, 7, 10) };
const isOverlapping1 = areIntervalsOverlapping(interval1, interval2);
console.log('重なる時間間隔1:', isOverlapping1); // true

// 隣接する時間間隔(inclusiveオプションをtrueに設定した場合のみ重なる)
const interval3 = { start: new Date(2024, 5, 1), end: new Date(2024, 6, 20) };
const interval4 = { start: new Date(2024, 6, 20), end: new Date(2024, 7, 10) };
const isOverlapping2 = areIntervalsOverlapping(interval3, interval4, { inclusive: true });
console.log('隣接する時間間隔2:', isOverlapping2); // true

// 隣接する時間間隔(inclusiveオプションをfalseに設定した場合)
const isOverlapping3 = areIntervalsOverlapping(interval3, interval4, { inclusive: false });
console.log('隣接する時間間隔3:', isOverlapping3); // false

// 完全包含関係にある時間間隔
const interval5 = { start: new Date(2024, 4, 1), end: new Date(2024, 7, 31) };
const interval6 = { start: new Date(2024, 5, 15), end: new Date(2024, 6, 10) };
const isOverlapping4 = areIntervalsOverlapping(interval5, interval6);
console.log('完全包含関係にある時間間隔4:', isOverlapping4); // true

// 部分包含関係にある時間間隔
const interval7 = { start: new Date(2024, 4, 1), end: new Date(2024, 7, 31) };
const interval8 = { start: new Date(2024, 6, 5), end: new Date(2024, 6, 25) };
const isOverlapping5 = areIntervalsOverlapping(interval7, interval8);
console.log('部分包含関係にある時間間隔5:', isOverlapping5); // true

// 全く重ならない時間間隔
const interval9 = { start: new Date(2024, 1, 1), end: new Date(2024, 3, 31) };
const interval10 = { start: new Date(2024, 8, 1), end: new Date(2024, 12, 31) };
const isOverlapping6 = areIntervalsOverlapping(interval9, interval10);
console.log('全く重ならない時間間隔6:', isOverlapping6); // false

説明

上記のコードでは、以下の6つの異なる状況における時間間隔の重なりを判定しています。

  1. 重なる時間間隔: interval1interval2は、6月15日から7月10日までの期間で重なっています。
  2. 隣接する時間間隔: interval3interval4は、6月20日で隣接していますが、inclusiveオプションをfalseに設定しているため、重なりとはみなされません。一方、inclusiveオプションをtrueに設定すると、隣接する間隔も重なりとみなされます。
  3. 完全包含関係にある時間間隔: interval5interval6を完全に包含しているため、重なりとみなされます。
  4. 部分包含関係にある時間間隔: interval7interval8を部分的に包含しているため、重なりとみなされます。
  5. 全く重ならない時間間隔: interval9interval10は、全く重なっていないため、重なりとはみなされません。


比較演算子を使用する

最も単純な代替方法は、比較演算子を使用して時間間隔の開始と終了を比較することです。例えば、以下のコードは、interval1interval2 が重なっているかどうかを判定します。

const interval1 = { start: new Date(2024, 6, 1), end: new Date(2024, 6, 20) };
const interval2 = { start: new Date(2024, 6, 15), end: new Date(2024, 7, 10) };

const isOverlapping = interval1.start <= interval2.end && interval2.start <= interval1.end;
console.log(isOverlapping); // true

利点

  • 追加のライブラリを必要としない
  • シンプルで理解しやすい

欠点

  • 包含関係を考慮できない(隣接する間隔は重なりとみなされない)
  • 境界条件の処理が煩雑になる可能性がある

Moment.js ライブラリを使用する

Moment.js は、時間操作のための包括的なライブラリです。isOverlapping 関数を提供しており、2つの時間間隔が重なっているかどうかを判定することができます。

const moment = require('moment');

const interval1 = moment({ start: 2024, 6, 1, end: 2024, 6, 20 });
const interval2 = moment({ start: 2024, 6, 15, end: 2024, 7, 10 });

const isOverlapping = interval1.isOverlapping(interval2);
console.log(isOverlapping); // true

利点

  • 包含関係を考慮できる
  • 境界条件の処理を自動的に行う
  • Moment.js は、時間操作に関する多くの便利な機能を提供している

欠点

  • date-fns よりもサイズが大きい
  • 追加のライブラリを必要とする

Lodash ライブラリの _.intersection 関数を使用する

Lodash は、JavaScript に役立つ様々なユーティリティ関数を提供するライブラリです。_.intersection 関数を使用して、2つの時間間隔の共通部分を計算することができます。共通部分が存在すれば、時間間隔は重なっていると判断できます。

const _ = require('lodash');

const interval1 = { start: new Date(2024, 6, 1), end: new Date(2024, 6, 20) };
const interval2 = { start: new Date(2024, 6, 15), end: new Date(2024, 7, 10) };

const overlappingInterval = _.intersection(interval1, interval2);
console.log(overlappingInterval.length > 0); // true

利点

  • 包含関係を考慮できる
  • 境界条件の処理を自動的に行う
  • Lodash は、配列やオブジェクト操作に関する多くの便利な機能を提供している

欠点

  • date-fns よりもサイズが大きい
  • 追加のライブラリを必要とする

最適な代替方法の選択

どの代替方法が最適かは、状況によって異なります。シンプルな判定であれば、比較演算子を使用する方が効率的です。Moment.js や Lodash を既に利用している場合は、これらのライブラリの isOverlapping または _.intersection 関数を使用する方が便利です。

  • 将来的**: 今後 Moment.js や Lodash を使用する予定がある場合は、これらのライブラリの関数を使用する方が将来的なメンテナンス性を考慮した上で適切な場合があります。
  • コードの簡潔性:コードの簡潔性を重視する場合は、areIntervalsOverlapping 関数を使用する方が分かりやすい場合があります。
  • 性能:パフォーマンスが重要な場合は、比較演算子を使用する方が高速な場合があります。