Sort array of objects by date field
Asked Answered
I

6

26

How can I re-arrange a array of objects like this:

 [495] => stdClass Object
        (
         [date] => 2009-10-31 18:24:09
         ...
        )
 [582] => stdClass Object
        (
         [date] => 2010-2-11 12:01:42
         ...
        )
 ...

by the date key, oldest first ?

Infelicity answered 19/8, 2011 at 21:46 Comment(0)
Z
53
usort($array, function($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
});

Or if you don't have PHP 5.3:

function cb($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
}
usort($array, 'cb');
Zonazonal answered 19/8, 2011 at 21:48 Comment(2)
Looks good, and I'd recommend to the OP to do the date/time sorting in the database, and/or return a plain unix timestamp along with the formatted value, as strtotime() has CONSIDERABLE overhead and would make repeated sorting very expensive.Bioclimatology
replace usort by uasort thenZonazonal
B
24

Since the original question is about sorting arrays of stdClass() objects, here's the code which would work if $a and $b are objects:

usort($array, function($a, $b) {
    return strtotime($a->date) - strtotime($b->date);
});

Or if you don't have PHP 5.3:

function cb($a, $b) {
    return strtotime($a->date) - strtotime($b->date);
}
usort($array, 'cb');
Bearce answered 22/4, 2013 at 11:27 Comment(0)
K
4

I wanted to expand on arnaud576875's answer. I ran across this same issue, but with using DateTime objects. This is how I was able to accomplish the same thing.

usort($array, function($a, $b) {
    return $a['date']->format('U') - $b['date']->format('U');
});
Kenner answered 22/1, 2013 at 20:55 Comment(1)
Are you calling the format() method on a string value? This answer feels misleading to researchers. The OP's sample data is an array of objects, not an array of arrays.Communize
C
2

Because your month -- and possibly your day -- values are not zero-padded, you cannot instantly compare the dates as simple strings. You should use strtotime() to convert the dates to unix time integers -- these will be suitable for reliable comparisons.

Also, it seems important to not lose the associative relationship between the first level keys and their objects. To sort and retain the keys, call uasort(). In modern php, the spaceship operator is the go-to utility for making 3-way comparisons (returns -1, 0, or 1).

All approaches below will work identically even if the 2d array is an array of arrays instead of an array of objects (you'll only need to change the ->date syntax to ['date'].

Code:

uasort(
    $array,
    function($a, $b) {
        return strtotime($a->date) <=> strtotime($b->date);
    }
);

Or in PHP7.4, there is arrow function syntax:

uasort(
    $array,
    fn($a, $b) => strtotime($a->date) <=> strtotime($b->date)
);

The only minor drawback with using function calls in u*sort()'s body is that it will do greater than n sets of function calls to break ties and otherwise determine the correct order. An alternative sorting technique that avoids these redundant function calls is array_multisort(). It can be fed a column of data which has had exactly n function calls performed -- this effectively makes it more efficient. However, this sorting function has its own caveat -- it will lose the numeric first level keys. This is probably not a tolerable loss for this case.

Code:

array_multisort(
    array_map('strtotime', array_column($array, 'date')),
    $array
);

Here is a demo of both techniques.

For anyone who is sorting date, time, or datetime values that can be naturally compared as basic strings (so-called Big-endian formats such as Y-m-d H:i:s, H:i, m/d, Y-m-d, etc., then see this answer for more efficient techniques.

Communize answered 15/4, 2021 at 12:32 Comment(0)
P
0

I wanted to expand on arnaud576875 and Michael Irigoyen.

Same issue with object containing dateTime with Symphony.

I coudn't use $a['date'] because it was not an key array.

usort($verifications, function($a, $b) {
   return $a->getDate()->format('U') - $b->getDate()->format('U');
});

This solved my problem

Pleuro answered 14/6, 2018 at 9:34 Comment(0)
D
0

When working with DateTime objects as properties of your Entity, this worked for me:

$myArray = $entityRepository->findAll();

usort($myArray, function($a, $b) {
    return $a->getDate()->getTimestamp() - $b->getDate()->getTimestamp();
        });
Deed answered 3/12, 2021 at 16:15 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Halloran

© 2022 - 2024 — McMap. All rights reserved.