35
Array
        (
            [0] => Array
                (
                    [dateTime] => 2011-10-18 0:0:00
                    [chanl1] => 20.7
                    [chanl2] => 45.4
                    [chanl3] => 
                )

            [1] => Array
                (
                    [dateTime] => 2011-10-18 0:15:00
                    [chanl1] => 20.7
                    [chanl2] => 45.4
                    [chanl3] => 
                )


            [2] => Array
                (
                    [dateTime] => 2011-10-18 00:14:00
                    [chanl1] => 20.7
                    [chanl2] => 33.8
                    [chanl3] => 
                )

            [3] => Array
                (
                    [dateTime] => 2011-10-18 00:29:00
                    [chanl1] => 20.6
                    [chanl2] => 33.9
                    [chanl3] => 
                )

I want to sort the above array based on the [dateTime], the final output should be:

Array
        (
            [0] => Array
                (
                    [dateTime] => 2011-10-18 0:0:00
                    [chanl1] => 20.7
                    [chanl2] => 45.4
                    [chanl3] => 
                )

            [1] => Array
                (
                    [dateTime] => 2011-10-18 00:14:00
                    [chanl1] => 20.7
                    [chanl2] => 33.8
                    [chanl3] => 
                )

            [2] => Array
                (
                    [dateTime] => 2011-10-18 0:15:00
                    [chanl1] => 20.7
                    [chanl2] => 45.4
                    [chanl3] => 
                )            

            [3] => Array
                (
                    [dateTime] => 2011-10-18 00:29:00
                    [chanl1] => 20.6
                    [chanl2] => 33.9
                    [chanl3] => 
                )

Is there anyone know how to do it? Thanks!

Acubi
  • 2,793
  • 11
  • 41
  • 54
  • The datetime data in this question is "Big-endian", so there is no need to parse the column values -- just [comparing them as strings is 100% reliable](https://stackoverflow.com/a/67124505/2943403). – mickmackusa Aug 15 '22 at 20:02

6 Answers6

64

Use usort() function with custom comparator:

$arr = array(...);

usort($arr, function($a, $b) {
  $ad = new DateTime($a['dateTime']);
  $bd = new DateTime($b['dateTime']);

  if ($ad == $bd) {
    return 0;
  }

  return $ad < $bd ? -1 : 1;
});

DateTime class has overloaded comparison operators (<, >, ==).

Andy
  • 4,901
  • 5
  • 35
  • 57
Crozin
  • 43,890
  • 13
  • 88
  • 135
  • it should be usort(**$arr, **function($a, $b) but the rest is ok – Martin Holzhauer Nov 14 '11 at 12:05
  • 3
    @Crozin It is a common misconception that usort has to return `-1,0,1`. Like the manual states: *The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.* and that means any value `<=>0`. – Gordon Nov 14 '11 at 12:34
  • 3
    @Gordon: Yeah, I know that fact, however if we're operating on something that is not a number (DateTime in this case) it's a common practice to return `±1`. – Crozin Nov 14 '11 at 13:04
  • 2
    Isn't the ternary backwards? Unless there's something silly that I'm missing, if the first value is less than the second then you should be returning a value <0. I think it should be ```return $ad < $bd ? -1 : 1;``` – John Pancoast Aug 07 '15 at 18:55
  • @JohnPancoast Or just return $ad > $bd ? 1 : -1 – Jaaaaaaay Mar 09 '16 at 04:29
  • @Jaaaaaaay Yea, yours has the same effect as mine but the OPs original was different. – John Pancoast Mar 10 '16 at 06:14
  • 2
    Note: switch -1 and 1 around to change general order to descending – Arnas Ziedavicius Dec 15 '16 at 10:58
  • 3
    I'm glad we can use the spaceship operator `<=>` in PHP 7. :) – Arvid Jan 07 '19 at 14:15
21

For performance, this method using array_multisort is very efficient:

$ord = array();
foreach ($array as $key => $value){
    $ord[] = strtotime($value['dateTime']);
}
array_multisort($ord, SORT_ASC, $array);
print_r($array);
Community
  • 1
  • 1
Expedito
  • 7,771
  • 5
  • 30
  • 43
  • 1
    I was trying to sort an array of datetime objects and this worked great for me. Thanks! I modified it a bit to just be ````array_multisort($array, SORT_ASC, $array);```` – thenomadicmann Oct 28 '20 at 21:18
14

Simple sorting for DateTime objects with the spaceship operator:

$list = [
    new DateTime('yesterday'),
    new DateTime('today'),
    new DateTime('1 week ago'),
];

uasort($list, function ($a, $b) {
    return $a <=> $b;
});

var_dump($list);
Stefan Pöltl
  • 141
  • 1
  • 2
12

Using uasort() with a custom sort callback should do it:

function cmp($a, $b) {
  if ($a['dateTime'] == $b['dateTime']) {
    return 0;
  }

  return ($a['dateTime'] < $b['dateTime']) ? -1 : 1;
}

uasort($arr, 'cmp');

uasort() preserves your array's keys, you can use usort() instead if you don't need that to happen.

Clive
  • 36,918
  • 8
  • 87
  • 113
5

For php array and object this example is helpful for sorting...

For datetime descending:

usort($response_data['callback'], function($a, $b) {
   return strcasecmp(strtotime($b->view_date), strtotime($a->view_date));
});

For datetime ascending:

usort($response_data['callback'], function($a, $b) {
   return strtotime($a->view_date) - strtotime($b->view_date);
});
Nico Haase
  • 11,420
  • 35
  • 43
  • 69
AngularJMK
  • 1,178
  • 13
  • 15
  • I like the subtraction part of your solution. This is pretty neat and (at least for me) better to read than the whole `$a < $b ? -1 : ($a > $b ? 1 : 0)` stuff. … With a current PHP version I'd rather use the spaceship operator `<=>` but in single cases you can't just switch a running project to latest PHP version (as in my current case where the customer has some … "issues" with updating. ;)). – Arvid Jan 07 '19 at 14:14
3

Use array_multisort :

 <?php
        $myarray=array(
                    0 => array
                        (
                            'dateTime' => '2011-10-18 00:0:00',
                            'chanl1' => '20.7',
                            'chanl2' => '45.4',
                            'chanl3' => '',
                        ),

                    1 => array
                        (
                            'dateTime' => '2011-10-18 00:15:00',
                            'chanl1' => '20.7',
                            'chanl2' => '45.4',
                            'chanl3' => '',
                        ),
                  2 => array
                        (
                            'dateTime' => '2011-10-18 00:14:00',
                            'chanl1' => '20.7',
                            'chanl2' => '33.8',
                            'chanl3' => '',
                        ),

                    3 => array
                        (
                            'dateTime' => '2011-10-18 00:29:00',
                            'chanl1' => '20.6',
                            'chanl2' => '33.9',
                            'chanl3' => ''
                        ));

            foreach($myarray as $c=>$key) {
                    $dateTime[] = $key['dateTime'];
                $chanl1[] = $key['chanl1'];
                    $chanl2[] = $key['chanl2'];
                    $chanl3[] = $key['chanl3'];
            }

        array_multisort($dateTime,SORT_ASC,SORT_STRING,$myarray);   
        print_r($myarray);