BetweenTimeExtension::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 4
crap 1
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\Schedule\Extension;
4
5
use Zenstruck\ScheduleBundle\Schedule\Exception\SkipTask;
6
7
/**
8
 * @author Kevin Bond <[email protected]>
9
 */
10
final class BetweenTimeExtension
11
{
12
    /** @var string */
13
    private $startTime;
14
15
    /** @var string */
16
    private $endTime;
17 13
18
    /** @var bool */
19 13
    private $within;
20 13
21 13
    /** @var bool */
22 13
    private $inclusive;
23 13
24
    private function __construct(string $startTime, string $endTime, bool $within, bool $inclusive)
25 1
    {
26
        $this->startTime = self::normalizeTime($startTime);
27 1
        $this->endTime = self::normalizeTime($endTime);
28 1
        $this->within = $within;
29
        $this->inclusive = $inclusive;
30
    }
31 1
32
    public function __toString(): string
33
    {
34 12
        if ($this->within) {
35
            return "Only run between {$this->startTime} and {$this->endTime}";
36 12
        }
37
38 12
        return "Only run if not between {$this->startTime} and {$this->endTime}";
39 3
    }
40
41
    public function filter(?\DateTimeZone $timezone): void
42 9
    {
43 3
        $isBetween = $this->isBetween($timezone);
44
45 6
        if ($this->within && !$isBetween) {
46
            throw new SkipTask("Only runs between {$this->startTime} and {$this->endTime}");
47 7
        }
48
49 7
        if (!$this->within && $isBetween) {
50
            throw new SkipTask("Only runs if not between {$this->startTime} and {$this->endTime}");
51
        }
52 7
    }
53
54 7
    public static function whenWithin(string $startTime, string $endTime, bool $inclusive = true): self
55
    {
56
        return new self($startTime, $endTime, true, $inclusive);
57 12
    }
58
59
    public static function unlessWithin(string $startTime, string $endTime, bool $inclusive = true): self
60 12
    {
61 12
        return new self($startTime, $endTime, false, $inclusive);
62 12
    }
63
64
    private function isBetween(?\DateTimeZone $timezone): bool
65 12
    {
66
        [$now, $startTime, $endTime] = [
67 4
            new \DateTime(\date('Y-m-d H:i:00'), $timezone),
68
            self::parseTime($this->startTime, $timezone),
69
            self::parseTime($this->endTime, $timezone),
70 12
        ];
71 8
72
        if ($endTime < $startTime) {
73
            // account for overnight
74 4
            $endTime = $endTime->add(new \DateInterval('P1D'));
75
        }
76
77 13
        if ($this->inclusive) {
78
            return $now >= $startTime && $now <= $endTime;
79 13
        }
80
81
        return $now > $startTime && $now < $endTime;
82 12
    }
83
84 12
    private static function normalizeTime(string $time): string
85
    {
86 12
        return false === \mb_strpos($time, ':') ? "{$time}:00" : $time;
87 12
    }
88
89
    private static function parseTime(string $time, ?\DateTimeZone $timezone): \DateTime
90
    {
91
        [$hour, $minute] = \explode(':', $time, 2);
92
93
        return (new \DateTime('today', $timezone))
94
            ->add(new \DateInterval("PT{$hour}H{$minute}M"))
95
        ;
96
    }
97
}
98