Home > Software design >  How to compare previous date with next date in array using PHP?
How to compare previous date with next date in array using PHP?

Time:09-27

I have these datetime input in array from 8am until 5pm

2022-09-23 08:00:00
2022-09-23 08:30:00
2022-09-23 09:00:00
2022-09-23 09:30:00
2022-09-23 10:00:00
2022-09-23 10:30:00
2022-09-23 11:00:00
2022-09-23 13:00:00
2022-09-23 13:30:00
2022-09-23 14:00:00
2022-09-23 14:30:00
2022-09-23 15:00:00
2022-09-23 16:00:00
2022-09-23 16:30:00
2022-09-23 17:00:00
2022-09-23 17:30:00

My goal is to get/output previous array if input for datetime is greater than previous array and less than next array

Input datetime 2022-09-23 09:12:00, it will use 2022-09-23 09:00:00
Input datetime 2022-09-23 10:29:00, it will use 2022-09-23 10:00:00

My current code :

$final_datetime = array();
$datetime = "2022-09-22 09:12:00";

foreach ($arr as $k => $v) {
  if ($v == $datetime) {
    $final_datetime[] = $v;
  } else {

    $next1="";
    $prev1="";

    // Previous Array
    if (isset($arr[$k-1])) {
      $prev1 = $arr[$k-1];
    }

    // Next Array
    if (isset($arr[$k 1])) {
      $next1 = $arr[$k 1];
    }

    $prev2 = date_create($prev1);
    $prev  = date_format($prev2, 'Y-m-d H:i:s'); 

    $next2 = date_create($next1);
    $next  = date_format($next2, 'Y-m-d H:i:s');

    if ($datetime > $prev && $datetime < $next) {
      echo 'Output : '.$prev.'<br/>';
    } else {
      
    }

  }
}

My current output :

Output : 2022-09-22 08:30:00
Output : 2022-09-22 09:00:00

Expected Output :

Output : 2022-09-22 09:00:00

CodePudding user response:

Using date_format returns a string, but you want to compare DateTime objects for the given format 'Y-m-d H:i:s'

A few notes about the code.

  • You are using 2022-09-23 in the array, but the variable $datetime = "2022-09-22 09:12:00"; is of the day before
  • It can be confusing to put in the comment Previous Array while you actually mean the previous array item
  • If you only want to return a single item, then you should either return the last item of the array $final_datetime or make $final_datetime a string and overwrite the value everytime there is a new match. As you are using only a single value to check and the timeslots in sequence, you can just overwrite the value
  • At the end of the code when doing the comparison for the datetimes, you can first check the values of the variables that are in scope

Example code

$datetimeStr = "2022-09-23 09:12:00";
$final_datetime = "$datetimeStr is not within timeslots.";
$format = 'Y-m-d H:i:s';
$d = DateTime::createFromFormat($format, $datetimeStr);

foreach ($arr as $k => $v) {
    if ($v === $datetimeStr) {
        $final_datetime = $v;
        break;
    } else {
        $prevDatetime = false;
        $nextDateTime = false;
        $prevStr = "";
        $nextStr = "";

        if (isset($arr[$k - 1])) {
            $prevStr = $arr[$k - 1];
        }
        if (isset($arr[$k   1])) {
            $nextStr = $arr[$k   1];
        }
        if ($prevStr) {
            $prevDatetime = DateTime::createFromFormat($format, $prevStr);
        }
        if ($nextStr) {
            $nextDateTime = DateTime::createFromFormat($format, $nextStr);
        }

        if ($prevDatetime && $nextDateTime && $d && ($d > $prevDatetime && $d < $nextDateTime)){
            $final_datetime = $prevStr;
        }
    }
}

echo "Output: " . $final_datetime;

Result

Output: 2022-09-23 09:00:00

See a php demo.

CodePudding user response:

You were on the right track using date_create(), the easiest way is to just add the input datetime to the array and convert everything into a DateTime with array_map() then pass it to sort(). Then all you have to do is search the array for the input DateTime. If it is the first or last item in the array that means its outside the range. Below, I wrote the process into a function that returns false if the datetime falls outside the range (btw, your example searches for a datetime outside the range).

function findTimeSlotFor(string $dt_str, array $ts_arr)
{
  if (in_array($dt_str, $ts_arr))
    // return exact string match
    return $dt_str;
  
  // add it to the array
  $ts_arr[] = $dt_str;
  // convert to DateTimes
  $dt_arr = array_map('date_create', $ts_arr);
  $dt = date_create($dt_str);
  
  // sort the array
  sort($dt_arr);
  // find where it landed
  $landed_at_index = array_search($dt, $dt_arr);

  if(0 == $landed_at_index || array_key_last($dt_arr) == $landed_at_index){
    // input datetime outside the range of datetimes in the array
    // adjust to your logic
    return false;
  }
  // return the one before
  return $dt_arr[$landed_at_index - 1]->format('Y-m-d H:i:s');
}

See the above code in action here: https://onlinephp.io/c/2cc7a

  • Related