Code Duplication    Length = 386-386 lines in 5 locations

src/Date/DateInterval.php 1 location

@@ 19-404 (lines=386) @@
16
use GpsLab\Component\Interval\IntervalPointInterface;
17
use GpsLab\Component\Interval\IntervalType;
18
19
class DateInterval implements ComparableIntervalInterface
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
     * Checks if this interval is equal to the specified interval.
157
     *
158
     * @param DateInterval $interval
159
     *
160
     * @return bool
161
     */
162
    public function equal(self $interval)
163
    {
164
        return $this->comparator->equal($interval);
165
    }
166
167
    /**
168
     * Does this interval contain the specified point.
169
     *
170
     * @param \DateTime $point
171
     *
172
     * @return bool
173
     */
174
    public function contains(\DateTime $point)
175
    {
176
        return $this->comparator->contains(new DateIntervalPoint($point));
177
    }
178
179
    /**
180
     * Does this interval intersect the specified interval.
181
     *
182
     * @param DateInterval $interval
183
     *
184
     * @return bool
185
     */
186
    public function intersects(self $interval)
187
    {
188
        return $this->comparator->intersects($interval);
189
    }
190
191
    /**
192
     * Gets the intersection between this interval and another interval.
193
     *
194
     * @param DateInterval $interval
195
     *
196
     * @return self|null
197
     */
198
    public function intersection(self $interval)
199
    {
200
        return $this->comparator->intersection($interval);
201
    }
202
203
    /**
204
     * Gets the covered interval between this Interval and another interval.
205
     *
206
     * @param DateInterval $interval
207
     *
208
     * @return self
209
     */
210
    public function cover(self $interval)
211
    {
212
        return $this->comparator->cover($interval);
213
    }
214
215
    /**
216
     * Gets the gap between this interval and another interval.
217
     *
218
     * @param DateInterval $interval
219
     *
220
     * @return self|null
221
     */
222
    public function gap(self $interval)
223
    {
224
        return $this->comparator->gap($interval);
225
    }
226
227
    /**
228
     * Does this interval abuts with the interval specified.
229
     *
230
     * @param DateInterval $interval
231
     *
232
     * @return bool
233
     */
234
    public function abuts(self $interval)
235
    {
236
        return $this->comparator->abuts($interval);
237
    }
238
239
    /**
240
     * Joins the interval between the adjacent.
241
     *
242
     * @param DateInterval $interval
243
     *
244
     * @return self|null
245
     */
246
    public function join(self $interval)
247
    {
248
        return $this->comparator->join($interval);
249
    }
250
251
    /**
252
     * Gets the union between this interval and another interval.
253
     *
254
     * @param DateInterval $interval
255
     *
256
     * @return self|null
257
     */
258
    public function union(self $interval)
259
    {
260
        return $this->comparator->union($interval);
261
    }
262
263
    /**
264
     * The point is before the interval.
265
     *
266
     * @param \DateTime $point
267
     *
268
     * @return bool
269
     */
270
    public function before(\DateTime $point)
271
    {
272
        return $this->comparator->before(new DateIntervalPoint($point));
273
    }
274
275
    /**
276
     * The point is after the interval.
277
     *
278
     * @param \DateTime $point
279
     *
280
     * @return bool
281
     */
282
    public function after(\DateTime $point)
283
    {
284
        return $this->comparator->after(new DateIntervalPoint($point));
285
    }
286
287
    /**
288
     * @param \DateInterval|null $step
289
     *
290
     * @return \Generator
291
     */
292
    public function iterate(\DateInterval $step = null)
293
    {
294
        $step = $step ?: new \DateInterval('P1D');
295
296
        $date = $this->start();
297
        $end = $this->end();
298
299
        if ($this->type->startExcluded()) {
300
            $date->add($step);
301
        }
302
303
        while ($date < $end || (!$this->type->endExcluded() && $date == $end)) {
304
            yield $date;
305
            $date->add($step);
306
        }
307
    }
308
309
    /**
310
     * @param \DateInterval|null $step
311
     *
312
     * @return \DatePeriod
313
     */
314
    public function period(\DateInterval $step = null)
315
    {
316
        $step = $step ?: new \DateInterval('P1D');
317
318
        return new \DatePeriod($this->start(), $step, $this->end());
319
    }
320
321
    /**
322
     * @return IntervalType
323
     */
324
    public function type()
325
    {
326
        return $this->type;
327
    }
328
329
    /**
330
     * @return \DateTime
331
     */
332
    public function start()
333
    {
334
        return $this->start->value();
335
    }
336
337
    /**
338
     * @return \DateTime
339
     */
340
    public function end()
341
    {
342
        return $this->end->value();
343
    }
344
345
    /**
346
     * @return DateIntervalPoint
347
     */
348
    public function startPoint()
349
    {
350
        return $this->start;
351
    }
352
353
    /**
354
     * @return DateIntervalPoint
355
     */
356
    public function endPoint()
357
    {
358
        return $this->end;
359
    }
360
361
    /**
362
     * Returns a copy of this Interval with the start point altered.
363
     *
364
     * @param IntervalPointInterface|DateIntervalPoint $start
365
     *
366
     * @return self
367
     */
368
    public function withStart(IntervalPointInterface $start)
369
    {
370
        return new self($start, $this->end, $this->type);
371
    }
