morne morne - 5 months ago 20
PHP Question

sort multidimensional array by date

I have this

array
:-

array (size=8)
0 =>
array (size=2)
'date' => string '17/05/2016 00:00:00' (length=19)
'reason' => string 'DNA' (length=3)
1 =>
array (size=2)
'date' => string '10/05/2016 00:00:00' (length=19)
'reason' => string 'UTA' (length=3)
2 =>
array (size=2)
'date' => string '03/05/2016 00:00:00' (length=19)
'reason' => string 'DNA' (length=3)
3 =>
array (size=2)
'date' => string '26/04/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
4 =>
array (size=2)
'date' => string '31/05/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
5 =>
array (size=2)
'date' => string '24/05/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
6 =>
array (size=2)
'date' => string '07/06/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
7 =>
array (size=2)
'date' => string '14/06/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)


I want to sort it by 'date'

I tried both of the following methods, but the result ( below )is not sorted correctly.

usort($course, function($a, $b) {
return $a['date'] - $b['date'];
});

_______________________________
function date_compare($a, $b)
{
$t1 = strtotime($a['date']);
$t2 = strtotime($b['date']);
return $t1 - $t2;
}
usort($course, 'date_compare');


This is the "sorted" array

array (size=8)
0 =>
array (size=2)
'date' => string '24/05/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
1 =>
array (size=2)
'date' => string '14/06/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
2 =>
array (size=2)
'date' => string '31/05/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
3 =>
array (size=2)
'date' => string '26/04/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
4 =>
array (size=2)
'date' => string '17/05/2016 00:00:00' (length=19)
'reason' => string 'DNA' (length=3)
5 =>
array (size=2)
'date' => string '03/05/2016 00:00:00' (length=19)
'reason' => string 'DNA' (length=3)
6 =>
array (size=2)
'date' => string '07/06/2016 00:00:00' (length=19)
'reason' => string 'true' (length=4)
7 =>
array (size=2)
'date' => string '10/05/2016 00:00:00' (length=19)
'reason' => string 'UTA' (length=3)

Answer

You need to modify the datetime strings in your $course array in order to make them comparable in the manner that you want.

One (flexible) way to do this is to create DateTime objects from your datetime strings and compare those.

A quick note about datetimes: standard US format m/d/Y uses forward slashes, and standard European format d-m-Y uses hyphens. Your datetime strings are a mixture of both, using forward slashes with European day/month/year ordering.

Therefore you'll have to take an additional step to parse each datetime string into a valid DateTime object.

Static method DateTime::createFromFormat() can help in this regard. For example:

<?php

$course = [
    [
        'date' => '17/05/2016 00:00:00',
        'reason' => 'DNA',
    ],
    [
        'date'   => '10/05/2016 00:00:00',
        'reason' => 'UTA',
    ],
    [
        'date'   => '03/05/2016 00:00:00',
        'reason' => 'DNA',
    ],
    [
        'date'   => '26/04/2016 00:00:00',
        'reason' => 'true',
    ],
    [
        'date'   => '31/05/2016 00:00:00',
        'reason' => 'true',
    ],
    [
        'date'   => '24/05/2016 00:00:00',
        'reason' => 'true',
    ],
    [
        'date'   => '07/06/2016 00:00:00',
        'reason' => 'true',
    ],
    [
        'date'   => '14/06/2016 00:00:00',
        'reason' => 'true',
    ],
];


usort($course, function ($a, $b) {
    $dateA = DateTime::createFromFormat('d/m/Y H:i:s', $a['date']);
    $dateB = DateTime::createFromFormat('d/m/Y H:i:s', $b['date']);
    // ascending ordering, use `<=` for descending
    return $dateA >= $dateB;
});

var_dump($course);

This yields:

Array
(
    [0] => Array
        (
            [date] => 26/04/2016 00:00:00
            [reason] => true
        )

    [1] => Array
        (
            [date] => 03/05/2016 00:00:00
            [reason] => DNA
        )

    [2] => Array
        (
            [date] => 10/05/2016 00:00:00
            [reason] => UTA
        )

    [3] => Array
        (
            [date] => 17/05/2016 00:00:00
            [reason] => DNA
        )

    [4] => Array
        (
            [date] => 24/05/2016 00:00:00
            [reason] => true
        )

    [5] => Array
        (
            [date] => 31/05/2016 00:00:00
            [reason] => true
        )

    [6] => Array
        (
            [date] => 07/06/2016 00:00:00
            [reason] => true
        )

    [7] => Array
        (
            [date] => 14/06/2016 00:00:00
            [reason] => true
        )

)

If your course array is very large, then there may be some overhead in creating DateTime objects on the fly like the example above. YMMV. In this case, I'd consider mapping over the array first and create DateTime objects for each entry, and then apply usort.

Note that with a standard format datetime string, such as European d-m/Y H:i:s, US m/d/Y H:i:s or IS08601 Y-m-d H:i:s, you can simply pass the datetime string as the first value into the DateTime constructor; e.g:

$dt = new DateTime($someStandardFormatDateTimeString);

Apologies about the errant close vote earlier. I've removed that now.

Hope this helps :)