I have an array such as:
Array
(
[0] => Array
(
[id] => 2
[type] => comment
[text] => hey
[datetime] => 2010-05-15 11:29:45
)
[1] => Array
(
[id] => 3
[type] => status
[text] => oi
[datetime] => 2010-05-26 15:59:53
)
[2] => Array
(
[id] => 4
[type] => status
[text] => yeww
[datetime] => 2010-05-26 16:04:24
)
)
Can anyone suggest a way to sort/order this based on the datetime element?
Use usort()
and a custom comparison function:
function date_compare($a, $b)
{
$t1 = strtotime($a['datetime']);
$t2 = strtotime($b['datetime']);
return $t1 - $t2;
}
usort($array, 'date_compare');
EDIT : Your data is organized in an array of arrays. To better distinguish those, let's call the inner arrays (data) records, so that your data really is an array of records.
usort
will pass two of these records to the given comparison function date_compare()
at aa time. date_compare
then extracts the "datetime"
field of each record as a UNIX timestamp (an integer), and returns the difference, so that the result will be 0
if both dates are equal, a positive number if the first one ( $a
) is larger or a negative value if the second argument ( $b
) is larger. usort()
uses this information to sort the array.
This should work. I converted the date to unix time via strtotime.
foreach ($originalArray as $key => $part) {
$sort[$key] = strtotime($part['datetime']);
}
array_multisort($sort, SORT_DESC, $originalArray);
One-liner version would be using multiple array methods:
array_multisort(array_map('strtotime',array_column($originalArray,'datetime')),
SORT_DESC,
$originalArray);
From php7 you can use the Spaceship operator :
usort($array, function($a, $b) {
return new DateTime($a['datetime']) <=> new DateTime($b['datetime']);
});
$array = Array
(
[0] => Array
(
[id] => 2
[type] => comment
[text] => hey
[datetime] => 2010-05-15 11:29:45
)
[1] => Array
(
[id] => 3
[type] => status
[text] => oi
[datetime] => 2010-05-26 15:59:53
)
[2] => Array
(
[id] => 4
[type] => status
[text] => yeww
[datetime] => 2010-05-26 16:04:24
)
);
print_r($array);
$name = 'datetime';
usort($array, function ($a, $b) use(&$name){
return $a[$name] - $b[$name];});
print_r($array);
http://us2.php.net/manual/en/function.array-multisort.php see third example:
<?php
$data[] = array('volume' => 67, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 1);
$data[] = array('volume' => 85, 'edition' => 6);
$data[] = array('volume' => 98, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 6);
$data[] = array('volume' => 67, 'edition' => 7);
foreach ($data as $key => $row) {
$volume[$key] = $row['volume'];
$edition[$key] = $row['edition'];
}
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
?>
fyi, using a unix (seconds from 1970) or mysql timestamp (YmdHis - 20100526014500) would be be easier for the parser but i think in your case it makes no difference.
You can simply solve this problem using usort() with callback function. No need to write any custom function.
$your_date_field_name = 'datetime';
usort($your_given_array_name, function ($a, $b) use (&$your_date_field_name) {
return strtotime($a[$your_date_field_name]) - strtotime($b[$your_date_field_name]);
});
Sorting array of records/assoc_arrays by specified mysql datetime field and by order:
function build_sorter($key, $dir='ASC') {
return function ($a, $b) use ($key, $dir) {
$t1 = strtotime(is_array($a) ? $a[$key] : $a->$key);
$t2 = strtotime(is_array($b) ? $b[$key] : $b->$key);
if ($t1 == $t2) return 0;
return (strtoupper($dir) == 'ASC' ? ($t1 < $t2) : ($t1 > $t2)) ? -1 : 1;
};
}
// $sort - key or property name
// $dir - ASC/DESC sort order or empty
usort($arr, build_sorter($sort, $dir));
I came across to this post but I wanted to sort by time when returning the items inside my class and I got an error.
So I research the php.net website and end up doing this:
class MyClass {
public function getItems(){
usort( $this->items, array("MyClass", "sortByTime") );
return $this->items;
}
public function sortByTime($a, $b){
return $b["time"] - $a["time"];
}
}
You can find very useful examples in the PHP.net website
My array looked like this:
'recent' =>
array
92 =>
array
'id' => string '92' (length=2)
'quantity' => string '1' (length=1)
'time' => string '1396514041' (length=10)
52 =>
array
'id' => string '52' (length=2)
'quantity' => string '8' (length=1)
'time' => string '1396514838' (length=10)
22 =>
array
'id' => string '22' (length=2)
'quantity' => string '1' (length=1)
'time' => string '1396514871' (length=10)
81 =>
array
'id' => string '81' (length=2)
'quantity' => string '2' (length=1)
'time' => string '1396514988' (length=10)
For those still looking a solved it this way inside a class with a function sortByDate, see the code below
<?php
class ContactsController
{
public function __construct()
{
//
}
function sortByDate($key)
{
return function ($a, $b) use ($key) {
$t1 = strtotime($a[$key]);
$t2 = strtotime($b[$key]);
return $t2-$t1;
};
}
public function index()
{
$data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-11 12:38:23','created_at' =>'2020-06-11 12:38:23');
$data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-16 12:38:23','created_at' =>'2020-06-10 12:38:23');
$data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-7 12:38:23','created_at' =>'2020-06-9 12:38:23');
usort($data, $this->sortByDate('updated_at'));
//usort($data, $this->sortByDate('created_at'));
echo $data;
}
}
For 'd/m/Y'
dates:
usort($array, function ($a, $b, $i = 'datetime') {
$t1 = strtotime(str_replace('/', '-', $a[$i]));
$t2 = strtotime(str_replace('/', '-', $b[$i]));
return $t1 > $t2;
});
where $i
is the array index
Most of the earlier answers failed to acknowledge the available shortcut of comparing the datetime values as simple strings. Other answers that realized that strtotime()
was unnecessary did not spell out why did what they did ...so I will.
Because your datetime
values are formatted with units in descending size ( Y
, m
, d
, H
, i
, s
) AND because each unit is consistently expressed with the same number of characters (4, 2, 2, 2, 2, 2) AND because the delimiting characters are all identical from string to string, you can simply compare them character-by-character from left to right (naturally). This would not be true for a date string formatted as, say, d/m/Y
.
There are two functions that are ideal for this task, I'll demonstrate ASC and DESC versions for both.
usort() by date column DESC:
usort($array, function($a, $b) { return $b['datetime'] <=> $a['datetime']; });
usort() by date column ASC:
usort($array, function($a, $b) { return $a['datetime'] <=> $b['datetime']; });
usort() by date column ASC in >= PHP7.4:
usort($array, fn($a, $b) => $a['datetime'] <=> $b['datetime']);
array_multisort() by date column DESC:
array_multisort(array_column($array, 'datetime'), SORT_DESC, $array);
array_multisort() by date column ASC:
array_multisort(array_column($array, 'datetime'), $array);
All of these techniques modify by reference, so the function provide no real valuable return value.
array_multisort()
:
usort()
:
$a
before $b
(on either side of the spaceship operator) means ASC and $b
before $a
means DESCuasort()
insteadFor anyone who truly DOES need a date or datetime string to be parsed because its format does not permit instant string comparisons, here is an answer devoted to explaining the caveats of that task .
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.