rahul
rahul

Reputation: 849

how to sort a multidimensional array according to current time?

I have an array like

$arr = array(

        array(
            'id'=>'1',
            'time'=>'08:00'
            ),
        array(
            'id'=>'2',
            'time'=>'11:00'
            ),
        array(
            'id'=>'3',
            'time'=>'14:00'
            ),
        array(
            'id'=>'4',
            'time'=>'17:00'
            )
       );

what i want is suppose if the time is 11:30 i want the third array(time->14:00) to come in the first position of the array and the rest to come underneath it. I'm using PHP 5.3 (That's all far i can go with the technology).

The output should be:

array(
      array(
            'id'=>'1',
            'time'=>'14:00'
            ),
       array(
            'id'=>'2',
            'time'=>'17:00'
            )
        array(
            'id'=>'3',
            'time'=>'08:00'
            ),
        array(
            'id'=>'4',
            'time'=>'11:00'
            )
);

Upvotes: 0

Views: 57

Answers (3)

trincot
trincot

Reputation: 350300

You could use this callback to usort:

$t = date("h:m") . "_"; // add a character so it cannot be EQUAL to any time in the input
usort($arr, function ($a, $b) use ($t) {
    return strcmp($a["time"],$b["time"]) * strcmp($t,$a["time"]) * strcmp($t,$b["time"]);
});

Explanation

First the current time is retrieved in HH:MM format. A character is appended to it so to make sure none of the time strings in the input array will exactly match it. This will ensure that calling strcmp with the current time as argument, and an input date as other argument, will never return 0, but either -1 or 1. Note that -1 means that the first argument is less than the second argument. 1 means the opposite.

The callback passed to usort will be called for several pairs of input time strings and should return a negative or positive value (or 0) to indicate how the pair should be ordered in the output: negative means the first value should come before the second, 0 means they are identical and can be ordered any way, and 1 means the second should be ordered before the first.

The return value is here a multiplication of three values, each the result of strcmp. The second and third can never be zero.

When the second and third value are equal (both 1 or both -1), it means that the two input times are at the same side of the current time: either both before the current time, or both after it. The product of these two factors is then 1.

When these values are not equal (one is 1, the other -1), then it means the two input times are at different sides of the current time, and so their order should be opposite. The product is then -1.

Finally, the first factor tells us how the two input values compare to eachother. This should be reversed when the above mentioned product is -1, and indeed the multiplication will take care of that.

Upvotes: 3

Pinke Helga
Pinke Helga

Reputation: 6682

In PHP 7

usort($arr, function($a, $b)
{
  $t = time();
  $a = $t < ($a = strtotime($a['time'])) ? $a : $a + 86400; // +1 day
  $b = $t < ($b = strtotime($b['time'])) ? $b : $b + 86400;
  return $a <=> $b;
});

Upvotes: 1

Justinas
Justinas

Reputation: 43479

Use usort for that:

usort($array, function ($a, $b) {
   $aTime = strtotime(date('Y-m-d ' . $a['time']));
   $bTime = strtotime(date('Y-m-d ' . $b['time']));
   $time = strtotime(date('Y-m-d 13:00'));

   if ($aTime > $time && $bTime < $time)
       return -1; // $a is in future, while $b is in past
   elseif ($aTime < $time && $bTime > $time)
       return 1; // $a is in past, while $b is in future
   else
       return $aTime - $bTime; // $a and $b is either in future or in past, sort it normally.
});

Live example

Upvotes: 2

Related Questions