Date   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Test Coverage

Coverage 94.2%

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 178
ccs 65
cts 69
cp 0.942
rs 10
c 0
b 0
f 0
wmc 30

24 Methods

Rating   Name   Duplication   Size   Complexity  
A fromNative() 0 3 1
A __construct() 0 5 1
A toNative() 0 3 1
A format() 0 3 1
A createClone() 0 3 1
A setMonth() 0 3 1
A isSame() 0 3 1
A setYear() 0 3 1
A setDay() 0 3 1
A isAfter() 0 3 1
A getDateInterval() 0 11 2
A __clone() 0 3 1
A compareTo() 0 5 1
A max() 0 8 3
A isBefore() 0 3 1
A min() 0 8 3
A createInternalDateTime() 0 7 2
A add() 0 5 1
A isSameOrBefore() 0 3 1
A isToday() 0 5 1
A isSameOrAfter() 0 3 1
A getFormatFromTimePrecision() 0 3 1
A setDate() 0 5 1
A subtract() 0 5 1
1
<?php
2
3
namespace Palmtree\Chrono;
4
5
use Palmtree\Chrono\Option\ComparisonOperators;
6
use Palmtree\Chrono\Option\DatePeriods;
7
use Palmtree\Chrono\Option\TimePeriods;
8
9
class Date
10
{
11
    /** @var \DateTime */
12
    protected $dateTime;
13
14 16
    public function __construct(string $time = 'now', $timezone = null)
15
    {
16 16
        $this->dateTime = $this->createInternalDateTime($time, $timezone);
17
18 16
        $this->dateTime->setTime(0, 0);
19 16
    }
20
21 1
    public static function fromNative(\DateTime $dateTime): self
22
    {
23 1
        return new static($dateTime->format('Y-m-d H:i:s.u'), $dateTime->getTimezone());
24
    }
25
26 2
    public function toNative(): \DateTime
27
    {
28 2
        return clone $this->dateTime;
29
    }
30
31 25
    public function format(?string $format = null): string
32
    {
33 25
        return $this->dateTime->format($format ?? \DateTime::ISO8601);
34
    }
35
36 1
    public function isToday(): bool
37
    {
38 1
        $today = new self('now', $this->dateTime->getTimezone());
39
40 1
        return $this->isSame($today, DatePeriods::DAY);
41
    }
42
43 9
    public function isSame(self $date, ?string $precision = null): bool
44
    {
45 9
        return $this->compareTo($date, ComparisonOperators::EQUAL_TO, $precision);
46
    }
47
48 3
    public function isBefore(self $date, ?string $precision = null): bool
49
    {
50 3
        return $this->compareTo($date, ComparisonOperators::LESS_THAN, $precision);
51
    }
52
53 1
    public function isSameOrBefore(self $date, ?string $precision = null): bool
54
    {
55 1
        return $this->compareTo($date, ComparisonOperators::LESS_THAN_OR_EQUAL_TO, $precision);
56
    }
57
58 3
    public function isAfter(self $date, ?string $precision = null): bool
59
    {
60 3
        return $this->compareTo($date, ComparisonOperators::GREATER_THAN, $precision);
61
    }
62
63 1
    public function isSameOrAfter(self $date, ?string $precision = null): bool
64
    {
65 1
        return $this->compareTo($date, ComparisonOperators::GREATER_THAN_OR_EQUAL_TO, $precision);
66
    }
67
68
    /**
69
     * @param int    $value
70
     * @param string $period
71
     *
72
     * @return self
73
     */
74 4
    public function add(int $value, string $period)
75
    {
76 4
        $this->dateTime->add($this->getDateInterval($value, $period));
77
78 4
        return $this;
79
    }
80
81
    /**
82
     * @param int    $value
83
     * @param string $period
84
     *
85
     * @return self
86
     */
87 4
    public function subtract(int $value, string $period)
88
    {
89 4
        $this->dateTime->sub($this->getDateInterval($value, $period));
90
91 4
        return $this;
92
    }
93
94
    public function setYear(int $year): self
95
    {
96
        return $this->setDate($year, $this->dateTime->format('m'), $this->dateTime->format('d'));
0 ignored issues
show
Bug introduced by
$this->dateTime->format('d') of type string is incompatible with the type integer expected by parameter $day of Palmtree\Chrono\Date::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

96
        return $this->setDate($year, $this->dateTime->format('m'), /** @scrutinizer ignore-type */ $this->dateTime->format('d'));
Loading history...
Bug introduced by
$this->dateTime->format('m') of type string is incompatible with the type integer expected by parameter $month of Palmtree\Chrono\Date::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

96
        return $this->setDate($year, /** @scrutinizer ignore-type */ $this->dateTime->format('m'), $this->dateTime->format('d'));
Loading history...
97
    }
98
99
    public function setMonth(int $month): self
100
    {
101
        return $this->setDate($this->dateTime->format('Y'), $month, $this->dateTime->format('d'));
0 ignored issues
show
Bug introduced by
$this->dateTime->format('d') of type string is incompatible with the type integer expected by parameter $day of Palmtree\Chrono\Date::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        return $this->setDate($this->dateTime->format('Y'), $month, /** @scrutinizer ignore-type */ $this->dateTime->format('d'));
Loading history...
Bug introduced by
$this->dateTime->format('Y') of type string is incompatible with the type integer expected by parameter $year of Palmtree\Chrono\Date::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        return $this->setDate(/** @scrutinizer ignore-type */ $this->dateTime->format('Y'), $month, $this->dateTime->format('d'));
Loading history...
102
    }
103
104 1
    public function setDay(int $day): self
105
    {
106 1
        return $this->setDate($this->dateTime->format('Y'), $this->dateTime->format('m'), $day);
0 ignored issues
show
Bug introduced by
$this->dateTime->format('m') of type string is incompatible with the type integer expected by parameter $month of Palmtree\Chrono\Date::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
        return $this->setDate($this->dateTime->format('Y'), /** @scrutinizer ignore-type */ $this->dateTime->format('m'), $day);
Loading history...
Bug introduced by
$this->dateTime->format('Y') of type string is incompatible with the type integer expected by parameter $year of Palmtree\Chrono\Date::setDate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
        return $this->setDate(/** @scrutinizer ignore-type */ $this->dateTime->format('Y'), $this->dateTime->format('m'), $day);
Loading history...
107
    }
108
109
    /**
110
     * @param int $year
111
     * @param int $month
112
     * @param int $day
113
     *
114
     * @return self
115
     */
116 1
    public function setDate(int $year, int $month, int $day)
117
    {
118 1
        $this->dateTime->setDate($year, $month, $day);
119
120 1
        return $this;
121
    }
122
123 3
    public function createClone()
124
    {
125 3
        return clone $this;
126
    }
127
128 3
    public function __clone()
129
    {
130 3
        $this->dateTime = clone $this->dateTime;
131 3
    }
132
133 2
    public static function min(...$dates): ?self
134
    {
135
        return \array_reduce($dates, function (?self $carry, self $dateTime) {
136 2
            if (!$carry || $dateTime->isBefore($carry)) {
137 2
                $carry = $dateTime;
138
            }
139
140 2
            return $carry;
141 2
        });
142
    }
143
144 2
    public static function max(...$dates): ?self
145
    {
146
        return \array_reduce($dates, function (?self $carry, self $dateTime) {
147 2
            if (!$carry || $dateTime->isAfter($carry)) {
148 2
                $carry = $dateTime;
149
            }
150
151 2
            return $carry;
152 2
        });
153
    }
154
155 10
    protected function getFormatFromTimePrecision(?string $precision): string
156
    {
157 10
        return DatePeriods::getDateFormat($precision ?? DatePeriods::DAY);
158
    }
159
160 8
    protected function getDateInterval(int $value, string $period): \DateInterval
161
    {
162
        try {
163 8
            $intervalCode = TimePeriods::getIntervalCode($period);
164 4
            $prefix       = 'PT';
165 6
        } catch (\InvalidArgumentException $e) {
166 6
            $intervalCode = DatePeriods::getIntervalCode($period);
167 6
            $prefix       = 'P';
168
        }
169
170 8
        return new \DateInterval("$prefix$value$intervalCode");
171
    }
172
173 17
    private function compareTo(self $date, string $operator, ?string $precision = null): bool
174
    {
175 17
        $format = $this->getFormatFromTimePrecision($precision);
176
177 15
        return \version_compare((int)$this->format($format), (int)$date->format($format), $operator);
178
    }
179
180 28
    protected function createInternalDateTime(string $time = 'now', $timezone = null)
181
    {
182 28
        if (\is_string($timezone)) {
183 1
            $timezone = new \DateTimeZone($timezone);
184
        }
185
186 28
        return new \DateTime($time, $timezone);
187
    }
188
}
189