PHP Sort a Multidimensional Array by Element Containing Y-M-D H:I:S Date

PHP Sort a multidimensional array by element containing Y-m-d H:i:s date

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 a a 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.

sort multidimensional array by date

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 US-style 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 before comparing.

Static method DateTime::createFromFormat() can help in this regard. For example, given an array called $course:

$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',
],
];

You can then apply a callback with usort() which converts the date value of each comparison object into a valid DateTime() objects before comparing them:

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;
});

print_r($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 instead; e.g:

$dt = new DateTime($someStandardFormatDateTimeString);

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

Hope this helps :)

How to sort multidimensional array by date?

Use uksort. You can make your own compare function. There you could convert key into timestamp and compare.

You can change order direction

return $a > $b; // order ASC
return $a < $b; // order DESC

Your code should look like:

function cmp($a, $b)
{
$a = strtotime($a);
$b = strtotime($b);
return $a > $b;
}

uksort($data, "cmp");

See DEMO

OUTPUT

Array
(
[September 2, 2015] => Array
(
[admin] => Array
(
[checkin] => 2
[checkout] => 1
)

)

[September 3, 2015] => Array
(
[admin] => Array
(
[checkin] => 2
[checkout] => 2
)

)

[September 4, 2015] => Array
(
[admin] => Array
(
[checkin] => 1
[checkout] => 1
)

)

[September 5, 2015] => Array
(
[admin] => Array
(
[checkin] => 1
[checkout] => 1
)

)

[September 6, 2015] => Array
(
[admin] => Array
(
[checkin] => 2
[checkout] => 2
)

)

[September 7, 2015] => Array
(
[admin] => Array
(
[checkin] => 1
[checkout] => 1
)

)

[September 8, 2015] => Array
(
[admin] => Array
(
[checkin] => 1
[checkout] => 0
)

)

[October 8, 2015] => Array
(
[admin] => Array
(
[checkin] => 1
[checkout] => 0
)

)

)

How to sort a 3 dimensional array by element containing date, from newest to oldest

You can do this as a two-stage process. First, use array_walk with array_multisort to sort the inner arrays by datetime. Then use usort, comparing the maximum datetime values from the inner arrays:

array_walk($arr, function (&$v) { array_multisort(array_column($v, 'datetime'), SORT_DESC, $v); });
usort($arr, function ($a, $b) {
return strcmp(max(array_column($b, 'datetime')), max(array_column($a, 'datetime')));
});
print_r($arr);

Output:

Array
(
[0] => Array
(
[0] => Array
(
[personNum] => 4
[type] => status
[datetime] => 2019-05-26 16:04:24
)
[1] => Array
(
[personNum] => 3
[type] => status
[datetime] => 2019-05-26 15:59:53
)
)
[1] => Array
(
[0] => Array
(
[personNum] => 3
[type] => status
[datetime] => 2019-05-26 15:59:53
)
[1] => Array
(
[personNum] => 2
[type] => comment
[datetime] => 2019-05-15 11:29:45
)
)
)

Demo on 3v4l.org

Sort multidimensional array according to date values in in two elements?

I'm not sure if understood correctly but you mean you want sort your array base on column1 ("post date") and if these values are equal order is determined by column2. So, what you need is just fix your comparing function:

function date_compare($a, $b)
{
$t1 = strtotime($a['datetime']);
$t2 = strtotime($b['datetime']);
if ($t1 != $t2) {
return $t1 - $t2;
}

// if "post dates" are equal, compare "edit dates"
$t1 = strtotime($a['datetime2']);
$t2 = strtotime($b['datetime2']);

return $t1 - $t2;
}

edit:

ok, according to your comment, you just need to pick up max element from your array. So, this should work:

usort($array, function($a, $b) {
$t1 = max(strtotime($a[0]), strtotime($a[1]));
$t2 = max(strtotime($b[0]), strtotime($b[1]));

return $t1 - $t2;
});

How to sort date array in php?

If the date is in "Mysql" format (Y-m-d or Y-m-d H:i:s), then you can sort your array right away, no special action needed:

$arr = ["2019-11-11", "2019-10-10","2019-11-11", "2019-09-08","2019-05-11"];
sort($arr);

If the date is localized or formatted anyhow (that you should avoid, formatting the date only before output) you have to use a custom sorting function, such as usort(), that will convert the dates into sortable format before comparison.

The simplest way to convert a date into sortable format is to convert it into uninx timestamp using strtotime() function:

$arr = ['11/01/2012', '03/16/2022', '12/26/2021', '01/01/2014', '09/02/2013'];
usort($arr, function ($a, $b) {
return strtotime($a) - strtotime($b);
});
print_r($arr);

Check result in demo

However, there could be pitfalls, because in different countries the same date format could mean a different date. Which is exactly the case with your example format, for which the above function will return wrong results if dates are ['03-16-2022', '12-26-2021', '06-06-2022']. Therefore it's better to define the date format explicitly, as explained in this answer



Related Topics



Leave a reply



Submit