How to sort date array in php?
Asked Answered
B

9

30

I am new to php, I have php date array

[0] => 11-01-2012
[1] => 01-01-2014
[2] => 01-01-2015
[3] => 09-02-2013
[4] => 01-01-2013

I want to sort it like :

[0] => 11-01-2012
[1] => 01-01-2013
[2] => 09-02-2013
[3] => 01-01-2014
[4] => 01-01-2015

I use asort but not working.

Berwick answered 7/11, 2016 at 10:20 Comment(5)
It looks like you are trying to sort strings instead of dates. You should convert your data to real dates (DateTime objects or timestamps); then you can manipulate them very easily.Surfbird
https://mcmap.net/q/365983/-php-order-array-by-date-duplicateVarlet
Possible duplicate of Sorting arrays by dateNumerary
Despite my change to the title, the minimal reproducible example isn't crystal clear about whether the strings are d-m-Y or m-d-Y.Crinose
Sufficient resolving advice for the same task except a 2d array instead of 1d: Sort array of objects by date field. Simply compare the $a and $b instead of trying to access a date property.Crinose
O
67

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

Otoplasty answered 7/11, 2016 at 10:27 Comment(1)
what date format is this assuming? ['03-16-2022', '12-26-2021', '06-06-2022'] will not have correct output.Filamentous
F
3

The example dates data provided aren't clear what format they are. To be sure, you should use DateTime::createFromFormat and then specify the format explicitly:

$dates = ['11-01-2012', '03-16-2022', '12-26-2021', '01-01-2014', '01-01-2015', '09-02-2013', '01-01-2013'];

function sort_date($a, $b) {
    return \DateTime::createFromFormat('m-d-Y', $a) <=> \DateTime::createFromFormat('m-d-Y', $b);
}

usort($dates, "sort_date");
Filamentous answered 21/6, 2022 at 4:56 Comment(1)
C
1

Try below code:

<?php 

$array = array('11-01-2012','01-01-2011','09-02-2013','01-01-2014','01-01-2015');

function cmp($a, $b)
{
    $a = date('Y-m-d', strtotime($a));
    $b = date('Y-m-d', strtotime($b));

    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}
usort($array, "cmp");

foreach ($array as $key => $value) {
    echo "[$key]=> $value <br>";
}
?>
Cohlier answered 7/11, 2016 at 10:33 Comment(1)
Try this (code-only) answers are low value on Stackoverflow because they do very little to educate/empower the OP and future researchers. Please add an explanation of how your solution works and why it is a good idea.Crinose
M
0

out of the box use time function to generate ts and sort

<?php
  $out = array();
  // $your_array is the example obove
  foreach($your_array as $time) {
  $out[strtotime($time)] = $time;
  }
  // now $out has ts-keys and you can handle it

  ...
 ?>

ksort

Miscellanea answered 7/11, 2016 at 10:25 Comment(0)
C
0

Try this,

<?php 
$array = [ '11-01-2012', '01-01-2014', '01-01-2015', '09-02-2013', '01-01-2013' ];
function sortFunction( $a, $b ) {
    return strtotime($a) - strtotime($b);
}
usort($array, "sortFunction");
var_dump( $array );
?>

Will sort the dates into the order you want.

Compte answered 7/11, 2016 at 10:30 Comment(1)
Try this (code-only) answers are low value on Stackoverflow because they do very little to educate/empower the OP and future researchers. Please add an explanation of how your solution works and why it is a good idea.Crinose
C
0

I solved this problem by applying this line.

sort($imdarrayGG['newDate']);

Output before adding the value

[Mon Jul  6 10:33:23 2020] Array
(
    [coursedate] => 2020-07-17
    [newDate] => Array
        (
            [0] => 2020-07-30
            [1] => 2020-07-07
            [2] => 2020-07-08
            [3] => 2020-07-17
        )

)

After I put the line, the output will become like this.

