Completed
Push — master ( 8b40f4...1a4202 )
by Peter
13:15
created

DateInterval::equal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 4
Ratio 100 %

Importance

Changes 0
Metric Value
dl 4
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * GpsLab component.
4
 *
5
 * @author    Peter Gribanov <[email protected]>
6
 * @copyright Copyright (c) 2016, Peter Gribanov
7
 * @license   http://opensource.org/licenses/MIT
8
 */
9
10
namespace GpsLab\Component\Interval\Date;
11
12
use GpsLab\Component\Interval\Exception\IncorrectIntervalException;
13
use GpsLab\Component\Interval\Exception\InvalidIntervalFormatException;
14
use GpsLab\Component\Interval\IntervalComparator;
15
use GpsLab\Component\Interval\ComparableIntervalInterface;
16
use GpsLab\Component\Interval\IntervalPointInterface;
17
use GpsLab\Component\Interval\IntervalType;
18
19 View Code Duplication
class DateInterval implements ComparableIntervalInterface
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
20
{
21
    /**
22
     * @var string
23
     */
24
    const REGEXP = '/^
25
        (?:\(|\[)                   # start type char
26
        \s*
27
        (?<start>\d{4}-\d{2}-\d{2}) # start point
28
        \s*,\s*                     # separator
29
        (?<end>\d{4}-\d{2}-\d{2})   # end point
30
        \s*
31
        (?:\)|\])                   # end type char
32
    $/x';
33
34
    /**
35
     * @var IntervalType
36
     */
37
    private $type;
38
39
    /**
40
     * @var IntervalComparator
41
     */
42
    private $comparator;
43
44
    /**
45
     * @var DateIntervalPoint
46
     */
47
    private $start;
48
49
    /**
50
     * @var DateIntervalPoint
51
     */
52
    private $end;
53
54
    /**
55
     * @param DateIntervalPoint $start
56
     * @param DateIntervalPoint $end
57
     * @param IntervalType $type
58
     */
59
    private function __construct(DateIntervalPoint $start, DateIntervalPoint $end, IntervalType $type)
60
    {
61
        if ($start->gte($end)) {
62
            throw IncorrectIntervalException::create();
63
        }
64
65
        $this->type = $type;
66
        $this->start = $start;
67
        $this->end = $end;
68
        $this->comparator = new IntervalComparator($this);
69
    }
70
71
    /**
72
     * @param \DateTime $start
73
     * @param \DateTime $end
74
     * @param IntervalType $type
75
     *
76
     * @return self
77
     */
78
    public static function create(\DateTime $start, \DateTime $end, IntervalType $type)
79
    {
80
        return new self(new DateIntervalPoint($start), new DateIntervalPoint($end), $type);
81
    }
82
83
    /**
84
     * @param \DateTime $start
85
     * @param \DateTime $end
86
     *
87
     * @return self
88
     */
89
    public static function closed(\DateTime $start, \DateTime $end)
90
    {
91
        return static::create($start, $end, IntervalType::closed());
92
    }
93
94
    /**
95
     * @param \DateTime $start
96
     * @param \DateTime $end
97
     *
98
     * @return self
99
     */
100
    public static function halfClosed(\DateTime $start, \DateTime $end)
101
    {
102
        return static::create($start, $end, IntervalType::halfClosed());
103
    }
104
105
    /**
106
     * @param \DateTime $start
107
     * @param \DateTime $end
108
     *
109
     * @return self
110
     */
111
    public static function halfOpen(\DateTime $start, \DateTime $end)
112
    {
113
        return static::create($start, $end, IntervalType::halfOpen());
114
    }
115
116
    /**
117
     * @param \DateTime $start
118
     * @param \DateTime $end
119
     *
120
     * @return self
121
     */
122
    public static function open(\DateTime $start, \DateTime $end)
123
    {
124
        return static::create($start, $end, IntervalType::open());
125
    }
126
127
    /**
128
     * Create interval from string.
129
     *
130
     * Example formats for all interval types:
131
     *   [2016-12-09, 2016-12-21]
132
     *   (2015-03-07, 2015-10-19]
133
     *   [2014-09-11, 2015-02-08)
134
     *   (2013-10-27, 2013-10-30)
135
     *
136
     * Spaces are ignored in format.
137
     *
138
     * @param string $string
139
     *
140
     * @return self
141
     */
142
    public static function fromString($string)
143
    {
144
        if (!preg_match(self::REGEXP, $string, $match)) {
145
            throw InvalidIntervalFormatException::create('[YYYY-MM-DD, YYYY-MM-DD]', $string);
146
        }
147
148
        return self::create(
149
            new \DateTime($match['start']),
150
            new \DateTime($match['end']),
151
            IntervalType::fromString($string)
152
        );
153
    }
154
155
    /**
156
     * @param DateInterval $interval
157
     *
158
     * @return bool
159
     */
160
    public function equal(DateInterval $interval)
161
    {
162
        return $this->comparator->equal($interval);
163
    }
164
165
    /**
166
     * @param \DateTime $point
167
     *
168
     * @return bool
169
     */
170
    public function contains(\DateTime $point)
171
    {
172
        return $this->comparator->contains(new DateIntervalPoint($point));
173
    }
174
175
    /**
176
     * @param DateInterval $interval
177
     * @param bool $check_interval_type
178
     *
179
     * @return bool
180
     */
181
    public function intersects(DateInterval $interval, $check_interval_type = true)
182
    {
183
        return $this->comparator->intersects($interval, $check_interval_type);
184
    }
185
186
    /**
187
     * @param DateInterval $interval
188
     *
189
     * @return DateInterval|null
190
     */
191
    public function intersection(DateInterval $interval)
192
    {
193
        return $this->comparator->intersection($interval);
194
    }
195
196
    /**
197
     * The point is before the interval.
198
     *
199
     * @param \DateTime $point
200
     *
201
     * @return bool
202
     */
203
    public function before(\DateTime $point)
204
    {
205
        return $this->comparator->before(new DateIntervalPoint($point));
206
    }
207
208
    /**
209
     * The point is after the interval.
210
     *
211
     * @param \DateTime $point
212
     *
213
     * @return bool
214
     */
215
    public function after(\DateTime $point)
216
    {
217
        return $this->comparator->after(new DateIntervalPoint($point));
218
    }
219
220
    /**
221
     * @return IntervalType
222
     */
223
    public function type()
224
    {
225
        return $this->type;
226
    }
227
228
    /**
229
     * @return \DateTime
230
     */
231
    public function start()
232
    {
233
        return $this->start->value();
234
    }
235
236
    /**
237
     * @return \DateTime
238
     */
239
    public function end()
240
    {
241
        return $this->end->value();
242
    }
243
244
    /**
245
     * @return DateIntervalPoint
246
     */
247
    public function startPoint()
248
    {
249
        return $this->start;
250
    }
251
252
    /**
253
     * @return DateIntervalPoint
254
     */
255
    public function endPoint()
256
    {
257
        return $this->end;
258
    }
259
260
    /**
261
     * Returns a copy of this Interval with the start point altered.
262
     *
263
     * @param IntervalPointInterface|DateIntervalPoint $start
264
     *
265
     * @return self
266
     */
267
    public function withStart(IntervalPointInterface $start)
268
    {
269
        return new self($start, $this->end, $this->type);
0 ignored issues
show
Compatibility introduced by
$start of type object<GpsLab\Component\...IntervalPointInterface> is not a sub-type of object<GpsLab\Component\...Date\DateIntervalPoint>. It seems like you assume a concrete implementation of the interface GpsLab\Component\Interval\IntervalPointInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
270
    }
271
272
    /**
273
     * Returns a copy of this Interval with the end point altered.
274
     *
275
     * @param IntervalPointInterface|DateIntervalPoint $end
276
     *
277
     * @return self
278
     */
279
    public function withEnd(IntervalPointInterface $end)
280
    {
281
        return new self($this->start, $end, $this->type);
0 ignored issues
show
Compatibility introduced by
$end of type object<GpsLab\Component\...IntervalPointInterface> is not a sub-type of object<GpsLab\Component\...Date\DateIntervalPoint>. It seems like you assume a concrete implementation of the interface GpsLab\Component\Interval\IntervalPointInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
282
    }
283
284
    /**
285
     * Returns a copy of this Interval with the interval type altered.
286
     *
287
     * @param IntervalType $type
288
     *
289
     * @return self
290
     */
291
    public function withType(IntervalType $type)
292
    {
293
        return new self($this->start, $this->end, $type);
294
    }
295
296
    /**
297
     * @return string
298
     */
299
    public function __toString()
300
    {
301
        return $this->type->getReadable($this);
302
    }
303
}
304