简体   繁体   中英

How to compare previous date with next date in array using PHP?

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

Using date_format returns a string, but you want to compare DateTime objects for the given format 'Ymd 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 .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM