2016-07-19 15 views
0

日付範囲の配列を他の日付範囲の範囲で分割する必要があります。php - 日付範囲を分割して

$items = array(
    array(
     'ID' => 2, 
     'from' => new DateTime('2016-07-01'), 
     'to' => new DateTime('2016-07-19') 
    ), 
    array(
     'ID' => 3, 
     'from' => new DateTime('2016-07-15'), 
     'to' => new DateTime('2016-07-29') 
    ), 
    array(
     'ID' => 1, 
     'from' => new DateTime('2016-01-01'), 
     'to' => new DateTime('2016-12-31') 
    ), 
    array(
     'ID' => 4, 
     'from' => new DateTime('2016-06-15'), 
     'to' => new DateTime('2016-07-07') 
    ), 
    array(
     'ID' => 5, 
     'from' => new DateTime('2016-07-05'), 
     'to' => new DateTime('2016-07-17') 
    ), 
); 

を私は期待していた結果は次のように、アイテムのIDを参照して、全ての期間を持つ配列です:

例えば、私の開始配列は、することができ

$result = array(
    array(
     'from' => new DateTime('2016-01-01'), 
     'to' => new DateTime('2016-06-14'), 
     'ids' => array(
      1 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-06-15'), 
     'to' => new DateTime('2016-06-30'), 
     'ids' => array(
      1, 4 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-01'), 
     'to' => new DateTime('2016-07-04'), 
     'ids' => array(
      1, 2, 4 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-05'), 
     'to' => new DateTime('2016-07-07'), 
     'ids' => array(
      1, 2, 4, 5 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-08'), 
     'to' => new DateTime('2016-07-14'), 
     'ids' => array(
      1, 2, 5 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-15'), 
     'to' => new DateTime('2016-07-17'), 
     'ids' => array(
      1, 2, 3, 5 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-18'), 
     'to' => new DateTime('2016-07-19'), 
     'ids' => array(
      1, 2, 3 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-20'), 
     'to' => new DateTime('2016-07-29'), 
     'ids' => array(
      1, 3 
     ) 
    ), 
    array(
     'from' => new DateTime('2016-07-30'), 
     'to' => new DateTime('2016-12-31'), 
     'ids' => array(
      1 
     ) 
    ), 
); 

手伝って頂けますか?ありがとう

UPDATE 今のところ私は 'from'アイテムとループアイテムと配列の配列で配列を並べようとしました。これは私のコードです:

usort($items, function($a, $b) { 
    if ($a['from'] == $b['from']) { 
     return 0; 
    } 
    if ($a['from'] < $b['from']) { 
     return -1; 
    } 
    return 1; 
}); 

$ranges = array(
    array(
     'from' => clone $items[0]['from'], 
     'to' => clone $items[0]['to'], 
     'ids' => array($items[0]['ID']) 
    ) 
); 
unset($items[0]); 
foreach($items as $item) { 
    foreach($ranges as $k => $range) { 
     if (($range['from'] <= $item['from']) || ($range['to'] > $item['to'])) { 
      if ($range['from'] <= $item['from']) { 
       $clone = $range; 
       $clone['from'] = $item['from']; 
       $clone['to'] = clone $item['to']; 
       $clone['ids'][] = $item['ID']; 

       $ranges[$k]['to'] = clone $item['from']; 
       $ranges[$k]['to']->modify('-1 day'); 
       $ranges[] = $clone; 
      } 

      if ($range['to'] > $item['to']) { 
       $clone = $range; 
       $clone['from'] = clone $item['to']; 
       $clone['from']->modify('+1 day'); 
       $clone['to'] = clone $range['to']; 
       $ranges[] = $clone; 
      } 
     } 
    } 
} 

結果は、私が必要とする結果がより多くの配列です。ご協力ありがとうございました。

+0

問題は何ですか?何を試しましたか? –

答えて

0

正直言って、私はこれを複数のステップのプロセスにしています...しかし、私はそれが1つのステップで実行できると確信していますが、コードは - そして既にあるかもしれません -

to+1の日付とすべてのfromの日付を配列に格納して並べ替える1回のパスから開始します。

ここであなたの間隔があります。最初のエントリはfromで、最小のfromの日付と一致する必要があります。次の日付は、to+1またはfromのいずれかの日付です。どちらの方法でも、間隔はfromから次のものが-1です。次の間隔はその値から始まり、次の1まで続きます。

次の手順では、元の間隔を新しい間隔に並べ替えます。

パフォーマンス/ストレージが非常に大きな懸念事項でない限り、これは十分可能であり、コードが継承されるすべての人が理解できると思われます。