spatie / period

Complex period comparisons
https://spatie.be/open-source
MIT License
1.56k stars 72 forks source link

Get available time slots between periods #65

Closed amirakbulut closed 3 years ago

amirakbulut commented 3 years ago

Is this package sufficient enough to calculate timeslots between certain periods?

Let's say my business opens from 08:00 to 18:00 on a specific day, with a work break at 13:00 to 14:00.

This makes the following periods:

Period::make('2020-07-27 08:00', '2020-07-27 13:00', Precision::MINUTE);
Period::make('2020-07-27 14:00', '2020-07-27 18:00', Precision::MINUTE);

Now having those periods, how would I be able to generate an array of (e.g.) 15 minutes timeslots, that are available/gasps?

brendt commented 3 years ago

That's not possible yet, since the underlying iterator only supports days, not arbitrary precisions. Feel free to submit a tested PR if you want this functionality to be supported.

endelwar commented 2 years ago

I had the same issue and I resolved it with a splitter utility that makes use of Carbon\CarbonPeriod.

<?php

declare(strict_types=1);

namespace App\Service;

use Carbon\CarbonInterface;
use Carbon\CarbonPeriod;
use Spatie\Period\PeriodCollection;

final class SlotSplitter
{
    private PeriodCollection $slots;

    public function __construct(PeriodCollection $slots)
    {
        $this->slots = $slots;
    }

    /** @return array<int, CarbonInterface|null> */
    public function split(int $minutes): array
    {
        $splitPeriods = [];
        $interval = sprintf('%d minutes', $minutes);
        foreach ($this->slots as $item) {
            $carbonPeriod = CarbonPeriod::create($item->start(), $interval, $item->end());
            $carbonPeriod->excludeEndDate();
            foreach ($carbonPeriod as $period) {
                $splitPeriods[$period->timestamp] = $period;
            }
        }
        ksort($splitPeriods);

        return $splitPeriods;
    }
}