13

重複の可能性:
2 つの日付範囲が重複しているかどうかを判断する

PHP の 2 つの時間範囲が重複しているかどうかを調べようとしています。最初の試行で2 つの日付範囲が重複しているかどうかを判断する方法を参照してきましたが、すべてのケースに一致するわけではありません。時間範囲が別の時間範囲の開始時間と終了時間の間にネストされている場合、一致していません。シフトの開始または終了にオーバーラップする場合、またはシフトが完全に一致する場合は、期待どおりに機能します。

私が話していることのこの画像をチェックしてください:

ここに画像の説明を入力

基本的に、オレンジ色のシフトがどこかで赤いシフトと重なっている場合、オレンジ色のシフトを隠そうとしています。これを実現するために使用しようとしているコードの関連部分を次に示します。

if(($red['start'] <= $orange['end']) && ($red['end'] >= $orange['start'])) {
    //Conflict handling
}

変数の値は UNIX タイムスタンプです。数字を論理的に調べてみると、上記のステートメントが失敗する理由がわかりました。あるシフトが別のシフトに該当するかどうかを判断するために、より多くのロジックを実行できる方法があることは明らかですが (これが必要になる場合があります)、より普遍的なキャッチを期待していました。

編集:各ブロックの開始時間と終了時間の値を追加します。私が持っているものが機能することに同意します。そうではないという事実は、私の問題があるところです。私はおそらくばかげたことを見落としています。

orange-start = 1352899800
orange-end = 1352907000

red-start = 1352923200
red-end = 1352926200

したがって、私の論理は次のように述べます。

if((1352923200 <= 1352907000) && (1352926200 >= 1352899800))

それに続いて、最初の比較は失敗します。

EDIT 2:私のロジックは正しいようです (私はそう思っていました)。私の問題は、表示されている実際の時間と一致しない UNIX タイムスタンプに関連するものです。私と一緒にこの問題に取り組んでくれた人たちに感謝し、それが問題であることを発見するのを助けてくれました。アンドレイとジェイソンの両方の答えを受け入れることができればいいのにと思います。

4

4 に答える 4

10

[b1, e1]およびの 2 つの範囲がある場合(および[b2, e2]が既に確立されている場合)、オーバーラップは次の論理式によって検出されます。b1 < e1b2 < e2

not (e2 < b1 or e1 < b2)

これは次のように書き換えることができます

e2 >= b1 and e1 >= b2

あなたの構文では、

if(($orange['end'] >= $red['start']) && ($red['end'] >= $orange['start'])) {
   //Conflict handling
}

つまり、あなたはそれを正しく取得しました。「数字を論理的に処理することで、上記のステートメントが失敗する理由が理解できます」と主張する理由。私には明確ではありません。正確には何が失敗しますか?(そして、2 つ以上の比較を行う、ばかばかしいほど「過剰に設計された」チェックを誰もが思いつく理由はわかりません。)

もちろん、接触範囲が重複しているとみなすかどうかを決定し、それに応じて比較の厳密さを調整する必要があります。

PS編集で提供したサンプル範囲は重複しておらず、比較では競合のない状況として正しく認識されています。つまり、すべてが正常に機能します。どこに問題があると思いますか?

于 2012-11-14T21:42:57.527 に答える
7

ロジックは正しいです。$red(午後 8 時~午後 8 時 50 分)と$orange(午後 1 時 30 分~午後 3 時 30分)のタイムスタンプは重複していません

正しい値 (スクリーンショットを反映する) が与えられた場合、オーバーラップが実際に見つかります。

function show_date($value, $key) {
    echo $key, ': ', date('r', $value), PHP_EOL;
}

$red = array('start' => strtotime('today, 2pm'), 'end' => strtotime('today, 2:45pm'));
$orange = array('start' => strtotime('today, 1:30pm'), 'end' => strtotime('today, 4pm'));

array_walk($red, 'show_date');
array_walk($orange, 'show_date');

if (($red['start'] <= $orange['end']) && ($red['end'] >= $orange['start'])) {
    echo 'Conflict handling';
}

私の推測では、タイムゾーンの変換に問題があると思います。

于 2012-11-14T22:00:43.837 に答える
1

「オレンジ」タスクの開始と終了の間に開始または終了する「赤」タスクがあるかどうかを確認する必要があります。このように、「RED」タスクと重なっているすべての「ORANGE」タスクを検出する必要があります。

if((($red['start'] <= $orange['end']) && ($red['start'] >= $orange['start'])) ||
   (($red['end'] <= $orange['end']) && ($red['end'] >= $orange['start'])) ) {
    //Conflict handling
}

編集:AndreyTが述べたように、これは一種のやり過ぎであり、少ないチェックでより良くすることができます

于 2012-11-14T21:26:16.230 に答える
0
if ((($red['start'] <= $orange['end']) && ($red['start'] >= $orange['start']))
    || (($red['end'] <= $orange['end']) && ($red['end'] >= $orange['start']))
    || (($red['start'] >= $orange['start']) && ($red['end'] >= $orange['end']))
   ) {
 // conflict happens if Red starts sometime between Orange start and end
 //               or if Red ends sometime between Orange start and end
 //               or if Red starts before Orange starts and ends after Orange ends

}
于 2012-11-14T21:32:56.320 に答える