Last active
March 30, 2020 15:50
-
-
Save renalpha/ae5b5187516c43ff987bbec561095136 to your computer and use it in GitHub Desktop.
Get a group of dates and group them by X minutes (timetables)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Services; | |
use ArrayIterator; | |
use Carbon\Carbon; | |
use Illuminate\Support\Collection; | |
class TimeService | |
{ | |
/** @var int */ | |
public const GROUP_BY_MINUTES = 30; | |
/** @var array */ | |
protected $timesArray = []; | |
/** @var */ | |
protected $times; | |
/** @var string */ | |
protected $dateFormat = 'N'; | |
/** | |
* @param \Illuminate\Support\Collection $times | |
* @param string $format | |
* @return array | |
*/ | |
public function groupTimes(Collection $times, string $format = 'H:i'): array | |
{ | |
$groups = $times->groupBy(function (Carbon $obj, $key) { | |
return $obj->format($this->dateFormat); | |
}); | |
/** @var \Illuminate\Support\Collection $groupTimes */ | |
foreach ($groups as $groupTimes) { | |
$groupTimes = $groupTimes->sortBy(function (Carbon $obj, $key) { | |
return Carbon::parse($obj->getTimestamp())->timestamp; | |
}); | |
$this->times = $groupTimes; | |
$iterator = $groupTimes->getIterator(); | |
$i = 0; | |
while ($this->times->count() > 0) { | |
$time = $iterator->current(); | |
$date = $time->format($this->dateFormat); | |
$newTime = $time->format($format); | |
$this->timesArray[$date][$i][] = $newTime; | |
$this->times->forget($iterator->key()); | |
$this->nextTime($iterator, $i, $format); | |
} | |
} | |
return $this->timesArray; | |
} | |
/** | |
* @param \ArrayIterator $iterator | |
* @param int $i | |
* @param string $format | |
*/ | |
public function nextTime(ArrayIterator $iterator, int $i, string $format): void | |
{ | |
$time = $iterator->current(); | |
$iterator->next(); | |
$nextTime = $iterator->current(); | |
$date = $time->format($this->dateFormat); | |
// Create new group | |
if (!now()->parse($time)->addMinutes(self::GROUP_BY_MINUTES)->eq($nextTime)) { | |
$i++; | |
} | |
$newTime = $nextTime->format($format); | |
$this->timesArray[$date][$i][] = $newTime; | |
$this->times->forget($iterator->key()); | |
while ($this->times->count() > 0 && $iterator->valid()) { | |
$this->nextTime($iterator, $i, $format); | |
$i++; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tests\Unit; | |
use App\Services\TimeService; | |
use Tests\TestCase; | |
class TimeServiceTest extends TestCase | |
{ | |
/** @test */ | |
public function make_time_range(): void | |
{ | |
$times = collect([ | |
now()->parse(now()->format('Y-m-d') . '14:30'), | |
now()->parse(now()->format('Y-m-d') . '09:00'), | |
now()->parse(now()->format('Y-m-d') . '09:30'), | |
now()->parse(now()->format('Y-m-d') . '10:00'), | |
now()->parse(now()->format('Y-m-d') . '12:00'), | |
now()->parse(now()->format('Y-m-d') . '13:00'), | |
now()->parse(now()->format('Y-m-d') . '13:30'), | |
now()->parse(now()->format('Y-m-d') . '15:00'), | |
now()->parse(now()->format('Y-m-d') . '15:30'), | |
now()->parse(now()->format('Y-m-d') . '16:00'), | |
]); | |
/** @var \App\Services\TimeService $timeService */ | |
$timeService = app(TimeService::class); | |
$this->assertEquals($timeService->groupTimes($times), [ | |
0 => [ | |
0 => '09:00', | |
1 => '09:30', | |
2 => '10:00', | |
], | |
1 => [ | |
0 => '12:00', | |
], | |
2 => [ | |
0 => '13:00', | |
1 => '13:30', | |
], | |
3 => [ | |
0 => '14:30', | |
1 => '15:00', | |
2 => '15:30', | |
3 => '16:00', | |
], | |
]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment