2
\$\begingroup\$

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 ?

mdfst13
22.4k6 gold badges34 silver badges70 bronze badges
asked Sep 15, 2021 at 13:54
\$\endgroup\$
1
  • \$\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\$ Commented Sep 16, 2021 at 9:00

2 Answers 2

3
\$\begingroup\$

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
);
Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
answered Sep 15, 2021 at 14:01
\$\endgroup\$
2
  • \$\begingroup\$ Thanks for this explanation \$\endgroup\$ Commented 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\$ Commented Sep 17, 2021 at 5:24
0
\$\begingroup\$

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.

answered Sep 15, 2021 at 19:08
\$\endgroup\$
6
  • 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\$ Commented Sep 15, 2021 at 20:31
  • \$\begingroup\$ Thanks. Your answer is really interesting. \$\endgroup\$ Commented 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\$ Commented Sep 16, 2021 at 8:59
  • \$\begingroup\$ Why run another loop after sorting? 3v4l.org/m5hd9 \$\endgroup\$ Commented 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\$ Commented Sep 17, 2021 at 3:34

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.