Neeraj Sharma
Neeraj Sharma

Reputation: 346

Sort a 2d array by a date column formatted as d/m/Y

I have an array and I want to sort it by date. I am not able to sort it properly by date in descending order. Please help.

Array
(
[1] => Array
    (
        [1] => 11/05/2013
        [2] => Executive Planning Day
    )

[2] => Array
    (
        [1] => 13/06/2013
        [2] => Middle Leaders Planning Day
    )

[3] => Array
    (
        [1] => 12/07/2013
        [2] => New Staff Induction Day
    )

[4] => Array
    (
        [1] => 13/04/2013
        [2] => Staff Conference Day No. 1
    )

[5] => Array
    (
        [1] => 14/04/2013
        [2] => Staff Conference Day No. 2
    )

[6] => Array
    (
        [1] => 15/02/2013
        [2] => Staff Conference Day No. 3
    )

[7] => Array
    (
        [1] => 16/03/2013
        [2] => Australia Day
    )
)

Upvotes: 9

Views: 57942

Answers (11)

Sébastien Gicquel
Sébastien Gicquel

Reputation: 4386

Here is a working example with the spaceship operator <=>

    $array = Array(
        Array(
            "id" => "1",
            "date_time_rdv" => "2018-02-22 11:29:35",
        ),
        Array(
            "id" => "2",
            "date_time_rdv" => "2020-02-13 10:05:25",
        ),
        Array(
            "id" => "3",
            "date_time_rdv" => "2019-02-15 22:18:45",
        )
    );

    function date_compare($a, $b) {
        $format = 'Y-m-d H:i:s';
        $d1 = DateTime::createFromFormat($format, $a['date_time_rdv']);
        $d2 = DateTime::createFromFormat($format, $b['date_time_rdv']);
        return $d2 <=> $d1;
    }

    usort($array, 'date_compare');

It will output :

Array
(
    [0] => Array
        (
            [id] => 2
            [date_time_rdv] => 2020-02-13 10:05:25
        )

    [1] => Array
        (
            [id] => 3
            [date_time_rdv] => 2019-02-15 22:18:45
        )

    [2] => Array
        (
            [id] => 1
            [date_time_rdv] => 2018-02-22 11:29:35
        )

)

If you use uasort() instead, it will output this (it will maintain index association)

Array
(
    [1] => Array
        (
            [id] => 2
            [date_time_rdv] => 2020-02-13 10:05:25
        )

    [2] => Array
        (
            [id] => 3
            [date_time_rdv] => 2019-02-15 22:18:45
        )

    [0] => Array
        (
            [id] => 1
            [date_time_rdv] => 2018-02-22 11:29:35
        )

)

If you try return $d1 <=> $d2;, it will reverse the order.

In date_compare(), we use DateTime::createFromFormat which parses a time string according to a specified format. You could use the format you need, like in the op question dd/mm/YYYY

More info on DateTime::createFromFormat :

Upvotes: 1

Sagan
Sagan

Reputation: 112

so do it like this:

//your array


$arr = array();
array_push($arr, array("11/05/2013", "Executive Planning Day"));
array_push($arr, array("13/06/2013", "Middle Leaders Planning Day"));
array_push($arr, array("12/07/2013", "New Staff Induction Day"));
array_push($arr, array("13/04/2013", "Staff Conference Day No. 1"));
array_push($arr, array("14/04/2013", "Staff Conference Day No. 2"));
array_push($arr, array("15/02/2013", "Staff Conference Day No. 3"));
array_push($arr, array("16/03/2013", "Australia Day"));


var_dump($arr);

function sortDateDesc($a, $b){  
    $strA = implode("-", array_reverse( explode("/", $a[0]) ) ); 
    $strB = implode("-", array_reverse( explode("/", $b[0]) ) ); 

    return strtotime($strB) - strtotime($strA);
}



usort($arr, "sortDateDesc");

var_dump($arr);

If your date format is constant day/month/year then you need to pass it in a string format recognized by the parser and year-month-day is an ISO standard if I remember it well, that one works fine

Upvotes: 1

Ahmad Sayeed
Ahmad Sayeed

Reputation: 354

I jumped here for associative array sorting and found this amazing function on http://php.net/manual/en/function.sort.php. This function is very dynamic that sort in ascending and descending order with specified key.

Simple function to sort an array by a specific key. Maintains index association.

<?php

