0

I have this multidimentional array :

[
    {
        "Id": 14,
        "ClassDate": "2019-09-20T00:00:00",
        "StartTime": "06:00:00"
    },
    {
        "Id": 27,
        "ClassDate": "2019-09-20T00:00:00",
        "StartTime": "07:45:00"
    },
    {
        "Id": 144,
        "ClassDate": "2019-09-21T00:00:00",
        "StartTime": "05:00:00"
    },
    {
        "Id": 170,
        "ClassDate": "2019-09-21T00:00:00",
        "StartTime": "08:45:00"
    },

]

I want to sort this array values by date and then same date values by time.

This is the code I have which sorts the values by only date

function cmp($a, $b) {
    $a = strtotime($a['ClassDate']);
    $b = strtotime($b['ClassDate']);

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

Do anyone have a solution for this? I am sure I am the 1 millionth one to do this...

Shujaat Shaikh
  • 189
  • 1
  • 5
  • 17
  • I am making a list where I wanna show the classes in descending order – Shujaat Shaikh Sep 19 '19 at 13:55
  • 1
    In case the two items are equal regarding their date, then you must not return 0 at that point, but check your second criterion, and base the return value on that. – 04FS Sep 19 '19 at 13:56
  • Possible duplicate of [Sort array using multiple criteria in PHP](https://stackoverflow.com/questions/24559050/sort-array-using-multiple-criteria-in-php) – 04FS Sep 19 '19 at 13:57
  • (Didn't downvote) Things looks fine to me, except for this thing where calculation for time needs to take place `if ($a == $b) { return 0; }`. Convert the time to seconds and you are good to go. – nice_dev Sep 19 '19 at 13:59

4 Answers4

2

You can just concat your date and time then compare the string this can save a lot of work.

function cmp($a, $b){
    return strcmp($a["ClassDate"] . $a["StartTime"], $b["ClassDate"] . $b["StartTime"]);    
}

usort($result_array,'cmp');
Progrock
  • 7,373
  • 1
  • 19
  • 25
LF00
  • 27,015
  • 29
  • 156
  • 295
1

You were almost there. Add time StartTime to your ClassDate and then compare to make sort work.

function cmp($a, $b) {
    $a = date('Y-m-d H:i:s', strtotime($a['StartTime'], strtotime($a['ClassDate'])));
    $b = date('Y-m-d H:i:s', strtotime($b['StartTime'], strtotime($b['ClassDate'])));

    if ($a == $b) {  return 0;  }
    return ($a < $b) ? -1 : 1;  
}   

usort($result_array, "cmp");
Dark Knight
  • 6,116
  • 1
  • 15
  • 37
  • Never tried, but I presume `<`,`>`,`=` should work properly only with DateTime objects as date() would return a string. – nice_dev Sep 19 '19 at 14:04
  • Yup, you are right, it would be a comparison as a string but the format of date is in this way, that it would work. – Dark Knight Sep 19 '19 at 14:06
  • If date is in format `YYYY-mm-ddTHH:ii:ss` it would work perfectly, but lets say you change the foramt to `mm-dd-YYYYTHH:ii:ss` then it won't . – Dark Knight Sep 19 '19 at 14:07
  • I would still convert it to DateTime to be on safer side and for a robust code. – nice_dev Sep 19 '19 at 14:09
  • If you want to be sure, can convert these dates to `UNIX timestamp` using `strtotime` and then do comparison. – Dark Knight Sep 19 '19 at 14:13
  • See, you can compare dates directly when in same format and above mentioned order. https://stackoverflow.com/questions/14805944/comparing-date-and-time-php – Dark Knight Sep 19 '19 at 14:15
  • 1
    `It is a DateTime object, see the last outer function date`. Well, both aren't same. See here https://3v4l.org/cUEN5 – nice_dev Sep 19 '19 at 14:20
  • 1
    @vivek_23, thanks got it, that's the reason that I was able to compare that, – Dark Knight Sep 19 '19 at 14:22
1

Ordering by date, time ascending with the spaceship operator (I re-ordered your initial data because it looked to be already sorted):

<?php

$json=<<<JSON
[
    {
        "Id": 170,
        "ClassDate": "2019-09-21T00:00:00",
        "StartTime": "08:45:00"
    },
    {
        "Id": 14,
        "ClassDate": "2019-09-20T00:00:00",
        "StartTime": "06:00:00"
    },
    {
        "Id": 144,
        "ClassDate": "2019-09-21T00:00:00",
        "StartTime": "05:00:00"
    },
    {
        "Id": 27,
        "ClassDate": "2019-09-20T00:00:00",
        "StartTime": "07:45:00"
    }
]
JSON;

$data = json_decode($json, true);

function cmp($a, $b) {
    $a_date = $a['ClassDate'];
    $b_date = $b['ClassDate'];
    $a_time = $a['StartTime'];
    $b_time = $b['StartTime'];

    $cmp = $a_date <=> $b_date;
    if($cmp === 0)
        $cmp = $a_time <=> $b_time;

    return $cmp; 
}

usort($data, "cmp");
var_export($data);

Output:

array (
  0 => 
  array (
    'Id' => 14,
    'ClassDate' => '2019-09-20T00:00:00',
    'StartTime' => '06:00:00',
  ),
  1 => 
  array (
    'Id' => 27,
    'ClassDate' => '2019-09-20T00:00:00',
    'StartTime' => '07:45:00',
  ),
  2 => 
  array (
    'Id' => 144,
    'ClassDate' => '2019-09-21T00:00:00',
    'StartTime' => '05:00:00',
  ),
  3 => 
  array (
    'Id' => 170,
    'ClassDate' => '2019-09-21T00:00:00',
    'StartTime' => '08:45:00',
  ),
)
Progrock
  • 7,373
  • 1
  • 19
  • 25
0

I found something here : Sort array using multiple criteria in PHP. And edited the solution according to my needs and here's the working solution. Play with the <> signs to get ascending/descending ordered values.

function order_by_score_endgame($a, $b){
   if ($a['ClassDate'] == $b['ClassDate'])
    {
      // score is the same, sort by endgame
      if ($a['StartTime'] > $b['StartTime']) return 1;
    }
    // sort the higher score first:
    return $a['ClassDate'] > $b['ClassDate'] ? 1 : -1;
   }
   usort($result_array, "order_by_score_endgame");
Shujaat Shaikh
  • 189
  • 1
  • 5
  • 17