I have this array with dates. All the dates are checked before creating the array with preg_match
and check_dates
.
GoodDates (
[0] => 2021年09月01日
[1] => 2021年09月02日
[2] => 2021年09月03日
[3] => 2021年09月06日
[4] => 2021年09月07日
[5] => 2021年09月08日
[6] => 2021年09月09日
[7] => 2021年09月10日
[8] => 2021年08月11日
[9] => 2021年09月11日
[10] => 2021年09月12日
[11] => 2021年08月13日
[12] => 2021年08月16日
[13] => 2021年08月17日
[14] => 2021年08月18日
[15] => 2021年08月19日
[16] => 2021年08月20日
[17] => 2021年08月21日
[18] => 2021年08月23日
[19] => 2021年08月24日
[20] => 2021年08月27日
[21] => 2021年08月28日
[22] => 2021年08月29日
[23] => 2021年08月30日
[24] => 2021年08月31日 )
First, I wrote this to rsort
the array $GoodDates
and it works fine.
foreach ($GoodDates as $dateitem){
$strtotimeGoodDates[] = strtotime($dateitem);
}
rsort($strtotimeGoodDates);
foreach ($strtotimeGoodDates as $DatesForstrftime){
$GoodDatesSorted[] = strftime("%Y-%d-%B",$DatesForstrftime);
}
print_r($GoodDatesSorted);
I find this method and it works too.
$compare_function = function($a,$b) {
$a_timestamp = strtotime($a);
$b_timestamp = strtotime($b);
return $b_timestamp <=> $a_timestamp;
};
usort($GoodDates, $compare_function);
print_r($GoodDates);
Is my solution a good practice or it is better to use usort
and why ?
2 Answers 2
Your date format is Y-m-d
which means that you can safely sort these values as simple strings.
rsort()
is all that you require. A native function will always be more concise and efficient than a custom (non-native) function.
If your date string were not zero-padded or the date units were not arranged with descending unit values, then additional work would be required.
If the date format was, say, d.m.Y
, then strtotime()
would standardize/stabilize the values.
usort($GoodDates, fn($a, $b) => strtotime($b) <=> strtotime($a));
Or
array_multisort(
array_map('strtotime',$GoodDates),
SORT_DESC,
$GoodDates
);
-
\$\begingroup\$ Thanks for this explanation \$\endgroup\$Nasty Phoenix– Nasty Phoenix2021年09月15日 14:38:22 +00:00Commented Sep 15, 2021 at 14:38
-
\$\begingroup\$ @NastyPhoenix If I were obsessed with performance, which of course may be premature, I'd say that parsing those dates with strtotime in the usort callback is an issue. Whatever the sort implementation, Instead of parsing each of the n date strings once, you parse some of them (probably most of them) multiple times - the number of parsing is proportional to the sort time complexity which is no better then O(n * log(n)) in worst case. \$\endgroup\$slepic– slepic2021年09月17日 05:24:45 +00:00Commented Sep 17, 2021 at 5:24
You could also use the PHP DateTime
class together with array_map. This would remove the need for checking dates and writing your own sort function.
<?php
$input = [
"2021年01月01日",
"2019年05月23日",
"2022年09月13日",
];
$dates = array_map(
function (string $dateString) {
// Also validates the input, no need for pregmatch
return new \DateTimeImmutable($dateString);
},
$input
);
sort($dates); // Use rsort() for descending order
$output = array_map(
function (\DateTimeImmutable $date) {
return $date->format("Y-m-d");
},
$dates
);
var_dump($output);
I do not know about performance, but this seems more
PHP fiddle of this working.
-
1\$\begingroup\$ Hi. Welcome to Code Review! Note that answers that concentrate on the code to be reviewed explicitly are often received better here. Here, you implicitly suggest that the code does more work than necessary to check the dates. You might consider editing to make that observation explicit, grounded in the code from the question. Note: I'm not suggesting that you remove anything from the existing answer. Everything that is here is perfectly appropriate. I'm just saying that you might want to add an explicit observation about the existing code. \$\endgroup\$mdfst13– mdfst132021年09月15日 20:31:11 +00:00Commented Sep 15, 2021 at 20:31
-
\$\begingroup\$ Thanks. Your answer is really interesting. \$\endgroup\$Nasty Phoenix– Nasty Phoenix2021年09月16日 08:23:28 +00:00Commented Sep 16, 2021 at 8:23
-
\$\begingroup\$ With all your answers - I can delete my
checkdate
loop. - I have a better comprehension of how to sort a date array and some differents methods to do that. Thanks to everybody. \$\endgroup\$Nasty Phoenix– Nasty Phoenix2021年09月16日 08:59:56 +00:00Commented Sep 16, 2021 at 8:59 -
\$\begingroup\$ Why run another loop after sorting? 3v4l.org/m5hd9 \$\endgroup\$mickmackusa– mickmackusa2021年09月16日 10:28:23 +00:00Commented Sep 16, 2021 at 10:28
-
1\$\begingroup\$ @mickmackusa Here are the reasons which made me choose 2 loops: 1. With an array of
DateTimeImmutable
, one could perform other operations with the dates. 2. A second loop would not cause a huge performance cost. From O(n) to O(2n) \$\endgroup\$mariosimao– mariosimao2021年09月17日 03:34:02 +00:00Commented Sep 17, 2021 at 3:34
checkdate
loop. - I have a better comprehension of how to sort a date array and some differents methods to do that. Thanks to everybody. \$\endgroup\$