Lines 100.00% 10 / 10
Functions and Methods 100.00% 5 / 5
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
SunEventSchedule 100.00% 10 / 10 100.00% 5 / 5 8 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 forEvent 100.00% 4 / 4 100.00% 1 / 1 2
 findNextOccurrenceAfter 100.00% 1 / 1 100.00% 1 / 1 1
 describe 100.00% 3 / 3 100.00% 1 / 1 3
 isRecurring 100.00% 1 / 1 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Support\Schedule;
6
7use DateTimeImmutable;
8use Stewart\Contracts\Exception\ScheduleError;
9use Stewart\Contracts\Exception\ScheduleException;
10use Stewart\Contracts\Exception\SunException;
11use Stewart\Contracts\Sun\SunCalendar;
12use Stewart\Contracts\Sun\SunEvent;
13use Stewart\Contracts\Time\Instant;
14use Stewart\Contracts\Time\SunOffset;
15
16/** @internal */
17final readonly class SunEventSchedule implements WallClockSchedule
18{
19    private function __construct(
20        private SunCalendar $calendar,
21        public SunEvent $event,
22        public SunOffset $offset,
23    ) {}
24
25    /** @throws ScheduleException */
26    public static function forEvent(SunCalendar $calendar, SunEvent $event, ?SunOffset $offset = null): self
27    {
28        try {
29            $calendar->getLocation();
30        } catch (SunException $e) {
31            throw ScheduleException::createForReason(ScheduleError::SunLocationUnknown, $e, event: $event->describe());
32        }
33
34        return new self($calendar, $event, $offset ?? SunOffset::none());
35    }
36
37    public function findNextOccurrenceAfter(DateTimeImmutable $after): ?DateTimeImmutable
38    {
39        return $this->calendar->findNextEvent($this->event, $this->offset, Instant::fromDateTime($after))?->toDateTime($after->getTimezone());
40    }
41
42    public function describe(): string
43    {
44        if ($this->offset->isNone()) {
45            return 'at ' . $this->event->describe();
46        }
47
48        return \sprintf('%s %s %s', $this->offset->getMagnitude(), $this->offset->isBeforeEvent() ? 'before' : 'after', $this->event->describe());
49    }
50
51    public function isRecurring(): bool
52    {
53        return true;
54    }
55}