1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* League.Period (http://period.thephpleague.com) |
4
|
|
|
* |
5
|
|
|
* @package League.period |
6
|
|
|
* @author Ignace Nyamagana Butera <[email protected]> |
7
|
|
|
* @copyright 2014-2015 Ignace Nyamagana Butera |
8
|
|
|
* @license https://github.com/thephpleague/period/blob/master/LICENSE (MIT License) |
9
|
|
|
* @version 4.0.0 |
10
|
|
|
* @link https://github.com/thephpleague/period/ |
11
|
|
|
*/ |
12
|
|
|
declare(strict_types=1); |
13
|
|
|
|
14
|
|
|
namespace League\Period; |
15
|
|
|
|
16
|
|
|
use DateInterval; |
17
|
|
|
use DatePeriod; |
18
|
|
|
use DateTime; |
19
|
|
|
use DateTimeImmutable; |
20
|
|
|
use DateTimeInterface; |
21
|
|
|
use DateTimeZone; |
22
|
|
|
use Generator; |
23
|
|
|
use JsonSerializable; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* A immutable value object class to manipulate Time Range. |
27
|
|
|
* |
28
|
|
|
* @package League.period |
29
|
|
|
* @author Ignace Nyamagana Butera <[email protected]> |
30
|
|
|
* @since 1.0.0 |
31
|
|
|
*/ |
32
|
|
|
final class Period implements JsonSerializable |
33
|
|
|
{ |
34
|
|
|
/** |
35
|
|
|
* Period starting included date point. |
36
|
|
|
* |
37
|
|
|
* @var DateTimeImmutable |
38
|
|
|
*/ |
39
|
|
|
protected $startDate; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Period ending excluded date point. |
43
|
|
|
* |
44
|
|
|
* @var DateTimeImmutable |
45
|
|
|
*/ |
46
|
|
|
protected $endDate; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @inheritdoc |
50
|
|
|
*/ |
51
|
3 |
|
public static function __set_state(array $period): self |
52
|
|
|
{ |
53
|
3 |
|
return new self($period['startDate'], $period['endDate']); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Create a new instance. |
58
|
|
|
* |
59
|
|
|
* @param DateTimeInterface|string $startDate starting included date point |
60
|
|
|
* @param DateTimeInterface|string $endDate ending excluded date point |
61
|
|
|
* |
62
|
|
|
* @throws Exception If $startDate is greater than $endDate |
63
|
|
|
*/ |
64
|
255 |
|
public function __construct($startDate, $endDate) |
65
|
|
|
{ |
66
|
255 |
|
$startDate = static::filterDatePoint($startDate); |
67
|
255 |
|
$endDate = static::filterDatePoint($endDate); |
68
|
255 |
|
if ($startDate > $endDate) { |
69
|
39 |
|
throw new Exception('The ending datepoint must be greater or equal to the starting datepoint'); |
70
|
|
|
} |
71
|
246 |
|
$this->startDate = $startDate; |
72
|
246 |
|
$this->endDate = $endDate; |
73
|
246 |
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Validate the DateTimeInterface. |
77
|
|
|
* |
78
|
|
|
* @param DateTimeInterface|string $datepoint |
79
|
|
|
* |
80
|
|
|
* @return DateTimeImmutable |
81
|
|
|
*/ |
82
|
282 |
|
protected static function filterDatePoint($datepoint): DateTimeImmutable |
83
|
|
|
{ |
84
|
282 |
|
if ($datepoint instanceof DateTimeImmutable) { |
85
|
246 |
|
return $datepoint; |
86
|
|
|
} |
87
|
|
|
|
88
|
222 |
|
if ($datepoint instanceof DateTime) { |
89
|
78 |
|
return DateTimeImmutable::createFromMutable($datepoint); |
90
|
|
|
} |
91
|
|
|
|
92
|
153 |
|
return date_create_immutable($datepoint); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Create a Period object from a starting point and an interval. |
97
|
|
|
* |
98
|
|
|
* The interval can be |
99
|
|
|
* <ul> |
100
|
|
|
* <li>a DateInterval object</li> |
101
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
102
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
103
|
|
|
* </ul> |
104
|
|
|
* |
105
|
|
|
* @param DateTimeInterface|string $startDate The start date point |
106
|
|
|
* @param mixed $interval The interval |
107
|
|
|
* |
108
|
|
|
* @return self |
109
|
|
|
*/ |
110
|
138 |
|
public static function createFromDuration($startDate, $interval): self |
111
|
|
|
{ |
112
|
138 |
|
$startDate = static::filterDatePoint($startDate); |
113
|
|
|
|
114
|
138 |
|
return new self($startDate, $startDate->add(static::filterDateInterval($interval))); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Validate a DateInterval. |
119
|
|
|
* |
120
|
|
|
* The interval can be |
121
|
|
|
* <ul> |
122
|
|
|
* <li>a DateInterval object</li> |
123
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
124
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
125
|
|
|
* </ul> |
126
|
|
|
* |
127
|
|
|
* @param mixed $interval The interval |
128
|
|
|
* |
129
|
|
|
* @return DateInterval |
130
|
|
|
*/ |
131
|
177 |
|
protected static function filterDateInterval($interval): DateInterval |
132
|
|
|
{ |
133
|
177 |
|
if ($interval instanceof DateInterval) { |
134
|
27 |
|
return $interval; |
135
|
|
|
} |
136
|
|
|
|
137
|
165 |
|
if (false !== ($res = filter_var($interval, FILTER_VALIDATE_INT))) { |
138
|
30 |
|
return new DateInterval('PT'.$res.'S'); |
139
|
|
|
} |
140
|
|
|
|
141
|
153 |
|
return DateInterval::createFromDateString($interval); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Create a Period object from a ending excluded datepoint and an interval. |
146
|
|
|
* |
147
|
|
|
* The interval can be |
148
|
|
|
* <ul> |
149
|
|
|
* <li>a DateInterval object</li> |
150
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
151
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
152
|
|
|
* </ul> |
153
|
|
|
* |
154
|
|
|
* @param DateTimeInterface|string $endDate The start date point |
155
|
|
|
* @param mixed $interval The interval |
156
|
|
|
* |
157
|
|
|
* @return self |
158
|
|
|
*/ |
159
|
24 |
|
public static function createFromDurationBeforeEnd($endDate, $interval): self |
160
|
|
|
{ |
161
|
24 |
|
$endDate = static::filterDatePoint($endDate); |
162
|
|
|
|
163
|
24 |
|
return new self($endDate->sub(static::filterDateInterval($interval)), $endDate); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Create a Period object from a DatePeriod |
168
|
|
|
* |
169
|
|
|
* @param DatePeriod $datePeriod |
170
|
|
|
* |
171
|
|
|
* @throws Exception If the submitted DatePeriod lacks an End DateTimeInterface |
172
|
|
|
* |
173
|
|
|
* @return self |
174
|
|
|
*/ |
175
|
6 |
|
public static function createFromDatePeriod(DatePeriod $datePeriod): self |
176
|
|
|
{ |
177
|
6 |
|
if (null !== ($endDate = $datePeriod->getEndDate())) { |
178
|
3 |
|
return new self($datePeriod->getStartDate(), $endDate); |
179
|
|
|
} |
180
|
|
|
|
181
|
3 |
|
throw new Exception('The submitted DatePeriod object does not contain an end date'); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Create a Period object for a specific Year |
186
|
|
|
* |
187
|
|
|
* @param DateTimeInterface|string|int $year |
188
|
|
|
* |
189
|
|
|
* @return self |
190
|
|
|
*/ |
191
|
18 |
|
public static function createFromYear($year): self |
192
|
|
|
{ |
193
|
18 |
|
if (is_int($year)) { |
194
|
15 |
|
$startDate = date_create_immutable($year.'-01-01'); |
195
|
|
|
|
196
|
15 |
|
return new self($startDate, $startDate->add(new DateInterval('P1Y'))); |
197
|
|
|
} |
198
|
|
|
|
199
|
6 |
|
$startDate = self::approximateDate('Y-01-01 00:00:00', static::filterDatePoint($year)); |
200
|
|
|
|
201
|
6 |
|
return new self($startDate, $startDate->add(new DateInterval('P1Y'))); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Returns a DateTimeInterface object whose value are |
206
|
|
|
* approximated to the second |
207
|
|
|
* |
208
|
|
|
* @param string $format |
209
|
|
|
* @param DateTimeInterface $datepoint |
210
|
|
|
* |
211
|
|
|
* @return DateTimeInterface |
212
|
|
|
*/ |
213
|
21 |
|
protected static function approximateDate(string $format, DateTimeInterface $datepoint): DateTimeInterface |
214
|
|
|
{ |
215
|
21 |
|
return $datepoint->createFromFormat('Y-m-d H:i:s', $datepoint->format($format), $datepoint->getTimeZone()); |
|
|
|
|
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Create a Period object for a specific semester in a given year |
220
|
|
|
* |
221
|
|
|
* @param DateTimeInterface|string|int $year |
222
|
|
|
* @param int $semester Semester Index from 1 to 2 |
223
|
|
|
* |
224
|
|
|
* @return self |
225
|
|
|
*/ |
226
|
12 |
|
public static function createFromSemester($year, int $semester = null): self |
227
|
|
|
{ |
228
|
12 |
|
if (1 == func_num_args()) { |
229
|
3 |
|
$date = self::filterDatePoint($year); |
230
|
3 |
|
$month = (intdiv((int) $date->format('m'), 6) * 6) + 1; |
231
|
3 |
|
$startDate = self::approximateDate('Y-m-01 00:00:00', $date->setDate((int) $date->format('Y'), $month, 1)); |
232
|
|
|
|
233
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('P6M'))); |
234
|
|
|
} |
235
|
|
|
|
236
|
12 |
|
$month = ((static::validateRange($semester, 1, 2) - 1) * 6) + 1; |
237
|
6 |
|
$startDate = date_create_immutable($year.'-'.sprintf("%'.02d", $month).'-01'); |
238
|
|
|
|
239
|
6 |
|
return new self($startDate, $startDate->add(new DateInterval('P6M'))); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Validate a int according to a range. |
244
|
|
|
* |
245
|
|
|
* @param int $value the value to validate |
246
|
|
|
* @param int $min the minimum value |
247
|
|
|
* @param int $max the maximal value |
248
|
|
|
* |
249
|
|
|
* @throws Exception If the value is not in the range |
250
|
|
|
* |
251
|
|
|
* @return int |
252
|
|
|
*/ |
253
|
75 |
|
protected static function validateRange(int $value, int $min, int $max): int |
254
|
|
|
{ |
255
|
75 |
|
$res = filter_var($value, FILTER_VALIDATE_INT, ['options' => ['min_range' => $min, 'max_range' => $max]]); |
256
|
75 |
|
if (false !== $res) { |
257
|
51 |
|
return $res; |
258
|
|
|
} |
259
|
|
|
|
260
|
24 |
|
throw new Exception('the submitted value is not contained within the valid range'); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* Create a Period object for a specific quarter in a given year |
265
|
|
|
* |
266
|
|
|
* @param DateTimeInterface|string|int $year |
267
|
|
|
* @param int $quarter Quarter Index from 1 to 4 |
268
|
|
|
* |
269
|
|
|
* @return self |
270
|
|
|
*/ |
271
|
12 |
|
public static function createFromQuarter($year, int $quarter = null): self |
272
|
|
|
{ |
273
|
12 |
|
if (1 == func_num_args()) { |
274
|
3 |
|
$date = self::filterDatePoint($year); |
275
|
3 |
|
$month = (intdiv((int) $date->format('m'), 3) * 3) + 1; |
276
|
3 |
|
$startDate = self::approximateDate('Y-m-01 00:00:00', $date->setDate((int) $date->format('Y'), $month, 1)); |
277
|
|
|
|
278
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('P3M'))); |
279
|
|
|
} |
280
|
|
|
|
281
|
12 |
|
$month = ((static::validateRange($quarter, 1, 4) - 1) * 3) + 1; |
282
|
6 |
|
$startDate = date_create_immutable($year.'-'.sprintf("%'.02d", $month).'-01'); |
283
|
|
|
|
284
|
6 |
|
return new self($startDate, $startDate->add(new DateInterval('P3M'))); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Create a Period object for a specific year and month |
289
|
|
|
* |
290
|
|
|
* @param DateTimeInterface|string|int $year |
291
|
|
|
* @param int $month Month index from 1 to 12 |
292
|
|
|
* |
293
|
|
|
* @return self |
294
|
|
|
*/ |
295
|
39 |
|
public static function createFromMonth($year, int $month = null): self |
296
|
|
|
{ |
297
|
39 |
|
if (1 == func_num_args()) { |
298
|
6 |
|
$startDate = self::approximateDate('Y-m-01 00:00:00', static::filterDatePoint($year)); |
299
|
|
|
|
300
|
6 |
|
return new self($startDate, $startDate->add(new DateInterval('P1M'))); |
301
|
|
|
} |
302
|
|
|
|
303
|
36 |
|
$startDate = date_create_immutable($year.'-'.sprintf("%'.02d", self::validateRange($month, 1, 12)).'-01'); |
304
|
|
|
|
305
|
30 |
|
return new self($startDate, $startDate->add(new DateInterval('P1M'))); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* Create a Period object for a specific week |
310
|
|
|
* |
311
|
|
|
* @param DateTimeInterface|string|int $year |
312
|
|
|
* @param int $week index from 1 to 53 |
313
|
|
|
* |
314
|
|
|
* @return self |
315
|
|
|
*/ |
316
|
24 |
|
public static function createFromWeek($year, int $week = null): self |
317
|
|
|
{ |
318
|
24 |
|
if (1 == func_num_args()) { |
319
|
3 |
|
$date = static::filterDatePoint($year); |
320
|
3 |
|
$startDate = self::approximateDate( |
321
|
3 |
|
'Y-m-d 00:00:00', |
322
|
3 |
|
$date->sub(new DateInterval('P'.($date->format('N') - 1).'D')) |
323
|
|
|
); |
324
|
|
|
|
325
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('P1W'))); |
326
|
|
|
} |
327
|
|
|
|
328
|
24 |
|
$startDate = date_create_immutable() |
329
|
24 |
|
->setISODate($year, self::validateRange($week, 1, 53)) |
330
|
18 |
|
->setTime(0, 0, 0) |
331
|
|
|
; |
332
|
|
|
|
333
|
18 |
|
return new self($startDate, $startDate->add(new DateInterval('P1W'))); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Create a Period object for a specific date |
338
|
|
|
* |
339
|
|
|
* The date is truncated so that the time range starts at midnight |
340
|
|
|
* according to the date timezone and last a full day. |
341
|
|
|
* |
342
|
|
|
* @param DateTimeInterface|string $datepoint |
343
|
|
|
* |
344
|
|
|
* @return self |
345
|
|
|
*/ |
346
|
3 |
|
public static function createFromDay($datepoint): self |
347
|
|
|
{ |
348
|
3 |
|
$startDate = self::approximateDate('Y-m-d 00:00:00', static::filterDatePoint($datepoint)); |
349
|
|
|
|
350
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('P1D'))); |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* Create a Period object for a specific date and hour. |
355
|
|
|
* |
356
|
|
|
* The starting datepoint represents the beginning of the hour |
357
|
|
|
* The Period interval is equal to 1 hour |
358
|
|
|
* |
359
|
|
|
* @param DateTimeInterface|string $datepoint |
360
|
|
|
* |
361
|
|
|
* @return self |
362
|
|
|
*/ |
363
|
3 |
|
public static function createFromHour($datepoint): self |
364
|
|
|
{ |
365
|
3 |
|
$startDate = self::approximateDate('Y-m-d H:00:00', static::filterDatePoint($datepoint)); |
366
|
|
|
|
367
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('PT1H'))); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Create a Period object for a specific date, hour and minute. |
372
|
|
|
* |
373
|
|
|
* The starting datepoint represents the beginning of the minute |
374
|
|
|
* The Period interval is equal to 1 minute |
375
|
|
|
* |
376
|
|
|
* @param DateTimeInterface|string $datepoint |
377
|
|
|
* |
378
|
|
|
* @return self |
379
|
|
|
*/ |
380
|
3 |
|
public static function createFromMinute($datepoint): self |
381
|
|
|
{ |
382
|
3 |
|
$startDate = self::approximateDate('Y-m-d H:i:00', static::filterDatePoint($datepoint)); |
383
|
|
|
|
384
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('PT1M'))); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Create a Period object for a specific date, hour, minute and second. |
389
|
|
|
* |
390
|
|
|
* The starting datepoint represents the beginning of the second |
391
|
|
|
* The Period interval is equal to 1 second |
392
|
|
|
* |
393
|
|
|
* @param DateTimeInterface|string $datepoint |
394
|
|
|
* |
395
|
|
|
* @return self |
396
|
|
|
*/ |
397
|
3 |
|
public static function createFromSecond($datepoint): self |
398
|
|
|
{ |
399
|
3 |
|
$startDate = self::approximateDate('Y-m-d H:i:s', static::filterDatePoint($datepoint)); |
400
|
|
|
|
401
|
3 |
|
return new self($startDate, $startDate->add(new DateInterval('PT1S'))); |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Returns the Period starting datepoint. |
406
|
|
|
* |
407
|
|
|
* The starting datepoint is included in the specified period. |
408
|
|
|
* The starting datepoint is always less than or equal to the ending datepoint. |
409
|
|
|
* |
410
|
|
|
* @return DateTimeImmutable |
411
|
|
|
*/ |
412
|
177 |
|
public function getStartDate(): DateTimeImmutable |
413
|
|
|
{ |
414
|
177 |
|
return $this->startDate; |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* Returns the Period ending datepoint. |
419
|
|
|
* |
420
|
|
|
* The ending datepoint is excluded from the specified period. |
421
|
|
|
* The ending datepoint is always greater than or equal to the starting datepoint. |
422
|
|
|
* |
423
|
|
|
* @return DateTimeImmutable |
424
|
|
|
*/ |
425
|
162 |
|
public function getEndDate(): DateTimeImmutable |
426
|
|
|
{ |
427
|
162 |
|
return $this->endDate; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Returns the Period duration as expressed in seconds |
432
|
|
|
* |
433
|
|
|
* @return float |
434
|
|
|
*/ |
435
|
18 |
|
public function getTimestampInterval(): float |
436
|
|
|
{ |
437
|
18 |
|
return $this->endDate->getTimestamp() - $this->startDate->getTimestamp(); |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* Returns the Period duration as a DateInterval object. |
442
|
|
|
* |
443
|
|
|
* @return DateInterval |
444
|
|
|
*/ |
445
|
33 |
|
public function getDateInterval(): DateInterval |
446
|
|
|
{ |
447
|
33 |
|
return $this->startDate->diff($this->endDate); |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Allows iteration over a set of dates and times, |
452
|
|
|
* recurring at regular intervals, over the Period object. |
453
|
|
|
* |
454
|
|
|
* The interval can be |
455
|
|
|
* <ul> |
456
|
|
|
* <li>a DateInterval object</li> |
457
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
458
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
459
|
|
|
* </ul> |
460
|
|
|
* |
461
|
|
|
* @param DateInterval|int|string $interval The interval |
462
|
|
|
* |
463
|
|
|
* @param int $option can be set to DatePeriod::EXCLUDE_START_DATE |
464
|
|
|
* to exclude the start date from the set of |
465
|
|
|
* recurring dates within the period. |
466
|
|
|
* |
467
|
|
|
* @return DatePeriod |
468
|
|
|
*/ |
469
|
24 |
|
public function getDatePeriod($interval, int $option = 0): DatePeriod |
470
|
|
|
{ |
471
|
24 |
|
return new DatePeriod($this->startDate, static::filterDateInterval($interval), $this->endDate, $option); |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
/** |
475
|
|
|
* Allows splitting a Period in smaller Period object according |
476
|
|
|
* to a given interval. |
477
|
|
|
* |
478
|
|
|
* The returned iterable Period set is ordered so that: |
479
|
|
|
* <ul> |
480
|
|
|
* <li>The first returned Period MUST share the starting datepoint of the parent object.</li> |
481
|
|
|
* <li>The last returned Period MUST share the ending datepoint of the parent object.</li> |
482
|
|
|
* <li>The last returned Period MUST have a duration equal or lesser than the submitted interval.</li> |
483
|
|
|
* <li>All returned Period except for the first one MUST start immediately after the previously returned Period</li> |
484
|
|
|
* </ul> |
485
|
|
|
* |
486
|
|
|
* The interval can be |
487
|
|
|
* <ul> |
488
|
|
|
* <li>a DateInterval object</li> |
489
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
490
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
491
|
|
|
* </ul> |
492
|
|
|
* |
493
|
|
|
* @param DateInterval|int|string $interval The interval |
494
|
|
|
* |
495
|
|
|
* @return Generator |
496
|
|
|
*/ |
497
|
12 |
|
public function split($interval): Generator |
498
|
|
|
{ |
499
|
12 |
|
$startDate = $this->startDate; |
500
|
12 |
|
$interval = static::filterDateInterval($interval); |
501
|
|
|
do { |
502
|
12 |
|
$endDate = $startDate->add($interval); |
503
|
12 |
|
if ($endDate > $this->endDate) { |
504
|
6 |
|
$endDate = $this->endDate; |
505
|
|
|
} |
506
|
12 |
|
yield new self($startDate, $endDate); |
507
|
|
|
|
508
|
9 |
|
$startDate = $endDate; |
509
|
9 |
|
} while ($startDate < $this->endDate); |
510
|
9 |
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* Allows splitting a Period in smaller Period object according |
514
|
|
|
* to a given interval. |
515
|
|
|
* |
516
|
|
|
* The returned iterable Period set is ordered so that: |
517
|
|
|
* <ul> |
518
|
|
|
* <li>The first returned Period MUST share the ending datepoint of the parent object.</li> |
519
|
|
|
* <li>The last returned Period MUST share the starting datepoint of the parent object.</li> |
520
|
|
|
* <li>The last returned Period MUST have a duration equal or lesser than the submitted interval.</li> |
521
|
|
|
* <li>All returned Period except for the first one MUST end immediately before the previously returned Period</li> |
522
|
|
|
* </ul> |
523
|
|
|
* |
524
|
|
|
* The interval can be |
525
|
|
|
* <ul> |
526
|
|
|
* <li>a DateInterval object</li> |
527
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
528
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
529
|
|
|
* </ul> |
530
|
|
|
* |
531
|
|
|
* @param DateInterval|int|string $interval The interval |
532
|
|
|
* |
533
|
|
|
* @return Generator |
534
|
|
|
*/ |
535
|
6 |
|
public function splitBackwards($interval): Generator |
536
|
|
|
{ |
537
|
6 |
|
$endDate = $this->endDate; |
538
|
6 |
|
$interval = static::filterDateInterval($interval); |
539
|
|
|
do { |
540
|
6 |
|
$startDate = $endDate->sub($interval); |
541
|
6 |
|
if ($startDate < $this->startDate) { |
542
|
3 |
|
$startDate = $this->startDate; |
543
|
|
|
} |
544
|
6 |
|
yield new self($startDate, $endDate); |
545
|
|
|
|
546
|
6 |
|
$endDate = $startDate; |
547
|
6 |
|
} while ($endDate > $this->startDate); |
548
|
6 |
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* Returns the string representation of a Period object |
552
|
|
|
* as a string in the ISO8601 interval format |
553
|
|
|
* |
554
|
|
|
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals |
555
|
|
|
* |
556
|
|
|
* @return string |
557
|
|
|
*/ |
558
|
3 |
|
public function __toString() |
559
|
|
|
{ |
560
|
3 |
|
$period = $this->jsonSerialize(); |
561
|
|
|
|
562
|
3 |
|
return $period['startDate'].'/'.$period['endDate']; |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
/** |
566
|
|
|
* Returns the Json representation of a Period object using |
567
|
|
|
* the JSON representation of dates as returned by Javascript Date.toJSON() method |
568
|
|
|
* |
569
|
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON |
570
|
|
|
* |
571
|
|
|
* @return string[] |
572
|
|
|
*/ |
573
|
6 |
|
public function jsonSerialize() |
574
|
|
|
{ |
575
|
6 |
|
static $iso8601_format = 'Y-m-d\TH:i:s.u\Z'; |
576
|
6 |
|
static $utc; |
577
|
6 |
|
$utc = $utc ?? new DateTimeZone('UTC'); |
578
|
|
|
|
579
|
|
|
return [ |
580
|
6 |
|
'startDate' => $this->startDate->setTimeZone($utc)->format($iso8601_format), |
581
|
6 |
|
'endDate' => $this->endDate->setTimeZone($utc)->format($iso8601_format), |
582
|
|
|
]; |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
/** |
586
|
|
|
* Compares two Period objects according to their duration. |
587
|
|
|
* |
588
|
|
|
* Returns: |
589
|
|
|
* <ul> |
590
|
|
|
* <li> -1 if the current Period duration is lesser than the submitted Period duration |
591
|
|
|
* <li> 1 if the current Period duration is greater than the submitted Period duration |
592
|
|
|
* <li> 0 if both Period have the same duration |
593
|
|
|
* </ul> |
594
|
|
|
* |
595
|
|
|
* @param Period $period |
596
|
|
|
* |
597
|
|
|
* @return int |
598
|
|
|
*/ |
599
|
21 |
|
public function compareDuration(Period $period): int |
600
|
|
|
{ |
601
|
21 |
|
return $this->endDate <=> $this->startDate->add($period->getDateInterval()); |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
/** |
605
|
|
|
* Tells whether the current Period object duration |
606
|
|
|
* is greater than the submitted one. |
607
|
|
|
* |
608
|
|
|
* @param Period $period |
609
|
|
|
* |
610
|
|
|
* @return bool |
611
|
|
|
*/ |
612
|
9 |
|
public function durationGreaterThan(Period $period): bool |
613
|
|
|
{ |
614
|
9 |
|
return 1 == $this->compareDuration($period); |
615
|
|
|
} |
616
|
|
|
|
617
|
|
|
/** |
618
|
|
|
* Tells whether the current Period object duration |
619
|
|
|
* is less than the submitted one. |
620
|
|
|
* |
621
|
|
|
* @param Period $period |
622
|
|
|
* |
623
|
|
|
* @return bool |
624
|
|
|
*/ |
625
|
9 |
|
public function durationLessThan(Period $period): bool |
626
|
|
|
{ |
627
|
9 |
|
return -1 == $this->compareDuration($period); |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
/** |
631
|
|
|
* Tells whether the current Period object duration |
632
|
|
|
* is equal to the submitted one |
633
|
|
|
* |
634
|
|
|
* @param Period $period |
635
|
|
|
* |
636
|
|
|
* @return bool |
637
|
|
|
*/ |
638
|
3 |
|
public function sameDurationAs(Period $period): bool |
639
|
|
|
{ |
640
|
3 |
|
return 0 == $this->compareDuration($period); |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
/** |
644
|
|
|
* Tells whether two Period share the same datepoints. |
645
|
|
|
* |
646
|
|
|
* @param Period $period |
647
|
|
|
* |
648
|
|
|
* @return bool |
649
|
|
|
*/ |
650
|
18 |
|
public function sameValueAs(Period $period): bool |
651
|
|
|
{ |
652
|
18 |
|
return $this->startDate == $period->getStartDate() |
653
|
18 |
|
&& $this->endDate == $period->getEndDate(); |
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
/** |
657
|
|
|
* Tells whether two Period object abuts |
658
|
|
|
* |
659
|
|
|
* @param Period $period |
660
|
|
|
* |
661
|
|
|
* @return bool |
662
|
|
|
*/ |
663
|
42 |
|
public function abuts(Period $period): bool |
664
|
|
|
{ |
665
|
42 |
|
return $this->startDate == $period->getEndDate() |
666
|
42 |
|
|| $this->endDate == $period->getStartDate(); |
667
|
|
|
} |
668
|
|
|
|
669
|
|
|
/** |
670
|
|
|
* Tells whether two Period objects overlaps |
671
|
|
|
* |
672
|
|
|
* @param Period $period |
673
|
|
|
* |
674
|
|
|
* @return bool |
675
|
|
|
*/ |
676
|
36 |
|
public function overlaps(Period $period): bool |
677
|
|
|
{ |
678
|
36 |
|
return !$this->abuts($period) |
679
|
36 |
|
&& $this->startDate < $period->getEndDate() |
680
|
36 |
|
&& $this->endDate > $period->getStartDate(); |
681
|
|
|
} |
682
|
|
|
|
683
|
|
|
/** |
684
|
|
|
* Tells whether a Period is entirely after the specified index |
685
|
|
|
* |
686
|
|
|
* The specified index can be |
687
|
|
|
* <ul> |
688
|
|
|
* <li>a Period</li> |
689
|
|
|
* <li>a DateTimeInterface</li> |
690
|
|
|
* <li>a string in a format supported by DateTimeImmutable::__construct</li> |
691
|
|
|
* </ul> |
692
|
|
|
* |
693
|
|
|
* @param Period|DateTimeInterface|string $index |
694
|
|
|
* |
695
|
|
|
* @return bool |
696
|
|
|
*/ |
697
|
9 |
|
public function isAfter($index): bool |
698
|
|
|
{ |
699
|
9 |
|
if ($index instanceof Period) { |
700
|
3 |
|
return $this->startDate >= $index->getEndDate(); |
701
|
|
|
} |
702
|
|
|
|
703
|
6 |
|
return $this->startDate > static::filterDatePoint($index); |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
/** |
707
|
|
|
* Tells whether a Period is entirely before the specified index |
708
|
|
|
* |
709
|
|
|
* The specified index can be |
710
|
|
|
* <ul> |
711
|
|
|
* <li>a Period</li> |
712
|
|
|
* <li>a DateTimeInterface</li> |
713
|
|
|
* <li>a string in a format supported by DateTimeImmutable::__construct</li> |
714
|
|
|
* </ul> |
715
|
|
|
* |
716
|
|
|
* @param Period|DateTimeInterface|string $index |
717
|
|
|
* |
718
|
|
|
* @return bool |
719
|
|
|
*/ |
720
|
12 |
|
public function isBefore($index): bool |
721
|
|
|
{ |
722
|
12 |
|
if ($index instanceof Period) { |
723
|
6 |
|
return $this->endDate <= $index->getStartDate(); |
724
|
|
|
} |
725
|
|
|
|
726
|
6 |
|
return $this->endDate <= static::filterDatePoint($index); |
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
/** |
730
|
|
|
* Tells whether the specified index is fully contained within |
731
|
|
|
* the current Period object. |
732
|
|
|
* |
733
|
|
|
* The specified index can be |
734
|
|
|
* <ul> |
735
|
|
|
* <li>a Period</li> |
736
|
|
|
* <li>a DateTimeInterface</li> |
737
|
|
|
* <li>a string in a format supported by DateTimeImmutable::__construct</li> |
738
|
|
|
* </ul> |
739
|
|
|
* |
740
|
|
|
* @param Period|DateTimeInterface|string $index |
741
|
|
|
* |
742
|
|
|
* @return bool |
743
|
|
|
*/ |
744
|
24 |
|
public function contains($index): bool |
745
|
|
|
{ |
746
|
24 |
|
if ($index instanceof Period) { |
747
|
9 |
|
return $this->containsPeriod($index); |
748
|
|
|
} |
749
|
|
|
|
750
|
24 |
|
return $this->containsDatePoint($index); |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
/** |
754
|
|
|
* Tells whether a Period object is fully contained within |
755
|
|
|
* the current Period object. |
756
|
|
|
* |
757
|
|
|
* @param Period $period |
758
|
|
|
* |
759
|
|
|
* @return bool |
760
|
|
|
*/ |
761
|
9 |
|
protected function containsPeriod(Period $period): bool |
762
|
|
|
{ |
763
|
9 |
|
return $this->contains($period->getStartDate()) |
764
|
9 |
|
&& ($period->getEndDate() >= $this->startDate && $period->getEndDate() <= $this->endDate); |
765
|
|
|
} |
766
|
|
|
|
767
|
|
|
/** |
768
|
|
|
* Tells whether a datepoint is fully contained within |
769
|
|
|
* the current Period object. |
770
|
|
|
* |
771
|
|
|
* @param DateTimeInterface|string $datepoint |
772
|
|
|
* |
773
|
|
|
* @return bool |
774
|
|
|
*/ |
775
|
24 |
|
protected function containsDatePoint($datepoint): bool |
776
|
|
|
{ |
777
|
24 |
|
$datetime = static::filterDatePoint($datepoint); |
778
|
|
|
|
779
|
24 |
|
return ($datetime >= $this->startDate && $datetime < $this->endDate) |
780
|
24 |
|
|| ($datetime == $this->startDate && $datetime == $this->endDate); |
781
|
|
|
} |
782
|
|
|
|
783
|
|
|
/** |
784
|
|
|
* Returns a new Period object with a new included starting date point. |
785
|
|
|
* |
786
|
|
|
* @param DateTimeInterface|string $startDate date point |
787
|
|
|
* |
788
|
|
|
* @return self |
789
|
|
|
*/ |
790
|
9 |
|
public function startingOn($startDate): self |
791
|
|
|
{ |
792
|
9 |
|
return new self(static::filterDatePoint($startDate), $this->endDate); |
793
|
|
|
} |
794
|
|
|
|
795
|
|
|
/** |
796
|
|
|
* Returns a new Period object with a new ending date point. |
797
|
|
|
* |
798
|
|
|
* @param DateTimeInterface|string $endDate date point |
799
|
|
|
* |
800
|
|
|
* @return self |
801
|
|
|
*/ |
802
|
12 |
|
public function endingOn($endDate): self |
803
|
|
|
{ |
804
|
12 |
|
return new self($this->startDate, static::filterDatePoint($endDate)); |
805
|
|
|
} |
806
|
|
|
|
807
|
|
|
/** |
808
|
|
|
* Returns a new Period object with a new ending date point. |
809
|
|
|
* |
810
|
|
|
* The interval can be |
811
|
|
|
* <ul> |
812
|
|
|
* <li>a DateInterval object</li> |
813
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
814
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
815
|
|
|
* </ul> |
816
|
|
|
* |
817
|
|
|
* @param DateInterval|int|string $interval The interval |
818
|
|
|
* |
819
|
|
|
* @return self |
820
|
|
|
*/ |
821
|
6 |
|
public function withDuration($interval): self |
822
|
|
|
{ |
823
|
6 |
|
return new self($this->startDate, $this->startDate->add(static::filterDateInterval($interval))); |
824
|
|
|
} |
825
|
|
|
|
826
|
|
|
/** |
827
|
|
|
* Returns a new Period object with a new starting date point. |
828
|
|
|
* |
829
|
|
|
* The interval can be |
830
|
|
|
* <ul> |
831
|
|
|
* <li>a DateInterval object</li> |
832
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
833
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
834
|
|
|
* </ul> |
835
|
|
|
* |
836
|
|
|
* @param DateInterval|int|string $interval The interval |
837
|
|
|
* |
838
|
|
|
* @return self |
839
|
|
|
*/ |
840
|
6 |
|
public function withDurationBeforeEnd($interval): self |
841
|
|
|
{ |
842
|
6 |
|
return new self($this->endDate->sub(static::filterDateInterval($interval)), $this->endDate); |
843
|
|
|
} |
844
|
|
|
|
845
|
|
|
/** |
846
|
|
|
* Returns a new Period object with a new starting date point |
847
|
|
|
* moved forward or backward by the given interval |
848
|
|
|
* |
849
|
|
|
* The interval can be |
850
|
|
|
* <ul> |
851
|
|
|
* <li>a DateInterval object</li> |
852
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
853
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
854
|
|
|
* </ul> |
855
|
|
|
* |
856
|
|
|
* @param DateInterval|int|string $interval The interval |
857
|
|
|
* |
858
|
|
|
* @return self |
859
|
|
|
*/ |
860
|
9 |
|
public function moveStartDate($interval): self |
861
|
|
|
{ |
862
|
9 |
|
return new self($this->startDate->add(static::filterDateInterval($interval)), $this->endDate); |
863
|
|
|
} |
864
|
|
|
|
865
|
|
|
/** |
866
|
|
|
* Returns a new Period object with a new ending date point |
867
|
|
|
* moved forward or backward by the given interval |
868
|
|
|
* |
869
|
|
|
* The interval can be |
870
|
|
|
* <ul> |
871
|
|
|
* <li>a DateInterval object</li> |
872
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
873
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
874
|
|
|
* </ul> |
875
|
|
|
* |
876
|
|
|
* @param DateInterval|int|string $interval The interval |
877
|
|
|
* |
878
|
|
|
* @return self |
879
|
|
|
*/ |
880
|
12 |
|
public function moveEndDate($interval): self |
881
|
|
|
{ |
882
|
12 |
|
return new self($this->startDate, $this->endDate->add(static::filterDateInterval($interval))); |
883
|
|
|
} |
884
|
|
|
|
885
|
|
|
/** |
886
|
|
|
* Returns a new Period object where the datepoints |
887
|
|
|
* are moved forwards or backward simultaneously by the given DateInterval |
888
|
|
|
* |
889
|
|
|
* The interval can be |
890
|
|
|
* <ul> |
891
|
|
|
* <li>a DateInterval object</li> |
892
|
|
|
* <li>an int interpreted as the duration expressed in seconds.</li> |
893
|
|
|
* <li>a string in a format supported by DateInterval::createFromDateString</li> |
894
|
|
|
* </ul> |
895
|
|
|
* |
896
|
|
|
* @param DateInterval|int|string $interval The interval |
897
|
|
|
* |
898
|
|
|
* @return self |
899
|
|
|
*/ |
900
|
12 |
|
public function move($interval): self |
901
|
|
|
{ |
902
|
12 |
|
$interval = static::filterDateInterval($interval); |
903
|
|
|
|
904
|
12 |
|
return new self($this->startDate->add($interval), $this->endDate->add($interval)); |
905
|
|
|
} |
906
|
|
|
|
907
|
|
|
/** |
908
|
|
|
* Merges one or more Period objects to return a new Period object. |
909
|
|
|
* |
910
|
|
|
* The resultant object represents the largest duration possible. |
911
|
|
|
* |
912
|
|
|
* @param Period... $periods one or more Period objects |
|
|
|
|
913
|
|
|
* |
914
|
|
|
* @return self |
915
|
|
|
*/ |
916
|
6 |
|
public function merge(Period ...$periods): self |
917
|
|
|
{ |
918
|
6 |
|
return array_reduce($periods, [$this, 'reducer'], $this); |
919
|
|
|
} |
920
|
|
|
|
921
|
|
|
/** |
922
|
|
|
|
923
|
|
|
* Returns a Period whose endpoints are the larget possible |
924
|
|
|
* between 2 instance of Period objects |
925
|
|
|
* |
926
|
|
|
* @param Period $carry |
927
|
|
|
* @param Period $period |
928
|
|
|
* |
929
|
|
|
* @return self |
930
|
|
|
*/ |
931
|
6 |
|
protected function reducer(Period $carry, Period $period): self |
932
|
|
|
{ |
933
|
6 |
|
if ($carry->getStartDate() > $period->getStartDate()) { |
934
|
3 |
|
$carry = $carry->startingOn($period->getStartDate()); |
935
|
|
|
} |
936
|
|
|
|
937
|
6 |
|
if ($carry->getEndDate() < $period->getEndDate()) { |
938
|
6 |
|
$carry = $carry->endingOn($period->getEndDate()); |
939
|
|
|
} |
940
|
|
|
|
941
|
6 |
|
return $carry; |
942
|
|
|
} |
943
|
|
|
|
944
|
|
|
/** |
945
|
|
|
* Computes the intersection between two Period objects. |
946
|
|
|
* |
947
|
|
|
* @param Period $period |
948
|
|
|
* |
949
|
|
|
* @throws Exception If Both objects do not overlaps |
950
|
|
|
* |
951
|
|
|
* @return self |
952
|
|
|
*/ |
953
|
6 |
|
public function intersect(Period $period): self |
954
|
|
|
{ |
955
|
6 |
|
if (!$this->overlaps($period)) { |
956
|
3 |
|
throw new Exception('Both object should at least overlaps'); |
957
|
|
|
} |
958
|
|
|
|
959
|
3 |
|
return new self( |
960
|
3 |
|
($period->getStartDate() > $this->startDate) ? $period->getStartDate() : $this->startDate, |
961
|
3 |
|
($period->getEndDate() < $this->endDate) ? $period->getEndDate() : $this->endDate |
962
|
|
|
); |
963
|
|
|
} |
964
|
|
|
|
965
|
|
|
/** |
966
|
|
|
* Computes the gap between two Period objects. |
967
|
|
|
* |
968
|
|
|
* @param Period $period |
969
|
|
|
* |
970
|
|
|
* @return self |
971
|
|
|
*/ |
972
|
15 |
|
public function gap(Period $period): self |
973
|
|
|
{ |
974
|
15 |
|
if ($period->getStartDate() > $this->startDate) { |
975
|
12 |
|
return new self($this->endDate, $period->getStartDate()); |
976
|
|
|
} |
977
|
|
|
|
978
|
6 |
|
return new self($period->getEndDate(), $this->startDate); |
979
|
|
|
} |
980
|
|
|
|
981
|
|
|
/** |
982
|
|
|
* Returns the difference between two Period objects expressed in seconds |
983
|
|
|
* |
984
|
|
|
* @param Period $period |
985
|
|
|
* |
986
|
|
|
* @return float |
987
|
|
|
*/ |
988
|
3 |
|
public function timestampIntervalDiff(Period $period): float |
989
|
|
|
{ |
990
|
3 |
|
return $this->getTimestampInterval() - $period->getTimestampInterval(); |
991
|
|
|
} |
992
|
|
|
|
993
|
|
|
/** |
994
|
|
|
* Returns the difference between two Period objects expressed in DateInterval |
995
|
|
|
* |
996
|
|
|
* @param Period $period |
997
|
|
|
* |
998
|
|
|
* @return DateInterval |
999
|
|
|
*/ |
1000
|
6 |
|
public function dateIntervalDiff(Period $period): DateInterval |
1001
|
|
|
{ |
1002
|
6 |
|
return $this->endDate->diff($this->startDate->add($period->getDateInterval())); |
1003
|
|
|
} |
1004
|
|
|
|
1005
|
|
|
/** |
1006
|
|
|
* Computes the difference between two overlapsing Period objects |
1007
|
|
|
* |
1008
|
|
|
* Returns an array containing the difference expressed as Period objects |
1009
|
|
|
* The array will: |
1010
|
|
|
* |
1011
|
|
|
* <ul> |
1012
|
|
|
* <li>be empty if both objects have the same datepoints</li> |
1013
|
|
|
* <li>contain one Period object if both objects share one datepoint</li> |
1014
|
|
|
* <li>contain two Period objects if both objects share no datepoint</li> |
1015
|
|
|
* </ul> |
1016
|
|
|
* |
1017
|
|
|
* @param Period $period |
1018
|
|
|
* |
1019
|
|
|
* @throws Exception if both object do not overlaps |
1020
|
|
|
* |
1021
|
|
|
* @return Period[] |
1022
|
|
|
*/ |
1023
|
12 |
|
public function diff(Period $period): array |
1024
|
|
|
{ |
1025
|
12 |
|
if (!$this->overlaps($period)) { |
1026
|
3 |
|
throw new Exception('Both Period objects must overlaps'); |
1027
|
|
|
} |
1028
|
|
|
|
1029
|
|
|
$res = [ |
1030
|
9 |
|
static::createFromDatepoints($this->startDate, $period->getStartDate()), |
1031
|
9 |
|
static::createFromDatepoints($this->endDate, $period->getEndDate()), |
1032
|
|
|
]; |
1033
|
|
|
|
1034
|
9 |
|
$filter = function (Period $period) { |
1035
|
9 |
|
return $period->getStartDate() != $period->getEndDate(); |
1036
|
9 |
|
}; |
1037
|
|
|
|
1038
|
9 |
|
return array_values(array_filter($res, $filter)); |
1039
|
|
|
} |
1040
|
|
|
|
1041
|
|
|
/** |
1042
|
|
|
* Create a new instance given two datepoints |
1043
|
|
|
* |
1044
|
|
|
* The datepoints will be used as to allow the creation of |
1045
|
|
|
* a Period object |
1046
|
|
|
* |
1047
|
|
|
* @param DateTimeInterface|string $datePoint1 datepoint |
1048
|
|
|
* @param DateTimeInterface|string $datePoint2 datepoint |
1049
|
|
|
* |
1050
|
|
|
* @return Period |
1051
|
|
|
*/ |
1052
|
9 |
|
protected static function createFromDatepoints($datePoint1, $datePoint2): self |
1053
|
|
|
{ |
1054
|
9 |
|
$startDate = static::filterDatePoint($datePoint1); |
1055
|
9 |
|
$endDate = static::filterDatePoint($datePoint2); |
1056
|
9 |
|
if ($startDate > $endDate) { |
1057
|
3 |
|
return new self($endDate, $startDate); |
1058
|
|
|
} |
1059
|
|
|
|
1060
|
6 |
|
return new self($startDate, $endDate); |
1061
|
|
|
} |
1062
|
|
|
} |
1063
|
|
|
|
This check marks calls to methods that do not seem to exist on an object.
This is most likely the result of a method being renamed without all references to it being renamed likewise.