function array_sort($array, $on, $order=SORT_ASC)
{
    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
            break;
            case SORT_DESC:
                arsort($sortable_array);
            break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

$people = array(
    12345 => array(
        'id' => 12345,
        'first_name' => 'Joe',
        'surname' => 'Bloggs',
        'age' => 23,
        'sex' => 'm'
    ),
    12346 => array(
        'id' => 12346,
        'first_name' => 'Adam',
        'surname' => 'Smith',
        'age' => 18,
        'sex' => 'm'
    ),
    12347 => array(
        'id' => 12347,
        'first_name' => 'Amy',
        'surname' => 'Jones',
        'age' => 21,
        'sex' => 'f'
    )
);

print_r(array_sort($people, 'age', SORT_DESC)); // Sort by oldest first
print_r(array_sort($people, 'surname', SORT_ASC)); // Sort by surname

Upvotes: 2

jmontross
jmontross

Reputation: 3583

I spent a night working on how to do this for my own similar issue. To sort an associative array by date of a key in that array.

Both usort and uasort require a sort function that you must write and pass as the second parameter. The sort function is used by usort and uasort to compare each item in the array and store the result as $yourArray

 function sortFunction( $a, $b ) {
           return strtotime($a[1]) - strtotime($b[1]);
 }

 uasort($yourArray, "sortFunction");



 

Upvotes: 3

Masud Ahmed
Masud Ahmed

Reputation: 1

$sortdate = array(
    '17/08/2015',
    '02/01/2017',
    '05/02/2014'
);

function sortFunction($a, $b)
    {
    $datea = strtotime(str_replace('/', '-', $a));
    $dateb = strtotime(str_replace('/', '-', $b));
    if ($datea == $dateb)
        {
        return 0;
        }

    return ($datea < $dateb) ? -1 : 1;
    }

usort($sortdate, "sortFunction");
echo "<pre>";
var_dump($sortdate);

Upvotes: 0

JokiRuiz
JokiRuiz

Reputation: 311

The solution of @Gautam3164 is almost perfect. You need to change the format of the dates. I'd say:

function sortFunction( $a, $b ) {
    return strtotime(str_replace('/', '-',$a[1])) - strtotime(str_replace('/', '-',$b[1]));
}
usort($data, "sortFunction");   //Here You can use asort($data,"sortFunction")

11/10/1987 -> 10 Nov 1987 11-10-1987 -> 11 Oct 1987

Upvotes: 0

Emissary
Emissary

Reputation: 10148

Not entirely happy with all of the answers here so I thought I'd mention that if you wish to sort an associative array preserving the keys then you should use uasort rather than usort. You can also parse the date from any format you like with the DateTime library which also includes some predefined constants for some of the standard formats.

uasort($array, function($a, $b){ 
    $format = 'd/m/Y'; 
    $ascending = false;
    $zone = new DateTimeZone('UTC');
    $d1 = DateTime::createFromFormat($format, $a[1], $zone)->getTimestamp();
    $d2 = DateTime::createFromFormat($format, $b[1], $zone)->getTimestamp();
    return $ascending ? ($d1 - $d2) : ($d2 - $d1);
});

demo

Upvotes: 2

GautamD31
GautamD31

Reputation: 28763

Try like this

function sortFunction( $a, $b ) {
    return strtotime($a[1]) - strtotime($b[1]);
}
usort($data, "sortFunction");   //Here You can use asort($data,"sortFunction")

or you may try by detail like(its just suggestion)

function sortFunction($a,$b)
    if ($a[1] == $b[1]) return 0;
    return strtotime($a[1]) - strtotime($b[1]);
}
usort($data,"sortFunction");

As the strtotime is not obey d/m/Y format try like this

$orderByDate = $my2 = array();
foreach($data as $key=>$row)
{
    $my2 = explode('/',$row[1]);
    $my_date2 = $my2[1].'/'.$my2[0].'/'.$my2[2];        
    $orderByDate[$key] = strtotime($my_date2);  
}    
array_multisort($orderByDate, SORT_DESC, $data);

Upvotes: 22

Vedran Šego
Vedran Šego

Reputation: 3765

Use usort() function:

function cmp($a, $b) {
    if ($a[1] == $b[1]) return 0;
    return (strtotime($a[1]) < strtotime($b[1])) ? 1 : -1;
}

usort($data, "cmp");

Upvotes: 2

Vivek Sadh
Vivek Sadh

Reputation: 4268

Use usort(Sort an array by values using a user-defined comparison function).

usort($array, function($a1, $a2) {
   $value1 = strtotime($a1['date']);
   $value2 = strtotime($a2['date']);
   return $value1 - $value2;
});

Upvotes: 2

Ven
Ven

Reputation: 19039

I'd build an array for ordering.

$ordered = array();
foreach ($planning as $event) {
  $ordered[$event['date']] = $event;
}
ksort($ordered);

Upvotes: 1

Related Questions