Passed
Push — master ( 26e9e8...850720 )
by Andy
01:41
created

Date::add()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 13
    public function __construct(string $time = 'now', $timezone = null)
15
    {
16 13
        $this->dateTime = $this->createInternalDateTime($time, $timezone);
17
18 13
        $this->dateTime->setTime(0, 0);
19 13
    }
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 22
    public function format(string $format): string
32
    {
33 22
        return $this->dateTime->format($format);
34
    }
35
36 9
    public function isSame(self $date, ?string $precision = null): bool
37
    {
38 9
        return $this->compareTo($date, ComparisonOperators::EQUAL_TO, $precision);
39
    }
40
41 3
    public function isBefore(self $date, ?string $precision = null): bool
42
    {
43 3
        return $this->compareTo($date, ComparisonOperators::LESS_THAN, $precision);
44
    }
45
46 1
    public function isSameOrBefore(self $date, ?string $precision = null): bool
47
    {
48 1
        return $this->compareTo($date, ComparisonOperators::LESS_THAN_OR_EQUAL_TO, $precision);
49
    }
50
51 3
    public function isAfter(self $date, ?string $precision = null): bool
52
    {
53 3
        return $this->compareTo($date, ComparisonOperators::GREATER_THAN, $precision);
54
    }
55
56 1
    public function isSameOrAfter(self $date, ?string $precision = null): bool
57
    {
58 1
        return $this->compareTo($date, ComparisonOperators::GREATER_THAN_OR_EQUAL_TO, $precision);
59
    }
60
61 3
    public function add(int $value, string $period): self
62
    {
63 3
        $this->dateTime->add($this->getDateInterval($value, $period));
64
65 3
        return $this;
66
    }
67
68 3
    public function subtract(int $value, string $period): self
69
    {
70 3
        $this->dateTime->sub($this->getDateInterval($value, $period));
71
72 3
        return $this;
73
    }
74
75 1
    public function isToday(): bool
76
    {
77 1
        $today = new self('now', $this->dateTime->getTimezone());
78
79 1
        return $this->isSame($today, DatePeriods::DAY);
80
    }
81
82
    public function setYear(int $year): self
83
    {
84
        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

84
        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

84
        return $this->setDate($year, /** @scrutinizer ignore-type */ $this->dateTime->format('m'), $this->dateTime->format('d'));
Loading history...
85
    }
86
87
    public function setMonth(int $month): self
88
    {
89
        return $this->setDate($this->dateTime->format('Y'), $month, $this->dateTime->format('d'));
0 ignored issues
show
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

89
        return $this->setDate(/** @scrutinizer ignore-type */ $this->dateTime->format('Y'), $month, $this->dateTime->format('d'));
Loading history...
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

89
        return $this->setDate($this->dateTime->format('Y'), $month, /** @scrutinizer ignore-type */ $this->dateTime->format('d'));
Loading history...
90
    }
91
92
    public function setDay(int $day): self
93
    {
94
        return $this->setDate($this->dateTime->format('Y'), $this->dateTime->format('m'), $day);
0 ignored issues
show
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

94
        return $this->setDate(/** @scrutinizer ignore-type */ $this->dateTime->format('Y'), $this->dateTime->format('m'), $day);
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

94
        return $this->setDate($this->dateTime->format('Y'), /** @scrutinizer ignore-type */ $this->dateTime->format('m'), $day);
Loading history...
95
    }
96
97
    public function setDate(int $year, int $month, int $day): self
98
    {
99
        $this->dateTime->setDate($year, $month, $day);
100
101
        return $this;
102
    }
103
104 2
    public static function min(...$dates): ?self
105
    {
106
        return \array_reduce($dates, function (?self $carry, self $dateTime) {
107 2
            if (!$carry || $dateTime->isBefore($carry)) {
108 2
                $carry = $dateTime;
109
            }
110
111 2
            return $carry;
112 2
        });
113
    }
114
115 2
    public static function max(...$dates): ?self
116
    {
117
        return \array_reduce($dates, function (?self $carry, self $dateTime) {
118 2
            if (!$carry || $dateTime->isAfter($carry)) {
119 2
                $carry = $dateTime;
120
            }
121
122 2
            return $carry;
123 2
        });
124
    }
125
126 10
    protected function getFormatFromTimePrecision(?string $precision): string
127
    {
128 10
        return DatePeriods::getDateFormat($precision ?? DatePeriods::DAY);
129
    }
130
131 6
    protected function getDateInterval(int $value, string $period): \DateInterval
132
    {
133
        try {
134 6
            $intervalCode = TimePeriods::getIntervalCode($period);
135 4
            $prefix       = 'PT';
136 4
        } catch (\InvalidArgumentException $e) {
137 4
            $intervalCode = DatePeriods::getIntervalCode($period);
138 4
            $prefix       = 'P';
139
        }
140
141 6
        return new \DateInterval("$prefix$value$intervalCode");
142
    }
143
144 17
    private function compareTo(self $date, string $operator, ?string $precision = null): bool
145
    {
146 17
        $format = $this->getFormatFromTimePrecision($precision);
147
148 15
        return \version_compare((int)$this->format($format), (int)$date->format($format), $operator);
149
    }
150
151 25
    protected function createInternalDateTime(string $time = 'now', $timezone = null)
152
    {
153 25
        if (\is_string($timezone)) {
154 1
            $timezone = new \DateTimeZone($timezone);
155
        }
156
157 25
        return new \DateTime($time, $timezone);
158
    }
159
}
160