[Mon Jul  6 10:35:42 2020] Array
(
    [coursedate] => 2020-07-17
    [newDate] => Array
        (
            [0] => 2020-07-07
            [1] => 2020-07-08
            [2] => 2020-07-17
            [3] => 2020-07-30
        )

)

The date already sorted which is the latest date will be at the up.

This is where we have object and then we want to sort all of them

Example:-

[status_custom] => Array
    (
        [0] => stdClass Object
            (
                [type] => LDL - B2
                [date] => 23/10/2014
            )

        [1] => stdClass Object
            (
                [type] => LDL - D
                [date] => 18/04/2015
            )
   )

First we have to convert. Refer to this link to convert And then we sort them. Refer to this link to sort object

Here we go:-

    //At here we want to sort according to latest date. But this one involve with the object also.
    usort($array_custom_object, function ($a, $b) {
        $date1 = $a->date;
        $date2 = $b->date;

        //Since the income date is formatted like this d/m/Y , we have to change it
        $date1 = date_format(date_create_from_format('d/m/Y', $date1), 'Y-m-d');
        $date2 = date_format(date_create_from_format('d/m/Y', $date2), 'Y-m-d');

        if ($date1 > $date2) {
            return -1;
        }
        if ($date1 == $date2) {
            return 0;
        }
        if ($date1 < $date2) {
            return 1;
        }
    });
    $dataFinal->status_custom = $array_custom_object; //Result
Chronograph answered 6/7, 2020 at 2:36 Comment(0)
M
-1

use DateTime for sorting date :

$a = array(
    new DateTime('2016-01-02'),
    new DateTime('2016-05-01'),
    new DateTime('2015-01-01'),
    new DateTime('2016-01-01')
);
asort($a);
var_dump($a);

The output would be :

array(4) {
  [2]=>
  object(DateTime)#3 (3) {
    ["date"]=>
    string(26) "2015-01-01 00:00:00.000000"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "US/Pacific"
  }
  [3]=>
  object(DateTime)#4 (3) {
    ["date"]=>
    string(26) "2016-01-01 00:00:00.000000"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "US/Pacific"
  }
  [0]=>
  object(DateTime)#1 (3) {
    ["date"]=>
    string(26) "2016-01-02 00:00:00.000000"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "US/Pacific"
  }
  [1]=>
  object(DateTime)#2 (3) {
    ["date"]=>
    string(26) "2016-05-01 00:00:00.000000"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "US/Pacific"
  }
}
Malinda answered 7/11, 2016 at 10:25 Comment(1)
Your answer here is close if you have a list of DateTime or Carbon date objects. However I believe you have negative down votes because you suggested using asort() instead of sort(), If users use asort() then numerical index references will not reflect the actual sorted list that is dumped.Crummy
H
-1

You definitely can sort array to timestamps with the given code below, but I would like to drag your attention to the format of time I have used to store.. There are different benefits of storing time in such format. Read more about this here https://mcmap.net/q/472528/-dealing-with-timezones-in-php-and-mysql

function compareByTimeStamp($a, $b ) {
    return strtotime($b) - strtotime($a);
}
$arr = array("2020-02-11 00:00:00", "2020-02-13 00:00:00", "2020-02-08 00:00:00"); 
usort($arr, "compareByTimeStamp"); 
echo json_encode($arr);
Harrisonharrod answered 14/2, 2020 at 13:49 Comment(0)
S
-1

Here is some few methods:

$array_to_sort_1 = array(
  "11-01-2012",
  "01-01-2014",
  "01-01-2015",
  "09-02-2013",
  "01-01-2013"
);
fnc_sort_1($array_to_sort_1,"asc","d-m-Y");
// var_dump($array_to_sort_1); // * uncomment to test

$array_to_sort_2 = array(
  array( "user"=>"user1", "date_str"=>"11-01-2012", "comment"=>"1" ),
  array( "user"=>"Donny", "date_str"=>"01-01-2014", "comment"=>"4" ),
  array( "user"=>"Frenk", "date_str"=>"01-01-2015", "comment"=>"5" ),
  array( "user"=>"Axvel", "date_str"=>"01-01-2013", "comment"=>"2" ),
  array( "user"=>"Johny", "date_str"=>"09-02-2013", "comment"=>"3" )
);
fnc_sort_2($array_to_sort_2,"asc","d-m-Y");
// var_dump($array_to_sort_2); // * uncomment to test