372
373
    /**
374
     * Returns a copy of this Interval with the end point altered.
375
     *
376
     * @param IntervalPointInterface|DateIntervalPoint $end
377
     *
378
     * @return self
379
     */
380
    public function withEnd(IntervalPointInterface $end)
381
    {
382
        return new self($this->start, $end, $this->type);
383
    }
384
385
    /**
386
     * Returns a copy of this Interval with the interval type altered.
387
     *
388
     * @param IntervalType $type
389
     *
390
     * @return self
391
     */
392
    public function withType(IntervalType $type)
393
    {
394
        return new self($this->start, $this->end, $type);
395
    }
396
397
    /**
398
     * @return string
399
     */
400
    public function __toString()
401
    {
402
        return $this->type->formatInterval($this);
403
    }
404
}
405

src/DateTime/DateTimeInterval.php 1 location

@@ 19-404 (lines=386) @@
16
use GpsLab\Component\Interval\IntervalPointInterface;
17
use GpsLab\Component\Interval\IntervalType;
18
19
class DateTimeInterval implements ComparableIntervalInterface
20
{
21
    /**
22
     * @var string
23
     */
24
    const REGEXP = '/^
25
        (?:\(|\[)                                       # start type char
26
        \s*
27
        (?<start>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}) # start point
28
        \s*,\s*                                         # separator
29
        (?<end>\d{4}-\d{2}-\d{2}\s+\d{2}:\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 DateTimeIntervalPoint
46
     */
47
    private $start;
48
49
    /**
50
     * @var DateTimeIntervalPoint
51
     */
52
    private $end;
53
54
    /**
55
     * @param DateTimeIntervalPoint $start
56
     * @param DateTimeIntervalPoint $end
57
     * @param IntervalType $type
58
     */
59
    private function __construct(DateTimeIntervalPoint $start, DateTimeIntervalPoint $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 DateTimeIntervalPoint($start), new DateTimeIntervalPoint($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 02:55:00, 2016-12-21 12:30:12]
132
     *   (2015-03-07 12:04:45, 2015-10-19 19:38:14]
133
     *   [2014-09-11 17:31:09, 2015-02-08 23:45:58)
134
     *   (2013-10-27 15:03:37, 2013-10-30 05:06:34)
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 HH:II:SS, YYYY-MM-DD HH:II:SS]', $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
     * Checks if this interval is equal to the specified interval.
157
     *
158
     * @param DateTimeInterval $interval
159
     *
160
     * @return bool
161
     */
162
    public function equal(self $interval)
163
    {
164
        return $this->comparator->equal($interval);
165
    }
166
167
    /**
168
     * Does this interval contain the specified point.
169
     *
170
     * @param \DateTime $point
171
     *
172
     * @return bool
173
     */
174
    public function contains(\DateTime $point)
175
    {
176
        return $this->comparator->contains(new DateTimeIntervalPoint($point));
177
    }
178
179
    /**
180
     * Does this interval intersect the specified interval.
181
     *
182
     * @param DateTimeInterval $interval
183
     *
184
     * @return bool
185
     */
186
    public function intersects(self $interval)
187
    {
188
        return $this->comparator->intersects($interval);
189
    }
190
191
    /**
192
     * Gets the intersection between this interval and another interval.
193
     *
194
     * @param DateTimeInterval $interval
195
     *
196
     * @return self|null
197
     */
198
    public function intersection(self $interval)
199
    {
200
        return $this->comparator->intersection($interval);
201
    }
202
203
    /**
204
     * Gets the covered interval between this Interval and another interval.
205
     *
206
     * @param DateTimeInterval $interval
207
     *
208
     * @return self
209
     */
210
    public function cover(self $interval)
211
    {
212
        return $this->comparator->cover($interval);
213
    }
214
215
    /**
216
     * Gets the gap between this interval and another interval.
217
     *
218
     * @param DateTimeInterval $interval
219
     *
220
     * @return self|null
221
     */
222
    public function gap(self $interval)
223
    {
224
        return $this->comparator->gap($interval);
225
    }
226
227
    /**
228
     * Does this interval abuts with the interval specified.
229
     *
230
     * @param DateTimeInterval $interval
231
     *
232
     * @return bool
233
     */
234
    public function abuts(self $interval)
235
    {
236
        return $this->comparator->abuts($interval);
237
    }
238
239
    /**
240
     * Joins the interval between the adjacent.
241
     *
242
     * @param DateTimeInterval $interval
243
     *
244
     * @return self|null
245
     */
246
    public function join(self $interval)
247
    {
248
        return $this->comparator->join($interval);
249
    }
250
251
    /**
252
     * Gets the union between this interval and another interval.
253
     *
254
     * @param DateTimeInterval $interval
255
     *
256
     * @return self|null
257
     */
258
    public function union(self $interval)
259
    {
260
        return $this->comparator->union($interval);
261
    }
262
263
    /**
264
     * The point is before the interval.
265
     *
266
     * @param \DateTime $point
267
     *
268
     * @return bool
269
     */
270
    public function before(\DateTime $point)
271
    {
272
        return $this->comparator->before(new DateTimeIntervalPoint($point));
273
    }
274
275
    /**
276
     * The point is after the interval.
277
     *
278
     * @param \DateTime $point
279
     *
280
     * @return bool
281
     */
282
    public function after(\DateTime $point)
283
    {
284
        return $this->comparator->after(new DateTimeIntervalPoint($point));
285
    }
286
287
    /**
288
     * @param \DateInterval|null $step
289
     *
290
     * @return \Generator
291
     */
292
    public function iterate(\DateInterval $step = null)
293
    {
294
        $step = $step ?: new \DateInterval('P1D');
295
296
        $date = $this->start();
297
        $end = $this->end();
298
299
        if ($this->type->startExcluded()) {
300
            $date->add($step);
301
        }
302
303
        while ($date < $end || (!$this->type->endExcluded() && $date == $end)) {
304
            yield $date;
305
            $date->add($step);
306
        }
307
    }
308
309
    /**
310
     * @param \DateInterval|null $step
311
     *
312
     * @return \DatePeriod
313
     */
314
    public function period(\DateInterval $step = null)
315
    {
316
        $step = $step ?: new \DateInterval('P1D');
317
318
        return new \DatePeriod($this->start(), $step, $this->end());
319
    }
320
321
    /**
322
     * @return IntervalType
323
     */
324
    public function type()
325
    {
326
        return $this->type;
327
    }
328
329
    /**
330
     * @return \DateTime
331
     */
332
    public function start()
333
    {
334
        return $this->start->value();
335
    }
336
337
    /**
338
     * @return \DateTime
339
     */
340
    public function end()
341
    {
342
        return $this->end->value();
343
    }
344
345
    /**
346
     * @return DateTimeIntervalPoint
347
     */
348
    public function startPoint()
349
    {
350
        return $this->start;
351
    }
352
353
    /**
354
     * @return DateTimeIntervalPoint
355
     */
356
    public function endPoint()
357
    {
358
        return $this->end;
359
    }
360
361
    /**
362
     * Returns a copy of this Interval with the start point altered.
363
     *
364
     * @param IntervalPointInterface|DateTimeIntervalPoint $start
365
     *
366
     * @return self
367
     */
368
    public function withStart(IntervalPointInterface $start)
369
    {
370
        return new self($start, $this->end, $this->type);
371
    }
372
373
    /**
374
     * Returns a copy of this Interval with the end point altered.
375
     *
376
     * @param IntervalPointInterface|DateTimeIntervalPoint $end
377
     *
378
     * @return self
379
     */
380
    public function withEnd(IntervalPointInterface $end)
381
    {
382
        return new self($this->start, $end, $this->type);
383
    }
384
385
    /**
386
     * Returns a copy of this Interval with the interval type altered.
387
     *
388
     * @param IntervalType $type
389
     *
390
     * @return self
391
     */
392
    public function withType(IntervalType $type)
393
    {
394
        return new self($this->start, $this->end, $type);
395
    }
396
397
    /**
398
     * @return string
399
     */
400
    public function __toString()
401
    {
402
        return $this->type->formatInterval($this);
403
    }
404
}
405

src/Month/MonthInterval.php 1 location

@@ 20-405 (lines=386) @@
17
use GpsLab\Component\Interval\IntervalPointInterface;
18
use GpsLab\Component\Interval\IntervalType;
19
20
class MonthInterval implements ComparableIntervalInterface
21
{
22
    /**
23
     * @var string
24
     */
25
    const REGEXP = '/^
26
        (?:\(|\[)              # start type char
27
        \s*
28
        (?<start>\d{4}\/\d{2}) # start point
29
        \s*,\s*                # separator
30
        (?<end>\d{4}\/\d{2})   # end point
31
        \s*
32
        (?:\)|\])              # end type char
33
    $/x';
34
35
    /**
36
     * @var IntervalType
37
     */
38
    private $type;
39
40
    /**
41
     * @var IntervalComparator
42
     */
43
    private $comparator;
44
45
    /**
46
     * @var MonthIntervalPoint
47
     */
48
    private $start;
49
50
    /**
51
     * @var MonthIntervalPoint
52
     */
53
    private $end;
54
55
    /**
56
     * @param MonthIntervalPoint $start
57
     * @param MonthIntervalPoint $end
58
     * @param IntervalType $type
59
     */
60
    private function __construct(MonthIntervalPoint $start, MonthIntervalPoint $end, IntervalType $type)
61
    {
62
        if ($start->gte($end)) {
63
            throw IncorrectIntervalException::create();
64
        }
65
66
        $this->type = $type;
67
        $this->start = $start;
68
        $this->end = $end;
69
        $this->comparator = new IntervalComparator($this);
70
    }
71
72
    /**
73
     * @param \DateTime $start
74
     * @param \DateTime $end
75
     * @param IntervalType $type
76
     *
77
     * @return self
78
     */
79
    public static function create(\DateTime $start, \DateTime $end, IntervalType $type)
80
    {
81
        return new self(new MonthIntervalPoint($start), new MonthIntervalPoint($end), $type);
82
    }
83
84
    /**
85
     * @param \DateTime $start
86
     * @param \DateTime $end
87
     *
88
     * @return self
89
     */
90
    public static function closed(\DateTime $start, \DateTime $end)
91
    {
92
        return static::create($start, $end, IntervalType::closed());
93
    }
94
95
    /**
96
     * @param \DateTime $start
97
     * @param \DateTime $end
98
     *
99
     * @return self
100
     */
101
    public static function halfClosed(\DateTime $start, \DateTime $end)
102
    {
103
        return static::create($start, $end, IntervalType::halfClosed());
104
    }
105
106
    /**
107
     * @param \DateTime $start
108
     * @param \DateTime $end
109
     *
110
     * @return self
111
     */
112
    public static function halfOpen(\DateTime $start, \DateTime $end)
113
    {
114
        return static::create($start, $end, IntervalType::halfOpen());
115
    }
116
117
    /**
118
     * @param \DateTime $start
119
     * @param \DateTime $end
120
     *
121
     * @return self
122
     */
123
    public static function open(\DateTime $start, \DateTime $end)
124
    {
125
        return static::create($start, $end, IntervalType::open());
126
    }
127
128
    /**
129
     * Create interval from string.
130
     *
131
     * Example formats for all interval types:
132
     *   [2016/12, 2016/12]
133
     *   (2015/03, 2015/10]
134
     *   [2014/09, 2015/02)
135
     *   (2013/10, 2013/10)
136
     *
137
     * Spaces are ignored in format.
138
     *
139
     * @param string $string
140
     *
141
     * @return self
142
     */
143
    public static function fromString($string)
144
    {
145
        if (!preg_match(self::REGEXP, $string, $match)) {
146
            throw InvalidIntervalFormatException::create('[YYYY/MM, YYYY/MM]', $string);
147
        }
148
149
        return self::create(
150
            new \DateTime($match['start'].'/01'),
151
            new \DateTime($match['end'].'/01'),
152
            IntervalType::fromString($string)
153
        );
154
    }
155
156
    /**
157
     * Checks if this interval is equal to the specified interval.
158
     *
159
     * @param MonthInterval $interval
160
     *
161
     * @return bool
162
     */
163
    public function equal(self $interval)
164
    {
165
        return $this->comparator->equal($interval);
166
    }
167
168
    /**
169
     * Does this interval contain the specified point.
170
     *
171
     * @param \DateTime $point
172
     *
173
     * @return bool
174
     */
175
    public function contains(\DateTime $point)
176
    {
177
        return $this->comparator->contains(new MonthIntervalPoint($point));
178
    }
179
180
    /**
181
     * Does this interval intersect the specified interval.
182
     *
183
     * @param MonthInterval $interval
184
     *
185
     * @return bool
186
     */
187
    public function intersects(self $interval)
188
    {
189
        return $this->comparator->intersects($interval);
190
    }
191
192
    /**
193
     * Gets the intersection between this interval and another interval.
194
     *
195
     * @param MonthInterval $interval
196
     *
197
     * @return self|null
198
     */
199
    public function intersection(self $interval)
200
    {
201
        return $this->comparator->intersection($interval);
202
    }
203
204
    /**
205
     * Gets the covered interval between this Interval and another interval.
206
     *
207
     * @param MonthInterval $interval
208
     *
209
     * @return self
210
     */
211
    public function cover(self $interval)
212
    {
213
        return $this->comparator->cover($interval);
214
    }
215
216
    /**
217
     * Gets the gap between this interval and another interval.
218
     *
219
     * @param MonthInterval $interval
220
     *
221
     * @return self|null
222
     */
223
    public function gap(self $interval)
224
    {
225
        return $this->comparator->gap($interval);
226
    }
227
228
    /**
229
     * Does this interval abuts with the interval specified.
230
     *
231
     * @param MonthInterval $interval
232
     *
233
     * @return bool
234
     */
235
    public function abuts(self $interval)
236
    {
237
        return $this->comparator->abuts($interval);
238
    }
239
240
    /**
241
     * Joins the interval between the adjacent.
242
     *
243
     * @param MonthInterval $interval
244
     *
245
     * @return self|null
246
     */
247
    public function join(self $interval)
248
    {
249
        return $this->comparator->join($interval);
250
    }
251
252
    /**
253
     * Gets the union between this interval and another interval.
254
     *
255
     * @param MonthInterval $interval
256
     *
257
     * @return self|null
258
     */
259
    public function union(self $interval)
260
    {
261
        return $this->comparator->union($interval);
262
    }
263
264
    /**
265
     * The point is before the interval.
266
     *
267
     * @param \DateTime $point
268
     *
269
     * @return bool
270
     */
271
    public function before(\DateTime $point)
272
    {
273
        return $this->comparator->before(new MonthIntervalPoint($point));
274
    }
275
276
    /**
277
     * The point is after the interval.
278
     *
279
     * @param \DateTime $point
280
     *
281
     * @return bool
282
     */
283
    public function after(\DateTime $point)
284
    {
285
        return $this->comparator->after(new MonthIntervalPoint($point));
286
    }
287
288
    /**
289
     * @param \DateInterval|null $step
290
     *
291
     * @return \Generator
292
     */
293
    public function iterate(\DateInterval $step = null)
294
    {
295
        $step = $step ?: new \DateInterval('P1M');
296
297
        $date = $this->start();
298
        $end = $this->end();
299
300
        if ($this->type->startExcluded()) {
301
            $date->add($step);
302
        }
303
304
        while ($date < $end || (!$this->type->endExcluded() && $date == $end)) {
305
            yield $date;
306
            $date->add($step);
307
        }
308
    }
309
310
    /**
311
     * @param \DateInterval|null $step
312
     *
313
     * @return \DatePeriod
314
     */
315
    public function period(\DateInterval $step = null)
316
    {
317
        $step = $step ?: new \DateInterval('P1M');
318
319
        return new \DatePeriod($this->start(), $step, $this->end());
320
    }
321
322
    /**
323
     * @return IntervalType
324
     */
325
    public function type()
326
    {
327
        return $this->type;
328
    }
329
330
    /**
331
     * @return \DateTime
332
     */
333
    public function start()
334
    {
335
        return $this->start->value();
336
    }
337
338
    /**
339
     * @return \DateTime
340
     */
341
    public function end()
342
    {
343
        return $this->end->value();
344
    }
345
346
    /**
347
     * @return MonthIntervalPoint
348
     */
349
    public function startPoint()
350
    {
351
        return $this->start;
352
    }
353
354
    /**
355
     * @return MonthIntervalPoint
356
     */
357
    public function endPoint()
358
    {
359
        return $this->end;
360
    }
361
362
    /**
363
     * Returns a copy of this Interval with the start point altered.
364
     *
365
     * @param IntervalPointInterface|MonthIntervalPoint $start
366
     *
367
     * @return self
368
     */
369
    public function withStart(IntervalPointInterface $start)
370
    {
371
        return new self($start, $this->end, $this->type);
372
    }
373
374
    /**
375
     * Returns a copy of this Interval with the end point altered.
376
     *
377
     * @param IntervalPointInterface|MonthIntervalPoint $end
378
     *
379
     * @return self
380
     */
381
    public function withEnd(IntervalPointInterface $end)
382
    {
383
        return new self($this->start, $end, $this->type);
384
    }
385
386
    /**
387
     * Returns a copy of this Interval with the interval type altered.
388
     *
389
     * @param IntervalType $type
390
     *
391
     * @return self
392
     */
393
    public function withType(IntervalType $type)
394
    {
395
        return new self($this->start, $this->end, $type);
396
    }
397
398
    /**
399
     * @return string
400
     */
401
    public function __toString()
402
    {
403
        return $this->type->formatInterval($this);
404
    }
405
}
406

src/Time/TimeInterval.php 1 location

@@ 20-405 (lines=386) @@
17
use GpsLab\Component\Interval\IntervalPointInterface;
18
use GpsLab\Component\Interval\IntervalType;
19
20
class TimeInterval implements ComparableIntervalInterface
21
{
22
    /**
23
     * @var string
24
     */
25
    const REGEXP = '/^
26
        (?:\(|\[)                   # start type char
27
        \s*
28
        (?<start>\d{2}:\d{2}:\d{2}) # start point
29
        \s*,\s*                     # separator
30
        (?<end>\d{2}:\d{2}:\d{2})   # end point
31
        \s*
32
        (?:\)|\])                   # end type char
33
    $/x';
34
35
    /**
36
     * @var IntervalType
37
     */
38
    private $type;
39
40
    /**
41
     * @var IntervalComparator
42
     */
43
    private $comparator;
44
45
    /**
46
     * @var TimeIntervalPoint
47
     */
48
    private $start;
49
50
    /**
51
     * @var TimeIntervalPoint
52
     */
53
    private $end;
54
55
    /**
56
     * @param TimeIntervalPoint $start
57
     * @param TimeIntervalPoint $end
58
     * @param IntervalType $type
59
     */
60
    private function __construct(TimeIntervalPoint $start, TimeIntervalPoint $end, IntervalType $type)
61
    {
62
        if ($start->gte($end)) {
63
            throw IncorrectIntervalException::create();
64
        }
65
66
        $this->type = $type;
67
        $this->start = $start;
68
        $this->end = $end;
69
        $this->comparator = new IntervalComparator($this);
70
    }
71
72
    /**
73
     * @param \DateTime $start
74
     * @param \DateTime $end
75
     * @param IntervalType $type
76
     *
77
     * @return self
78
     */
79
    public static function create(\DateTime $start, \DateTime $end, IntervalType $type)
80
    {
81
        return new self(new TimeIntervalPoint($start), new TimeIntervalPoint($end), $type);
82
    }
83
84
    /**
85
     * @param \DateTime $start
86
     * @param \DateTime $end
87
     *
88
     * @return self
89
     */
90
    public static function closed(\DateTime $start, \DateTime $end)
91
    {
92
        return static::create($start, $end, IntervalType::closed());
93
    }
94
95
    /**
96
     * @param \DateTime $start
97
     * @param \DateTime $end
98
     *
99
     * @return self
100
     */
101
    public static function halfClosed(\DateTime $start, \DateTime $end)
102
    {
103
        return static::create($start, $end, IntervalType::halfClosed());
104
    }
105
106
    /**
107
     * @param \DateTime $start
108
     * @param \DateTime $end
109
     *
110
     * @return self
111
     */
112
    public static function halfOpen(\DateTime $start, \DateTime $end)
113
    {
114
        return static::create($start, $end, IntervalType::halfOpen());
115
    }
116
117
    /**
118
     * @param \DateTime $start
119
     * @param \DateTime $end
120
     *
121
     * @return self
122
     */
123
    public static function open(\DateTime $start, \DateTime $end)
124
    {
125
        return static::create($start, $end, IntervalType::open());
126
    }
127
128
    /**
129
     * Create interval from string.
130
     *
131
     * Example formats for all interval types:
132
     *   [02:55:00, 12:30:12]
133
     *   (12:04:45, 19:38:14]
134
     *   [17:31:09, 23:45:58)
135
     *   (15:03:37, 15:06:34)
136
     *
137
     * Spaces are ignored in format.
138
     *
139
     * @param string $string
140
     *
141
     * @return self
142
     */
143
    public static function fromString($string)
144
    {
145
        if (!preg_match(self::REGEXP, $string, $match)) {
146
            throw InvalidIntervalFormatException::create('[HH:II:SS, HH:II:SS]', $string);
147
        }
148
149
        return self::create(
150
            new \DateTime($match['start']),
151
            new \DateTime($match['end']),
152
            IntervalType::fromString($string)
153
        );
154
    }
155
156
    /**
157
     * Checks if this interval is equal to the specified interval.
158
     *
159
     * @param TimeInterval $interval
160
     *
161
     * @return bool
162
     */
163
    public function equal(self $interval)
164
    {
165
        return $this->comparator->equal($interval);
166
    }
167
168
    /**
169
     * Does this interval contain the specified point.
170
     *
171
     * @param \DateTime $point
172
     *
173
     * @return bool
174
     */
175
    public function contains(\DateTime $point)
176
    {
177
        return $this->comparator->contains(new TimeIntervalPoint($point));
178
    }
179
180
    /**
181
     * Does this interval intersect the specified interval.
182
     *
183
     * @param TimeInterval $interval
184
     *
185
     * @return bool
186
     */
187
    public function intersects(self $interval)
188
    {
189
        return $this->comparator->intersects($interval);
190
    }
191
192
    /**
193
     * Gets the intersection between this interval and another interval.
194
     *
195
     * @param TimeInterval $interval
196
     *
197
     * @return self|null
198
     */
199
    public function intersection(self $interval)
200
    {
201
        return $this->comparator->intersection($interval);
202
    }
203
204
    /**
205
     * Gets the covered interval between this Interval and another interval.
206
     *
207
     * @param TimeInterval $interval
208
     *
209
     * @return self
210
     */
211
    public function cover(self $interval)
212
    {
213
        return $this->comparator->cover($interval);
214
    }
215
216
    /**
217
     * Gets the gap between this interval and another interval.
218
     *
219
     * @param TimeInterval $interval
220
     *
221
     * @return self|null
222
     */
223
    public function gap(self $interval)
224
    {
225
        return $this->comparator->gap($interval);
226
    }
227
228
    /**
229
     * Does this interval abuts with the interval specified.
230
     *
231
     * @param TimeInterval $interval
232
     *
233
     * @return bool
234
     */
235
    public function abuts(self $interval)
236
    {
237
        return $this->comparator->abuts($interval);
238
    }
239
240
    /**
241
     * Joins the interval between the adjacent.
242
     *
243
     * @param TimeInterval $interval
244
     *
245
     * @return self|null
246
     */
247
    public function join(self $interval)
248
    {
249
        return $this->comparator->join($interval);
250
    }
251
252
    /**
253
     * Gets the union between this interval and another interval.
254
     *
255
     * @param TimeInterval $interval
256
     *
257
     * @return self|null
258
     */
259
    public function union(self $interval)
260
    {
261
        return $this->comparator->union($interval);
262
    }
263
264
    /**
265
     * The point is before the interval.
266
     *
267
     * @param \DateTime $point
268
     *
269
     * @return bool
270
     */
271
    public function before(\DateTime $point)
272
    {
273
        return $this->comparator->before(new TimeIntervalPoint($point));
274
    }
275
276
    /**
277
     * The point is after the interval.
278
     *
279
     * @param \DateTime $point
280
     *
281
     * @return bool
282
     */
283
    public function after(\DateTime $point)
284
    {
285
        return $this->comparator->after(new TimeIntervalPoint($point));
286
    }
287
288
    /**
289
     * @param \DateInterval|null $step
290
     *
291
     * @return \Generator
292
     */
293
    public function iterate(\DateInterval $step = null)
294
    {
295
        $step = $step ?: new \DateInterval('PT1M');
296
297
        $date = $this->start();
298
        $end = $this->end();
299
300
        if ($this->type->startExcluded()) {
301
            $date->add($step);
302
        }
303
304
        while ($date < $end || (!$this->type->endExcluded() && $date == $end)) {
305
            yield $date;
306
            $date->add($step);
307
        }
308
    }
309
310
    /**
311
     * @param \DateInterval|null $step
312
     *
313
     * @return \DatePeriod
314
     */
315
    public function period(\DateInterval $step = null)
316
    {
317
        $step = $step ?: new \DateInterval('PT1M');
318
319
        return new \DatePeriod($this->start(), $step, $this->end());
320
    }
321
322
    /**
323
     * @return IntervalType
324
     */
325
    public function type()
326
    {
327
        return $this->type;
328
    }
329
330
    /**
331
     * @return \DateTime
332
     */
333
    public function start()
334
    {
335
        return $this->start->value();
336
    }
337
338
    /**
339
     * @return \DateTime
340
     */
341
    public function end()
342
    {
343
        return $this->end->value();
344
    }
345
346
    /**
347
     * @return TimeIntervalPoint
348
     */
349
    public function startPoint()
350
    {
351
        return $this->start;
352
    }
353
354
    /**
355
     * @return TimeIntervalPoint
356
     */
357
    public function endPoint()
358
    {
359
        return $this->end;
360
    }
361
362
    /**
363
     * Returns a copy of this Interval with the start point altered.
364
     *
365
     * @param IntervalPointInterface|TimeIntervalPoint $start
366
     *
367
     * @return self
368
     */
369
    public function withStart(IntervalPointInterface $start)
370
    {
371
        return new self($start, $this->end, $this->type);
372
    }
373
374
    /**
375
     * Returns a copy of this Interval with the end point altered.
376
     *
377
     * @param IntervalPointInterface|TimeIntervalPoint $end
378
     *
379
     * @return self
380
     */
381
    public function withEnd(IntervalPointInterface $end)
382
    {
383
        return new self($this->start, $end, $this->type);
384
    }
385
386
    /**
387
     * Returns a copy of this Interval with the interval type altered.
388
     *
389
     * @param IntervalType $type
390
     *
391
     * @return self
392
     */
393
    public function withType(IntervalType $type)
394
    {
395
        return new self($this->start, $this->end, $type);
396
    }
397
398
    /**
399
     * @return string
400
     */
401
    public function __toString()
402
    {
403
        return $this->type->formatInterval($this);
404
    }
405
}
406

src/Week/WeekInterval.php 1 location

@@ 20-405 (lines=386) @@
17
use GpsLab\Component\Interval\IntervalPointInterface;
18
use GpsLab\Component\Interval\IntervalType;
19
20
class WeekInterval implements ComparableIntervalInterface
21
{
22
    /**
23
     * @var string
24
     */
25
    const REGEXP = '/^
26
        (?:\(|\[)                   # start type char
27
        \s*
28
        (?<start>\d{4}-\d{2}-\d{2}) # start point
29
        \s*,\s*                     # separator
30
        (?<end>\d{4}-\d{2}-\d{2})   # end point
31
        \s*
32
        (?:\)|\])                   # end type char
33
    $/x';
34
35
    /**
36
     * @var IntervalType
37
     */
38
    private $type;
39
40
    /**
41
     * @var IntervalComparator
42
     */
43
    private $comparator;
44
45
    /**
46
     * @var WeekIntervalPoint
47
     */
48
    private $start;
49
50
    /**
51
     * @var WeekIntervalPoint
52
     */
53
    private $end;
54
55
    /**
56
     * @param WeekIntervalPoint $start
57
     * @param WeekIntervalPoint $end
58
     * @param IntervalType $type
59
     */
60
    private function __construct(WeekIntervalPoint $start, WeekIntervalPoint $end, IntervalType $type)
61
    {
62
        if ($start->gte($end)) {
63
            throw IncorrectIntervalException::create();
64
        }
65
66
        $this->type = $type;
67
        $this->start = $start;
68
        $this->end = $end;
69
        $this->comparator = new IntervalComparator($this);
70
    }
71
72
    /**
73
     * @param \DateTime $start
74
     * @param \DateTime $end
75
     * @param IntervalType $type
76
     *
77
     * @return self
78
     */
79
    public static function create(\DateTime $start, \DateTime $end, IntervalType $type)
80
    {
81
        return new self(new WeekIntervalPoint($start), new WeekIntervalPoint($end), $type);
82
    }
83
84
    /**
85
     * @param \DateTime $start
86
     * @param \DateTime $end
87
     *
88
     * @return self
89
     */
90
    public static function closed(\DateTime $start, \DateTime $end)
91
    {
92
        return static::create($start, $end, IntervalType::closed());
93
    }
94
95
    /**
96
     * @param \DateTime $start
97
     * @param \DateTime $end
98
     *
99
     * @return self
100
     */
101
    public static function halfClosed(\DateTime $start, \DateTime $end)
102
    {
103
        return static::create($start, $end, IntervalType::halfClosed());
104
    }
105
106
    /**
107
     * @param \DateTime $start
108
     * @param \DateTime $end
109
     *
110
     * @return self
111
     */
112
    public static function halfOpen(\DateTime $start, \DateTime $end)
113
    {
114
        return static::create($start, $end, IntervalType::halfOpen());
115
    }
116
117
    /**
118
     * @param \DateTime $start
119
     * @param \DateTime $end
120
     *
121
     * @return self
122
     */
123
    public static function open(\DateTime $start, \DateTime $end)
124
    {
125
        return static::create($start, $end, IntervalType::open());
126
    }
127
128
    /**
129
     * Create interval from string.
130
     *
131
     * Example formats for all interval types:
132
     *   [2016-12-09, 2016-12-21]
133
     *   (2015-03-07, 2015-10-19]
134
     *   [2014-09-11, 2015-02-08)
135
     *   (2013-10-02, 2013-10-30)
136
     *
137
     * Spaces are ignored in format.
138
     *
139
     * @param string $string
140
     *
141
     * @return self
142
     */
143
    public static function fromString($string)
144
    {
145
        if (!preg_match(self::REGEXP, $string, $match)) {
146
            throw InvalidIntervalFormatException::create('[YYYY-MM-DD, YYYY-MM-DD]', $string);
147
        }
148
149
        return self::create(
150
            new \DateTime($match['start']),
151
            new \DateTime($match['end']),
152
            IntervalType::fromString($string)
153
        );
154
    }
155
156
    /**
157
     * Checks if this interval is equal to the specified interval.
158
     *
159
     * @param WeekInterval $interval
160
     *
161
     * @return bool
162
     */
163
    public function equal(self $interval)
164
    {
165
        return $this->comparator->equal($interval);
166
    }
167
168
    /**
169
     * Does this interval contain the specified point.
170
     *
171
     * @param \DateTime $point
172
     *
173
     * @return bool
174
     */
175
    public function contains(\DateTime $point)
176
    {
177
        return $this->comparator->contains(new WeekIntervalPoint($point));
178
    }
179
180
    /**
181
     * Does this interval intersect the specified interval.
182
     *
183
     * @param WeekInterval $interval
184
     *
185
     * @return bool
186
     */
187
    public function intersects(self $interval)
188
    {
189
        return $this->comparator->intersects($interval);
190
    }
191
192
    /**
193
     * Gets the intersection between this interval and another interval.
194
     *
195
     * @param WeekInterval $interval
196
     *
197
     * @return self|null
198
     */
199
    public function intersection(self $interval)
200
    {
201
        return $this->comparator->intersection($interval);
202
    }
203
204
    /**
205
     * Gets the covered interval between this Interval and another interval.
206
     *
207
     * @param WeekInterval $interval
208
     *
209
     * @return self
210
     */
211
    public function cover(self $interval)
212
    {
213
        return $this->comparator->cover($interval);
214
    }
215
216
    /**
217
     * Gets the gap between this interval and another interval.
218
     *
219
     * @param WeekInterval $interval
220
     *
221
     * @return self|null
222
     */
223
    public function gap(self $interval)
224
    {
225
        return $this->comparator->gap($interval);
226
    }
227
228
    /**
229
     * Does this interval abuts with the interval specified.
230
     *
231
     * @param WeekInterval $interval
232
     *
233
     * @return bool
234
     */
235
    public function abuts(self $interval)
236
    {
237
        return $this->comparator->abuts($interval);
238
    }
239
240
    /**
241
     * Joins the interval between the adjacent.
242
     *
243
     * @param WeekInterval $interval
244
     *
245
     * @return self|null
246
     */
247
    public function join(self $interval)
248
    {
249
        return $this->comparator->join($interval);
250
    }
251
252
    /**
253
     * Gets the union between this interval and another interval.
254
     *
255
     * @param WeekInterval $interval
256
     *
257
     * @return self|null
258
     */
259
    public function union(self $interval)
260
    {
261
        return $this->comparator->union($interval);
262
    }
263
264
    /**
265
     * The point is before the interval.
266
     *
267
     * @param \DateTime $point
268
     *
269
     * @return bool
270
     */
271
    public function before(\DateTime $point)
272
    {
273
        return $this->comparator->before(new WeekIntervalPoint($point));
274
    }
275
276
    /**
277
     * The point is after the interval.
278
     *
279
     * @param \DateTime $point
280
     *
281
     * @return bool
282
     */
283
    public function after(\DateTime $point)
284
    {
285
        return $this->comparator->after(new WeekIntervalPoint($point));
286
    }
287
288
    /**
289
     * @param \DateInterval|null $step
290
     *
291
     * @return \Generator
292
     */
293
    public function iterate(\DateInterval $step = null)
294
    {
295
        $step = $step ?: new \DateInterval('P1W');
296
297
        $date = $this->start();
298
        $end = $this->end();
299
300
        if ($this->type->startExcluded()) {
301
            $date->add($step);
302
        }
303
304
        while ($date < $end || (!$this->type->endExcluded() && $date == $end)) {
305
            yield $date;
306
            $date->add($step);
307
        }
308
    }
309
310
    /**
311
     * @param \DateInterval|null $step
312
     *
313
     * @return \DatePeriod
314
     */
315
    public function period(\DateInterval $step = null)
316
    {
317
        $step = $step ?: new \DateInterval('P1W');
318
319
        return new \DatePeriod($this->start(), $step, $this->end());
320
    }
321
322
    /**
323
     * @return IntervalType
324
     */
325
    public function type()
326
    {
327
        return $this->type;
328
    }
329
330
    /**
331
     * @return \DateTime
332
     */
333
    public function start()
334
    {
335
        return $this->start->value();
336
    }
337
338
    /**
339
     * @return \DateTime
340
     */
341
    public function end()
342
    {
343
        return $this->end->value();
344
    }
345
346
    /**
347
     * @return WeekIntervalPoint
348
     */
349
    public function startPoint()
350
    {
351
        return $this->start;
352
    }
353
354
    /**
355
     * @return WeekIntervalPoint
356
     */
357
    public function endPoint()
358
    {
359
        return $this->end;
360
    }
361
362
    /**
363
     * Returns a copy of this Interval with the start point altered.
364
     *
365
     * @param IntervalPointInterface|WeekIntervalPoint $start
366
     *
367
     * @return self
368
     */
369
    public function withStart(IntervalPointInterface $start)
370
    {
371
        return new self($start, $this->end, $this->type);
372
    }
373
374
    /**
375
     * Returns a copy of this Interval with the end point altered.
376
     *
377
     * @param IntervalPointInterface|WeekIntervalPoint $end
378
     *
379
     * @return self
380
     */
381
    public function withEnd(IntervalPointInterface $end)
382
    {
383
        return new self($this->start, $end, $this->type);
384
    }
385
386
    /**
387
     * Returns a copy of this Interval with the interval type altered.
388
     *
389
     * @param IntervalType $type
390
     *
391
     * @return self
392
     */
393
    public function withType(IntervalType $type)
394
    {
395
        return new self($this->start, $this->end, $type);
396
    }
397
398
    /**
399
     * @return string
400
     */
401
    public function __toString()
402
    {
403
        return $this->type->formatInterval($this);
404
    }
405
}
406