Lines 100.00% 11 / 11
Methods 100.00% 4 / 4
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 between 100.00% 5 / 5 100.00% 1 / 1 2
 includes 100.00% 4 / 4 100.00% 1 / 1 4
 crossesMidnight 100.00% 1 / 1 100.00% 1 / 1 1
13final readonly class TimeWindow
14{
15    private function __construct(
16        public TimeOfDay $start,
17        public TimeOfDay $end,
18    ) {}
19
20    /** @throws ScheduleException */
21    public static function between(TimeOfDay|string $start, TimeOfDay|string $end): self
22    {
23        $start = TimeOfDay::fromTimeOrString($start);
24        $end = TimeOfDay::fromTimeOrString($end);
25
26        if ($start->equals($end)) {
27            throw ScheduleException::createForReason(ScheduleError::TimeWindowEmpty, time: $start->format());
28        }
29
30        return new self($start, $end);
31    }
32
33    public function includes(DateTimeInterface $moment): bool
34    {
35        $seconds = TimeOfDay::fromDateTime($moment)->toSecondsOfDay();
36        $afterStart = $seconds >= $this->start->toSecondsOfDay();
37        $beforeEnd = $seconds < $this->end->toSecondsOfDay();
38
39        return $this->crossesMidnight() ? $afterStart || $beforeEnd : $afterStart && $beforeEnd;
40    }
41
42    public function crossesMidnight(): bool
43    {
44        return $this->end->toSecondsOfDay() < $this->start->toSecondsOfDay();
45    }
46}