$array_to_sort_3 = array(
  array( "user"=>"user1", "date_str"=>"11.01.2012 12:54", "comment"=>"1" ),
  array( "user"=>"Donny", "date_str"=>"01.01.2014 12:54", "comment"=>"4" ),
  array( "user"=>"Frenk", "date_str"=>"01.01.2015 12:54", "comment"=>"5" ),
  array( "user"=>"Johny", "date_str"=>"09.02.2013 12:53", "comment"=>"2" ),
  array( "user"=>"Axvel", "date_str"=>"09.02.2013 12:54", "comment"=>"3" )
);
fnc_sort_2($array_to_sort_3,"asc","d.m.Y H:i");
// var_dump($array_to_sort_3); // * uncomment to test

/** 
 * * DateTime::createFromFormat("d.m.Y H:i", $date_str);
 * * $in_direction ["asc","desc"]
 */
function fnc_sort_1(array &$in_arr, $in_direction = "asc", $in_dt_format = "Y-m-d H:i"){
  usort($in_arr, function($a, $b) use($in_direction,$in_dt_format){
    $v_desc = "desc";
    $v_asc  = "asc";
    $dt_format = "Y-m-d H:i:s";
    $a1 = DateTime::createFromFormat($in_dt_format, $a);
    $b1 = DateTime::createFromFormat($in_dt_format, $b);
    $a2 = $a1->format($dt_format) ;
    $b2 = $b1->format($dt_format) ;
    $a3 = strtotime($a2) ;
    $b3 = strtotime($b2) ;
    if($in_direction===$v_desc){
      return $b3 - $a3; // * Desc
    }else if ($in_direction===$v_asc){
      return $a3 - $b3; // * Asc
    }
    return 0;
  });
}

/** 
 * * DateTime::createFromFormat("d.m.Y H:i", $date_str);
 * * $in_direction ["asc","desc"]
 */
function fnc_sort_2(array &$in_arr, $in_direction = "asc", $in_dt_format = "Y-m-d H:i"){
  usort($in_arr, function($a, $b) use($in_direction,$in_dt_format){
    $v_desc = "desc";
    $v_asc  = "asc";
    $dt_format = "Y-m-d H:i";
    $a1 = DateTime::createFromFormat($in_dt_format, $a["date_str"]);
    $b1 = DateTime::createFromFormat($in_dt_format, $b["date_str"]);
    $a2 = $a1->format($dt_format) ;
    $b2 = $b1->format($dt_format) ;
    $a3 = strtotime($a2) ;
    $b3 = strtotime($b2) ;
    if($in_direction===$v_desc){
      return $b3 - $a3; // * Desc
    }else if ($in_direction===$v_asc){
      return $a3 - $b3; // * Asc
    }
    return 0;
  });
}
Seacock answered 1/5 at 12:52 Comment(4)
Mixing datetime methods with strtotime is completely heinous. I wouldn't recommend this answer to be used anywhere. There are much leaner, more elegant approaches to use.Crinose
@Crinose Maybe you can show these "more elegant approaches to use", because I don't see anything heinous here. I tried to create a universal function that can satisfy more needs, maybe you like "syntactic sugar" more, well that's your preference.Seacock
For starters, using the spaceship operator (<=>) will avoid multiple returns. Declaring $v_desc and $v_asc on each iteration of the callback is completely unnecessary. Hardcoding $dt_format makes the function inflexible. If something needs DESC sorting, then multiple the evaluation of the spaceship operator by -1. You can use DateTime::createFromFormat and pass in a format which will ignore any characters after the minute value. You can sort datetime objects without creating new formatted strings.Crinose
@Crinose Thank you, I will try to take your comments into account in the future.Seacock

© 2022 - 2024 — McMap. All rights reserved.