Stack Exchange
Filter result array based on date filter in PHP
I have an array of results fetched from mysql database. I want to group those data based on dates as below:
Input array:
$resultSet = [
   0 => [
     'id' => 123,
     'name' => 'ABC',
     'start_date' => '2019-12-18 20:00:00'
   ], 
   1 => [
     'id' => 124,
     'name' => 'CDE',
     'start_date' => '2019-12-19 20:00:00'
   ],  
   2 => [
     'id' => 125,
     'name' => 'TEST',
     'start_date' => '2019-12-23 20:00:00'
   ],
   3 => [
     'id' => 126,
     'name' => 'BWM',
     'start_date' => '2019-12-18 20:00:00'
   ], 
   4 => [
     'id' => 127,
     'name' => 'XYZ',
     'start_date' => '2019-12-19 20:00:00'
   ], 
   5 => [
     'id' => 128,
     'name' => 'GHJ',
     'start_date' => '2019-12-21 20:00:00'
   ], 
   6 => [
     'id' => 129,
     'name' => 'GHJK',
     'start_date' => '2019-12-22 20:00:00'
   ], 
   7 => [
     'id' => 130,
     'name' => 'GHL',
     'start_date' => '2019-12-20 20:00:00'
   ], 
   8 => [
     'id' => 131,
     'name' => 'JKL',
     'start_date' => '2019-12-25 20:00:00'
   ]
];

Output: Display all the list of products group by filters (Today, Tomorrow, This Weekend, Next Weekend etc.) Consider we are running script on Wednesday.
Today: Display only record of index: 0, 3 (Today's Date: 2019-12-18)
Tomorrow: Display only record of index: 0, 3 (Tomorrow Date: 2019-12-19)
This Weekend: Display only record of index: 5, 6, 7 (Friday, Saturday & Sunday: 2019-12-20, 2019-12-21, 2019-12-22)
Next Week: Display only record of index: 2, 8 (Date: 2019-12-23, 2019-12-25)
Result will display dynamically and every week different record will display as above. 
Sample Code Used: 
$arrayList = [];
 foreach($resultSet as $element){
   $arrayList[$element->start_date][] = $element;
 }

 dd($arrayList);

Need to alter the above code to fetch the result as per the requirement below.
Framework: Laravel 5.2
Requirements:

Script will either run on Wednesday or Thrusday (90% of time). 
In case for some reason script did not run on those days. We will manually run it on Friday. In that case Today is Friday and Saturday is Tomorrow. Also This Weekend will include data of Friday, Saturday and Sunday. 
This Weekend will include data of Friday, Saturday & Sunday.
Today, Tomorrow, This Weekend & Next Weekend label will be filtered from the "start_date". 

Expected OUTPUT:
$output = [
   'today' => [
       0 => [
         'id' => 123,
         'name' => 'ABC',
         'start_date' => '2019-12-18 20:00:00'
       ],
       1 => [
         'id' => 126,
         'name' => 'BWM',
         'start_date' => '2019-12-18 20:00:00'
       ]
    ],
    'tomorrow' => [
       0 => [
         'id' => 124,
         'name' => 'CDE',
         'start_date' => '2019-12-19 20:00:00'
       ],
       1 =>  [
         'id' => 127,
         'name' => 'XYZ',
         'start_date' => '2019-12-19 20:00:00'
       ]
    ],

    'this_weekend' => [
       0 => [
         'id' => 130,
         'name' => 'GHL',
         'start_date' => '2019-12-20 20:00:00'
       ],
       1 =>  [
         'id' => 128,
         'name' => 'GHJ',
         'start_date' => '2019-12-21 20:00:00'
       ],
       2 =>  [
         'id' => 129,
         'name' => 'GHJK',
         'start_date' => '2019-12-22 20:00:00'
       ]
    ],
    'next_week' => [
       0 => [
         'id' => 125,
         'name' => 'TEST',
         'start_date' => '2019-12-23 20:00:00'
       ],
       1 => [
         'id' => 131,
         'name' => 'JKL',
         'start_date' => '2019-12-25 20:00:00'
       ]
     ]
  ];    

I am running simple foreach loop in view page to display data. Please feel free to comment below if any queries. 

You don't need to repost your unclear question as many times as you can. It will be closed either.

@AksenP - What is the additional information you required ? Is there further question you have ? I am stuck with this, expecting a help. Let me know if any other information required

SO is not project writing service, firstly you should show what you've tried so far. You didn't do anything at all. Also, you didn't presented desired output.

@AksenP I have already provided sample code above which i have tried. But I know it is not the getting me the correct output i am looking for. That is the reason i am here. If possible do help. Requesting you do not downvote or raise a close request.

Nice, and HTML, and JS?  You didn't do anything for to solve this. I can print any foreach loop also. How could somebody represent your issue?

I have a foreach loop running in view page. That is the reason didn't mention HTML, CSS part. All i want is to filter the data in controller. Once data is filtered. I am running simple loop in my view page to display it.

Well if you are using laravel then you can use the power of carbon and collection methods to solve such kinds of issues. 
You can map the array key and group them by using carbon method. Check the following snippets will give you the exact result.
date_default_timezone_set("Asia/Kolkata");
$resultSet = [ 
   0 => [
     'id' => 127,
     'name' => 'XYZ',
     'start_date' => '2020-01-03 20:00:00'
   ], 
   1 => [
     'id' => 128,
     'name' => 'GHJ',
     'start_date' => '2020-01-04 20:00:00'
   ], 
   2 => [
     'id' => 129,
     'name' => 'GHJK',
     'start_date' => '2020-01-05 16:00:00'
   ], 
   3 => [
     'id' => 130,
     'name' => 'GHL',
     'start_date' => '2020-01-05 20:00:00'
   ], 
   4 => [
     'id' => 131,
     'name' => 'JKL',
     'start_date' => '2020-01-18 20:00:00'
   ]
];

in case if you want the future date will be in "in_future" key.
$output = collect($resultSet)->map(function ($value) {
    $group_by_key = Carbon::parse($value['start_date']);
    switch ($group_by_key) {
        case $group_by_key->isToday():
            $group_by_key = 'today';
            break;
        case $group_by_key->isTomorrow():
            $group_by_key = 'tomorrow';
            break;
        case $group_by_key->isNextWeek():
            $group_by_key = 'next_week';
            break;
        case $group_by_key->weekOfYear > Carbon::now()->addWeek()->weekOfYear:
            $group_by_key = 'in_future';
            break;
        case $group_by_key->isWeekend():
            $group_by_key = 'this_weekend';
            break;

        default:
            $group_by_key = $group_by_key->format('l');;
            break;
    }
    $value['group_by_key'] = $group_by_key;
    return $value;
})->groupBy('group_by_key');
var_dump($output);

or in case if you want the future date will be in "next_week" key.
$output = collect($resultSet)->map(function ($value) {
    $group_by_key = Carbon::parse($value['start_date']);
    switch ($group_by_key) {
        case $group_by_key->isToday():
            $group_by_key = 'today';
            break;
        case $group_by_key->isTomorrow():
            $group_by_key = 'tomorrow';
            break;
        case $group_by_key->weekOfYear > Carbon::now()->addWeek()->weekOfYear:
            $group_by_key = 'next_week';
            break;
        case $group_by_key->isWeekend():
            $group_by_key = 'this_weekend';
            break;

        default:
            $group_by_key = $group_by_key->format('l');;
            break;
    }
    $value['group_by_key'] = $group_by_key;
    return $value;
})->groupBy('group_by_key');
var_dump($output);


Thanks, really appreciate your answer. I am trying this solution with real time data, let you know if any issues.

While testing, above code is breaking for next week condition. @sachin kumar Sample input array: https://3v4l.org/Ovd8u

As by default carbon compare the parsed date's weekOfTheYear with the current date's weekOfTheYear. and in your use case "2020-01-18 20:00:00" is not belongs to next week but belongs to after next week. So check my updated answer(both variation).

I am still checking with real data. There are some cases i found it is displaying wrong record in the "this weekend" category. Trying to figure it out and update you. @sachin

Ok. Don't forget to set the default timezone for this script.

At the beginning you should define a useful date format for further comparing of dates:
 $s = new DateTime();                         // create date value
 $s->modify('+2 days');                       // in fact today is 2019-12-16
                                              // but you've choose 2019-12-18
                                              // you can comment this line
 //echo $s->format('Y-m-d H:i:s').PHP_EOL;    // today
 $today = $s->format('Ymd');                  // format 20191218

 echo $today.' <- today'.PHP_EOL;             // today

 $nextmonday = $s->modify('next monday')->format('Ymd');
 echo $nextmonday.' <- next monday'.PHP_EOL.PHP_EOL;     // next monday, format 20191223

Then you need to make a foreach loop like this one:
foreach($resultSet as $rec){
    $d = date('Ymd', strtotime($rec['start_date']));      // transform to format 20191218 
    $d2 = date('l', strtotime($rec['start_date']));       // name of the day
    echo $d.' --- '.$d2.PHP_EOL;    

    if ($d == $today) {                 // 2019-12-18 == 2019-12-18
        $res['today'][] = $rec;
    } else if ($d - $today == 1) {      // 2019-12-19 - 2019-12-18 == 1
        $res['tomorrow'][] = $rec;
    } else if (in_array($d2,['Friday','Saturday','Sunday']) && $d < $nextmonday){    // < 2019-12-23 and by day name
        $res['this_weekend'][] = $rec;
    } else if ($d >= $nextmonday){       // next week (not a weekend)
        $res['next_weekend'][] = $rec;
    } 
}

Outputs will be:
Array
(
    [today] => Array
        (
            [0] => Array
                (
                    [id] => 123
                    [name] => ABC
                    [start_date] => 2019-12-18 20:00:00
                )

            [1] => Array
                (
                    [id] => 126
                    [name] => BWM
                    [start_date] => 2019-12-18 20:00:00
                )

        )

    [tomorrow] => Array
        (
            [0] => Array
                (
                    [id] => 124
                    [name] => CDE
                    [start_date] => 2019-12-19 20:00:00
                )

            [1] => Array
                (
                    [id] => 127
                    [name] => XYZ
                    [start_date] => 2019-12-19 20:00:00
                )

        )

    [next_weekend] => Array
        (
            [0] => Array
                (
                    [id] => 125
                    [name] => TEST
                    [start_date] => 2019-12-23 20:00:00
                )

            [1] => Array
                (
                    [id] => 131
                    [name] => JKL
                    [start_date] => 2019-12-25 20:00:00
                )

        )

    [this_weekend] => Array
        (
            [0] => Array
                (
                    [id] => 128
                    [name] => GHJ
                    [start_date] => 2019-12-21 20:00:00
                )

            [1] => Array
                (
                    [id] => 129
                    [name] => GHJK
                    [start_date] => 2019-12-22 20:00:00
                )

            [2] => Array
                (
                    [id] => 130
                    [name] => GHL
                    [start_date] => 2019-12-20 20:00:00
                )

        )

)

Note: the last array named as next_weekend , perhaps you need to rename it as next_week , cause it has dates just after your current weekend.
I think you've understood an idea and will be able to add your further logic.
Demo

I think you should make the array of different dates: Today, tomorrow, this weekend, nextweek
Check link for time formats:https://carbon.nesbot.com/docs/
$now = Carbon::now();
echo $now;                               // 2019-11-20 16:41:03
echo "\n";
$today = Carbon::today();
echo $today;                             // 2019-11-20 00:00:00
echo "\n";
$tomorrow = Carbon::tomorrow('Europe/London');
echo $tomorrow;                          // 2019-11-21 00:00:00
echo "\n";

Check your results with compare condition of dates and make arrays and combine them to one array.
$totalarr = array('today'=>$todayarr,'tomorrow'=>$tomorrowarr,'thisweek'=>$thisweek,'nextweek'=>$nextweekarr);

print_r($totalarr);


Try the bellow example   
$group = [];
    foreach ($start_date as $item)  {
        if (!isset($group[$item['start_date']])) {
            $group[$item['start_date']] = [];
        }
        foreach ($item as $key => $value) {
            if ($key == 'start_date') continue;
            $group[$item['start_date']][$key] = $value;
        }
    }


@sss S This is not what exactly I want. I have already achieved it using my code.  Please check the requirement above.

@appsntech, I told you - your question is unclear. People don't know what do you need.

Let me paste you a sample output what exactly i am looking for. Give me a moment please.

@AksenP added expected output. Hope this is clear now. Thanks for directing me to the right direction. Let me know if any queries.

Let us continue this discussion in chat.

@AksenP - yes i am there already in chat room. Please join me in.

@appsntech, no need, I can't be near keyboard all the time. I'll prepare an answer to you soon.
