petrusjak
petrusjak

Reputation: 45

Sorting array of objects by date in object

I'am trying to sort this Array with Objects which originates from at Google Calendar Batch request with this resulting array with objects:

array(3) {
  ["response-test0"]=>;
  object(Google_Service_Calendar_Events)#46 (17) {
        .
        .
        .
      ["items"]=>;
      array(1) {
        [0]=>;
        array(20) {
            .
            .
          ["start"]=>;
          array(1) {
            ["dateTime"]=>;
            string(25) "2017-02-01T10:00:00+01:00"
          } 
        .
        .
        .
  ["response-test1"]=>;
  object(Google_Service_Calendar_Events)#46 (17) {
        .
        .
        .
      ["items"]=>;
      array(1) {
        [0]=>;
        array(20) {
            .
            .
          ["start"]=>;
          array(1) {
            ["dateTime"]=>;
            string(25) "2017-02-01T11:00:00+01:00"
          }
        .
        .
        .
  ["response-test3"]=>;
  object(Google_Service_Calendar_Events)#46 (17) {
        .
        .
        .
      ["items"]=>;
      array(1) {
        [0]=>;
        array(20) {
            .
            .
          ["start"]=>;
          array(1) {
            ["dateTime"]=>;
            string(25) "2017-02-01T11:00:00+01:00"
          }
        .
        .

This is the code for fetching the data:

$arrlength = count($calendarId);
for ($x = 0; $x <= $arrlength-1; $x++) {
    $results = $service->events->listEvents($calendarId[$x], $optParams);
    $batch->add($results, "test" .$x);
};
$results = $batch->execute();

The resulting array contain thee (in this case) objects named ["response-test0"], ["response-test1"] and ["response-test2"] as shown in my array example.

Edit: The fact that the array objects is convoluted with an assosiative array seem to be missing in the answers so far as far as I understand (or am I wrong)?The proposals for search inside the object seem to be in the right direction, but I haven't been able to test this out fully because the "top level" ['response_x'] is not taken in to consideration.

The structure to sort start-dates in (not individually sorting dates in each object):

array(3) {
    ["response-test0"]
    Object(Google_Service_Calendar_Events)#46(17){
    .
    .
    }
    ["response-test1"]
    Object(Google_Service_Calendar_Events)#46(17){
    .
    .
    }
    ["response-test2"]
    Object(Google_Service_Calendar_Events)#46(17){
    .
    .
    }

I have tried using this snippet (and many others) to sort the individual items by date (["start"]) - start of calender meeting, but with no luck so far. I have also looked into merging the objects but with no luck. I am a novice in PHP but know the basics og programming fairly so I hope that someone can point me in the right direction - and I would be greatful:

usort($results, function($a, $b) {
    return $a['items']['start'] - $b['items']['start'];
});

var_dump( $results );

Upvotes: 2

Views: 2148

Answers (2)

petrusjak
petrusjak

Reputation: 45

I found a working solution myself by looping through the resulting array from the Calendar API by constructing a more manageble array to sort (close to Nitin's suggestion). For others who might have the same problem I post the relevant part here. I am sure that my code can be optimized and better looking sematically, but it works:

function cmpDate($a, $b) {
    $date1 = new DateTime($a['start']);
    $date2 = new DateTime($b['start']);

    $date1 = $date1->getTimestamp();
    $date2 = $date2->getTimestamp();
    return $date1 - $date2;
}

$y = 0;
for ($x = 0; $x <= $arrlength-1; $x++) {
if (count($results["response-test".$x.""]->getItems()) == 0) {

} else {

  foreach ($results["response-test".$x.""]->getItems() as $event) {
    $start = $event->start->dateTime;
    $dato = date_format(date_create($start), "d.m.Y");
    $s = strtotime($start);
    if (empty($start)) {
      $start = $event->start->date;
    }
    $tid = new dateTime($start);
    $data[$y]['start'] = $start;
    $data[$y]['dato'] = $dato;
    $data[$y]['tid'] = $tid->format('H:i');
    $data[$y]['lokasjon'] = $event->getLocation();
    $data[$y]['organisator'] = $event->getOrganizer()->email;
    $data[$y]['tema'] = $event->getSummary();
    $y++;
  }
}
usort($data, 'cmpDate');

Upvotes: 0

Nitin
Nitin

Reputation: 916

You can use DateTime objects to compare dates:

function cmpDate($a, $b) {
    // To confirm expected result, dump the data for inspection.
    //var_dump($a);
    //var_dump($b);

    // Option 1:
    //$date1 = new \DateTime($a['items'][0]['start']['dateTime'])->getTimestamp();
    //$date2 = new \DateTime($b['items'][0]['start']['dateTime'])->getTimestamp();

    // Option 2
    $date1 = new \DateTime($a->items[0]['start']['dateTime'])->getTimestamp();
    $date2 = new \DateTime($b->items[0]['start']['dateTime'])->getTimestamp();

    // usort compares integers and orders it accordingly.
    return $date1 - $date2;
}

usort($results, 'cmpDate');

I am using timestamp so that you do not need to format the date to a string.

Sources:

http://php.net/manual/en/class.datetime.php

http://php.net/manual/en/function.usort.php

In response to your comment on rearranging the array by removing the first layer, you can try the following. Do note that the keys can be important to know which record is which.

$newArr = [];
foreach ($results as $key => $data) {
    // echo $key; // response-test0
    // You can reduce the array as much as you like.
    // $newArr[] = $data;
    // $newArr[] = $data->items['start'];
    $newArr[] = $data->items['start']['dateTime'];

    // In case you want to preserve the key
    // $newArr[$key] = $data->items['start']['dateTime'];

}

Upvotes: 2

Related Questions