12

First of all i'm a complete newbie to this, i have searched for solutions but none seem to do the trick.

So I am trying to sort this JSON array by date but i don't really know i should tackle this, any tips in the right direction are much appreciated!

["info":[
{"id":1, "title":"original title", "name":"john doe", "date":"2010-05-15"}, 
{"id":2, "title":"another title", "name":"foo bar", "date":"2009-04-11"},
...

So i'm getting the data like this

$data=file_get_contents('jsondata...');
$d=json_decode($data,true);

I would like to sort the data by date, any ideas how i should approach this? Is it also possible to return the year value only? So the output would be 2009 instead of 2009-04-11?

Thanks in advance

xtoffer
  • 121
  • 1
  • 1
  • 3
  • Use `strtotime` to turn it into a number and then sort by that? – Madara's Ghost Mar 21 '12 at 16:28
  • How deep have you tried to dig into this? It doesn't seem like you've really tried to do what you're asking us to help you with. – Brian Driscoll Mar 21 '12 at 16:30
  • @BrianDriscoll i have been playing with it for the past 2 days, i have read and tried many of the solutions i found on others questioning the same issue but i've probably been applying it wrongly since i am still very new to this. Sorry for asking help. – xtoffer Mar 21 '12 at 17:21

4 Answers4

23

You can use usort and a custom comparison function:

$data = '{"info":[{"id":1, "title":"original title", "name":"john doe", "date":"2010-05-15"}, {"id":2, "title":"another title", "name":"foo bar", "date":"2009-04-11"}]}';

$info = json_decode($data, true)['info'];

usort($info, function ($a, $b) {
    return $a['date'] <=> $b['date'];
});

<=> works on strings here because a string comparison is also a date comparison when your dates are formatted as YYYY-MM-DD.

Then, to show the year value for an entry, you can parse the date into a DateTime and reformat it:

$date = DateTime::createFromFormat('Y-m-d', $item['date']);
$year = $date->format('Y');

Here's a demo.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Thank you so much for this, got it working now! Thanks for your effort to explain this! I really appreciate it – xtoffer Mar 21 '12 at 17:15
  • 2
    @xtoffer You should accept an answer as correct so you don't just appreciate their effort to help you, but you can also help someone like me who has the same issue as you and I try to find out which answer from here is the correct one! Thank you in advance! – Laci May 10 '14 at 07:55
  • Note: As of PHP 5.2.2, DateTime objects can be compared using comparison operators, so you should just be able to `return ($dA > $dB)` – joshuahedlund Jul 09 '18 at 15:25
  • @joshuahedlund: `usort` doesn’t expect a boolean return, but you’re right, it doesn’t make much sense to compare only the year even if you only show the year. – Ry- Jul 09 '18 at 15:41
  • Does this work on large lists? or just lists of two? – user982853 Sep 12 '19 at 23:24
0

You have to convert the date to a sortable format first. I think that strtotime() does the job. After that you can output whatever with strftime().

Frank van Wijk
  • 3,234
  • 20
  • 41
0

Use uasort to sort the array with user-defined function and strtotime to parse the date to timestamp.

$json = '
    {"info":[
        {"id":1, "title":"original title", "name":"john doe", "date":"2010-05-15"}, 
        {"id":2, "title":"another title", "name":"foo bar", "date":"2009-04-11"}
        ]
    }';

$arr = json_decode($json)->info;
uasort($arr, function($item1, $item2){
    return strtotime($item1->date) > strtotime($item2->date);
});

Will output

Array
(
    [1] => stdClass Object
        (
            [id] => 2
            [title] => another title
            [name] => foo bar
            [date] => 2009-04-11
        )

    [0] => stdClass Object
        (
            [id] => 1
            [title] => original title
            [name] => john doe
            [date] => 2010-05-15
        )

)
cypher
  • 6,822
  • 4
  • 31
  • 48
  • You also don't need `uasort` because the keys are numeric, and ordering them maintaining the numeric keys can be incredibly confusing (in your output, `0` comes after `1`). – Ry- Mar 21 '12 at 16:42
  • Yes, it does and does so because I want it to. I don't want to modify the array any more then it's necessary for no reason. What if the key is actually important? – cypher Mar 21 '12 at 16:46
  • I'll bet you $50 that the OP does not want item 1 to come before item 0 in the array, especially since it wasn't associative to begin with ;) – Ry- Mar 21 '12 at 16:49
  • You can bet me whatever you want, I'm not changing indexes just because I think that I can. – cypher Mar 21 '12 at 16:51
  • *Sigh* I don't think you understand how ridiculous having an array in that order with those keys is. But whatever. – Ry- Mar 21 '12 at 16:52
  • Does it sound more riddiculous then relying on "1 comes after 0"? That can get even more confusing. – cypher Mar 21 '12 at 16:56
  • Yes, it does. I'm sorry, but look - you're arguing that relying on 1 coming after 0 is ridiculous. 1 comes after 0. It's not confusing, it's math. – Ry- Mar 21 '12 at 17:01
  • Math has nothing to do with it, we're talking about a hash map (yes, in PHP, array is an ordered hash map). In hash map, the key has no ordering meaning. Let's make a pros and cons list: + Both functions order an array. - With usort, you reindex the array for no valid reason. Now what would confuse me? I'll do `echo $array[0]; //prints Foo usort($array); echo $array[0]; //prints Bar` Of course, there's a case when I want to get the first element. Wait, that should be done with [reset](http://php.net/manual/en/function.reset.php). I see no reason for changing indexes when I don't need to. – cypher Mar 21 '12 at 17:12
0

Something like the following should get you started:

<?php

function sortDate($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
}

$input = array('info' => array(array('id' => 2, 'date' => '2019-04-11'), array('id' => 1, 'date' => '2010-05-15')));

usort($input['info'], 'sortDate');
print_r($input);
Andreas Wong
  • 59,630
  • 19
  • 106
  • 123