Code Duplication    Length = 239-239 lines in 5 locations

src/Date/DateInterval.php 1 location

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

src/DateTime/DateTimeInterval.php 1 location

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

src/Month/MonthInterval.php 1 location

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

src/Time/TimeInterval.php 1 location

@@ 17-255 (lines=239) @@
14
use GpsLab\Component\Interval\IntervalInterface;
15
use GpsLab\Component\Interval\IntervalType;
16
17
class TimeInterval implements IntervalInterface
18
{
19
    /**
20
     * @var string
21
     */
22
    const REGEXP = '/^
23
        (?:\(|\[)                   # start type char
24
        \s*
25
        (?<start>\d{2}:\d{2}:\d{2}) # start point
26
        \s*,\s*                     # separator
27
        (?<end>\d{2}:\d{2}:\d{2})   # end point
28
        \s*
29
        (?:\)|\])                   # end type char
30
    $/x';
31
32
    /**
33
     * @var IntervalType
34
     */
35
    private $type;
36
37
    /**
38
     * @var TimeIntervalComparator
39
     */
40
    private $comparator;
41
42
    /**
43
     * @var TimeIntervalPoint
44
     */
45
    private $start;
46
47
    /**
48
     * @var TimeIntervalPoint
49
     */
50
    private $end;
51
52
    /**
53
     * @param TimeIntervalPoint $start
54
     * @param TimeIntervalPoint $end
55
     * @param IntervalType $type
56
     */
57
    private function __construct(TimeIntervalPoint $start, TimeIntervalPoint $end, IntervalType $type)
58
    {
59
        if ($start->gte($end)) {
60
            throw IncorrectIntervalException::create();
61
        }
62
63
        $this->type = $type;
64
        $this->start = $start;
65
        $this->end = $end;
66
        $this->comparator = new TimeIntervalComparator($this);
67
    }
68
69
    /**
70
     * @param \DateTime $start
71
     * @param \DateTime $end
72
     * @param IntervalType $type
73
     *
74
     * @return self
75
     */
76
    public static function create(\DateTime $start, \DateTime $end, IntervalType $type)
77
    {
78
        return new self(new TimeIntervalPoint($start), new TimeIntervalPoint($end), $type);
79
    }
80
81
    /**
82
     * @param \DateTime $start
83
     * @param \DateTime $end
84
     *
85
     * @return self
86
     */
87
    public static function closed(\DateTime $start, \DateTime $end)
88
    {
89
        return static::create($start, $end, IntervalType::closed());
90
    }
91
92
    /**
93
     * @param \DateTime $start
94
     * @param \DateTime $end
95
     *
96
     * @return self
97
     */
98
    public static function halfClosed(\DateTime $start, \DateTime $end)
99
    {
100
        return static::create($start, $end, IntervalType::halfClosed());
101
    }
102
103
    /**
104
     * @param \DateTime $start
105
     * @param \DateTime $end
106
     *
107
     * @return self
108
     */
109
    public static function halfOpen(\DateTime $start, \DateTime $end)
110
    {
111
        return static::create($start, $end, IntervalType::halfOpen());
112
    }
113
114
    /**
115
     * @param \DateTime $start
116
     * @param \DateTime $end
117
     *
118
     * @return self
119
     */
120
    public static function open(\DateTime $start, \DateTime $end)
121
    {
122
        return static::create($start, $end, IntervalType::open());
123
    }
124
125
    /**
126
     * Create interval from string.
127
     *
128
     * Example formats for all interval types:
129
     *   [02:55:00, 12:30:12]
130
     *   (12:04:45, 19:38:14]
131
     *   [17:31:09, 23:45:58)
132
     *   (15:03:37, 15:06:34)
133
     *
134
     * Spaces are ignored in format.
135
     *
136
     * @param string $string
137
     *
138
     * @return self
139
     */
140
    public static function fromString($string)
141
    {
142
        if (!preg_match(self::REGEXP, $string, $match)) {
143
            throw InvalidIntervalFormatException::create('[HH:II:SS, HH:II:SS]', $string);
144
        }
145
146
        return self::create(
147
            new \DateTime($match['start']),
148
            new \DateTime($match['end']),
149
            IntervalType::fromString($string)
150
        );
151
    }
152
153
    /**
154
     * @param \DateTime $point
155
     *
156
     * @return bool
157
     */
158
    public function contains(\DateTime $point)
159
    {
160
        return $this->comparator->contains(new TimeIntervalPoint($point));
161
    }
162
163
    /**
164
     * @param TimeInterval $interval
165
     * @param bool $check_interval_type
166
     *
167
     * @return bool
168
     */
169
    public function intersect(TimeInterval $interval, $check_interval_type = true)
170
    {
171
        return $this->comparator->intersect($interval, $check_interval_type);
172
    }
173
174
    /**
175
     * @param TimeInterval $interval
176
     *
177
     * @return TimeInterval|null
178
     */
179
    public function intersectInterval(TimeInterval $interval)
180
    {
181
        return $this->comparator->intersectInterval($interval);
182
    }
183
184
    /**
185
     * The point is before the interval
186
     *
187
     * @param \DateTime $point
188
     *
189
     * @return bool
190
     */
191
    public function before(\DateTime $point)
192
    {
193
        return $this->comparator->before(new TimeIntervalPoint($point));
194
    }
195
196
    /**
197
     * The point is after the interval
198
     *
199
     * @param \DateTime $point
200
     *
201
     * @return bool
202
     */
203
    public function after(\DateTime $point)
204
    {
205
        return $this->comparator->after(new TimeIntervalPoint($point));
206
    }
207
208
    /**
209
     * @return IntervalType
210
     */
211
    public function type()
212
    {
213
        return $this->type;
214
    }
215
216
    /**
217
     * @return \DateTime
218
     */
219
    public function start()
220
    {
221
        return $this->start->value();
222
    }
223
224
    /**
225
     * @return \DateTime
226
     */
227
    public function end()
228
    {
229
        return $this->end->value();
230
    }
231
232
    /**
233
     * @return TimeIntervalPoint
234
     */
235
    public function startPoint()
236
    {
237
        return $this->start;
238
    }
239
240
    /**
241
     * @return TimeIntervalPoint
242
     */
243
    public function endPoint()
244
    {
245
        return $this->end;
246
    }
247
248
    /**
249
     * @return string
250
     */
251
    public function __toString()
252
    {
253
        return $this->type->getReadable($this);
254
    }
255
}
256

src/Week/WeekInterval.php 1 location

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