📜 ⬆️ ⬇️

PHP: work with time intervals

Once, according to the task, I ran into a problem that I could not find a solution on the Internet. Either the problem is specific and no one has come across it, or it is primitive, and I used the wrong search procedure. But as for any programmer, it became interesting for me to solve it myself and in my own way ...

The problem was this: for example, there are 10 tasks that are performed in parallel, each task is divided into subtasks that start at a certain time and their duration is known, we need to add a couple of subtasks to one of the tasks, but first we need to find out if there are free the length of time we need and how long to how long they last. We have $ reservArray with data that contains the start and end time of an event for each element of the array, as well as the start and end time ($ timeArray) of the interval in which we need to check which intervals and how long we will have if in the given interval All events from the previous array will occur.

As a result, I needed the function to return the array with free intervals if they are longer than the duration that I pass to the function as the $ duration parameter, the error variable was also added for the start and end time of the event, which I needed at that moment to cut off the intervals no interest to me (less than 3 seconds)
')


function getFreeTimeArray($timeArray, $reservArray, $duration, $nullDuration = 3) { $resultArray = null; $tmpArray[] = $timeArray; if (!empty($reservArray) && is_array($reservArray)) { foreach ($reservArray as $value) { if (!empty($tmpArray)) foreach ($tmpArray as $tmp_key => $tmp_val) { /* * reserved line * a|============|b * * time line * x|------------|y * * * a = $value['start'] * b = $value['end'] * * x = $tmp_val['start'] * y = $tmp_val['end'] */ /* if x>a && x>b * * a|====|b * * x|------|y * * * OR y * * a|====|b * * x|------|y * * * => reserved & time line not intersect */ if (($tmp_val['start'] > $value['start'] && $tmp_val['start'] > $value['end']) || ($tmp_val['end'] < $value['start'] && $tmp_val['end'] < $value['end'])) { } else { //reserved & time line intersect /* if x<=a && y>=b * * a|====|b * * x|------------|y * */ if ($tmp_val['start'] <= $value['start'] && $tmp_val['end'] >= $value['end']) { //if (ax) > nullDuration -> save data to array('start'=>x,'end'=>(a-1)) if (($value['start'] - $tmp_val['start']) > $nullDuration) $tmpArray[] = array('start' => $tmp_val['start'], 'end' => $value['start'] - 1); //if (yb) > nullDuration -> save data to array('start'=>(b+1),'end'=>y) if (($tmp_val['end'] - $value['end']) > $nullDuration) $tmpArray[] = array('start' => ($value['end'] + 1), 'end' => $tmp_val['end']); //delete this time interval unset($tmpArray[$tmp_key]); } /* if x>=a && y<=b * * a|==========|b * * x|------|y * */ else if ($tmp_val['start'] >= $value['start'] && $tmp_val['end'] <= $value['end']) { unset($tmpArray[$tmp_key]); } /* if x>=a && x<=b * * a|=====|b * * x|------------|y * */ else if ($tmp_val['start'] >= $value['start'] && $tmp_val['start'] <= $value['end']) { if (($tmp_val['end'] - $value['end']) > $nullDuration) $tmpArray[] = array('start' => ($value['end'] + 1), 'end' => $tmp_val['end']); unset($tmpArray[$tmp_key]); } /* if y>=a && y<=b * * a|=====|b * * x|----------|y * */ else if ($tmp_val['end'] >= $value['start'] && $tmp_val['end'] <= $value['end']) { if (($value['start'] - $tmp_val['start']) > $nullDuration) $tmpArray[] = array('start' => $tmp_val['start'], 'end' => ($value['start'] - 1)); unset($tmpArray[$tmp_key]); } } } } } // if result is not null // check duration in result data and sort array if (!empty($tmpArray)) { $tmpArray2 = null; foreach ($tmpArray as $val) { if ($duration <= ($val['end'] - $val['start'])) $tmpArray2[$val['start']] = $val; } ksort($tmpArray2); $tmpArray = $tmpArray2; } $resultArray = $tmpArray; return $resultArray; } 


As a result of the transfer of this function of all parameters, I received at the output of an array of time intervals free from events and with a duration longer than that specified in $ duration

If you have questions, ask, but I would like to hear a solution to this problem in other ways. ;)
original article in my blog on LiveJournal

PS if you minus it, then at least indicate what you did not like, or I have a bad mood, come on and ruin others ...
A person solves a problem and proposes its solution to others, but someone quietly minus it and his mood rises from it ...

PS2 Here are the trolls ... at least say what you don't like, why just minusovat so ??? I still have a couple of solutions for Javascript and PHP, but I don’t even know with such trolls only memoirs here you can write, judging by the evaluation of this topic, you don’t like free solutions here ... at least there are a few minuses than pluses. Is there any washed away posting?

PPS, thanks to MikhailEdoshin, a solution was found that allows replacing lines 46-52 with
if($tmp_val['start'] < $value['end'] && $value['start'] < $tmp_val['end'])
for which a special thank you to him!

Source: https://habr.com/ru/post/65184/


All Articles