0

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 )
3
  • 2
    What you have done so far ? Commented May 3, 2019 at 11:22
  • 2
    "I have tried foreach loops for the dates and the DatePeriod class but I couldn't get it to work." Please show us that piece of code, you might be closer to the solution than you believe Commented May 3, 2019 at 11:23
  • I think I suggested on yesterdays question that the Dates would be a better key Commented May 3, 2019 at 11:44

2 Answers 2

1

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,
)
Sign up to request clarification or add additional context in comments.

1 Comment

@SVL you will notice that my solution makes no function calls and performs no data preparation. This solution is clean, efficient, and even handles dates that are out of the provided ranges.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.