SVL
SVL

Reputation: 37

How to determine if each date in an array is between dates in other arrays

I have an array with dates. I have to determine which dates belongs to which periods. For that purpose I have two other arrays - one with start dates and one with end dates for these periods.

I have tried foreach loops for the dates and the DatePeriod class but I couldn't get it to work.

foreach ($dates as $value) {
  foreach ($startdates as $key => $value1) {
    foreach ($enddates as $key => $value2) {
      if ($value > $value1 && $value < $value2) {
        result[$value] = $key;
      }
    }
  }
}

dates (extract) / $dates

$dates = Array ( [0] => 2011-04-11 
                [1] => 2011-06-28 
                [2] => 2011-09-26 
                [3] => 2012-01-02 
                [4] => 2012-05-12 )

start dates with assigned keys (extract) / $startdates

Array ( [10] => 2011-01-01 
        [20] => 2011-07-01 
        [30] => 2012-01-01 
        [40] => 2012-07-01 )

end dates with assigned keys (extract) / $enddates

Array ( [10] => 2011-06-30 
        [20] => 2011-12-31 
        [30] => 2012-06-30 
        [40] => 2012-12-31 )

I would like the result to be a new array, where the dates in the $dates array becomes keys and the periods in the start- and end dates arrays becomes values like this:

Array ( [2011-04-11] => 10 
        [2011-06-28] => 10 
        [2011-09-26] => 20 
        [2012-01-02] => 30 
        [2012-05-12] => 30 )

Upvotes: 0

Views: 346

Answers (2)

mickmackusa
mickmackusa

Reputation: 47894

Because you are comparing Y-m-d formatted dates, you don't need date/time functions -- in other words, just treat the dates as strings.

Simultaneously iterate the start and end elements. When you find the correct range, store the data and continue with the next date to assess.

Code: (Demo)

$dates = ['2011-04-11', '2011-06-28', '2011-09-26', '2012-01-02', '2012-05-12'];
$startdates = [
    10 => '2011-01-01',
    20 => '2011-07-01',
    30 => '2012-01-01',
    40 => '2012-07-01'
];
$enddates = [
    10 => '2011-06-30',
    20 => '2011-12-31',
    30 => '2012-06-30',
    40 => '2012-12-31'
];

foreach ($dates as $date) {
    foreach ($startdates as $key => $startdate) {
        if ($date >= $startdate && $date <= $enddates[$key]) {
            $result[$date] = $key;
            continue 2;
        }
    }
    $result[$date] = 'out of bounds';
}
var_export($result);

Output:

array (
  '2011-04-11' => 10,
  '2011-06-28' => 10,
  '2011-09-26' => 20,
  '2012-01-02' => 30,
  '2012-05-12' => 30,
)

Upvotes: 1

Rahul
Rahul

Reputation: 18557

You can loop around your main dates variable for the period of start and end date arrays,

// combining keys and values
$temp   = array_combine($startdates, $enddates);
$result = [];
// & for making changes on assigned address of variable regardless of array_walk function scope
array_walk($dates, function ($item, $key) use (&$result, $temp, $startdates) { 
    foreach ($temp as $k => $v) {
        // comparing with start and end date range
        if (strtotime($item) >= strtotime($k) && strtotime($item) <= strtotime($v)) {
            // searching by value and getting key
            $result[$item] = array_search($k, $startdates); 
            // if comes to this loop break as its never gonna come here
            break;
        }
    }
});

array_combine — Creates an array by using one array for keys and another for its values
array_walk — Apply a user supplied function to every member of an array
array_search — Searches the array for a given value and returns the first corresponding key if successful

Output

Array
(
    [2011-04-11] => 10
    [2011-06-28] => 10
    [2011-09-26] => 20
    [2012-01-02] => 30
    [2012-05-12] => 30
)

Demo.

Upvotes: 1

Related Questions