GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#51)
by
unknown
01:36 queued 27s
created

Period::__construct()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.8177
c 0
b 0
f 0
cc 6
nc 9
nop 4
1
<?php
2
3
namespace Spatie\Period;
4
5
use DateTime;
6
use DatePeriod;
7
use DateInterval;
8
use DateTimeImmutable;
9
use DateTimeInterface;
10
use IteratorAggregate;
11
use Spatie\Period\Exceptions\InvalidDate;
12
use Spatie\Period\Exceptions\InvalidPeriod;
13
use Spatie\Period\Exceptions\CannotComparePeriods;
14
15
class Period implements IteratorAggregate
16
{
17
    /** @var \DateTimeImmutable */
18
    protected $start;
19
20
    /** @var \DateTimeImmutable */
21
    protected $end;
22
23
    /** @var \DateInterval */
24
    protected $interval;
25
26
    /** @var \DateTimeImmutable */
27
    private $includedStart;
28
29
    /** @var \DateTimeImmutable */
30
    private $includedEnd;
31
32
    /** @var int */
33
    private $boundaryExclusionMask;
34
35
    /** @var int */
36
    private $precisionMask;
37
38
    /**
39
     * Period constructor.
40
     * @param DateTimeImmutable $start
41
     * @param DateTimeImmutable $end
42
     * @param int|null $precisionMask
43
     * @param int|null $boundaryExclusionMask
44
     * @throws \Exception
45
     */
46
    public function __construct(
47
        DateTimeImmutable $start,
48
        ?DateTimeImmutable $end,
49
        ?int $precisionMask = null,
50
        ?int $boundaryExclusionMask = null
51
    ) {
52
        if ($start > $end && null != $end) {
53
            throw InvalidPeriod::endBeforeStart($start, $end);
54
        }
55
56
        $this->boundaryExclusionMask = $boundaryExclusionMask ?? Boundaries::EXCLUDE_NONE;
57
        $this->precisionMask = $precisionMask ?? Precision::DAY;
58
59
        $this->start = $this->roundDate($start, $this->precisionMask);
60
        if (null != $end) {
61
            $this->end = $this->roundDate($end, $this->precisionMask);
62
        } else {
63
            $this->end = null;
64
        }
65
66
        $this->interval = $this->createDateInterval($this->precisionMask);
67
68
        $this->includedStart = $this->startIncluded()
69
            ? $this->start
70
            : $this->start->add($this->interval);
71
72
        $this->includedEnd = $this->endIncluded()
73
            ? $this->end
74
            : $this->end->sub($this->interval);
75
    }
76
77
    /**
78
     * @param string|DateTimeInterface $start
79
     * @param string|DateTimeInterface $end
80
     * @param int|null $precisionMask
81
     * @param int|null $boundaryExclusionMask
82
     * @param string|null $format
83
     *
84
     * @return static
85
     */
86
    public static function make(
87
        $start,
88
        $end,
89
        ?int $precisionMask = null,
90
        ?int $boundaryExclusionMask = null,
91
        ?string $format = null
92
    ): Period {
93
        if ($start === null) {
94
            throw InvalidDate::cannotBeNull('Start date');
95
        }
96
97
//        if ($end === null) {
98
//            throw InvalidDate::cannotBeNull('End date');
99
//        }
100
101
        return new static(
102
            static::resolveDate($start, $format),
103
            $end ? static::resolveDate($end, $format) : null,
0 ignored issues
show
Bug introduced by
It seems like $end ? static::resolveDate($end, $format) : null can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
104
            $precisionMask,
105
            $boundaryExclusionMask
106
        );
107
    }
108
109
    /**
110
     * @return bool
111
     */
112
    public function startIncluded(): bool
113
    {
114
        return ! $this->startExcluded();
115
    }
116
117
    /**
118
     * @return bool
119
     */
120
    public function startExcluded(): bool
121
    {
122
        return Boundaries::EXCLUDE_START & $this->boundaryExclusionMask;
123
    }
124
125
    /**
126
     * @return bool
127
     */
128
    public function endIncluded(): bool
129
    {
130
        return ! $this->endExcluded();
131
    }
132
133
    /**
134
     * @return bool
135
     */
136
    public function endExcluded(): bool
137
    {
138
        return Boundaries::EXCLUDE_END & $this->boundaryExclusionMask;
139
    }
140
141
    /**
142
     * @return DateTimeImmutable
143
     */
144
    public function getStart(): DateTimeImmutable
145
    {
146
        return $this->start;
147
    }
148
149
    /**
150
     * @return DateTimeImmutable
151
     */
152
    public function getIncludedStart(): DateTimeImmutable
153
    {
154
        return $this->includedStart;
155
    }
156
157
    /**
158
     * @return DateTimeImmutable
159
     */
160
    public function getEnd(): DateTimeImmutable
161
    {
162
        return $this->end;
163
    }
164
165
    /**
166
     * @return DateTimeImmutable
167
     */
168
    public function getIncludedEnd(): DateTimeImmutable
169
    {
170
        return $this->includedEnd;
171
    }
172
173
    /**
174
     * @return int
175
     */
176
    public function length(): int
177
    {
178
        $length = $this->getIncludedStart()->diff($this->getIncludedEnd())->days + 1;
179
180
        return $length;
181
    }
182
183
    /**
184
     * @param Period $period
185
     * @return bool
186
     * @throws CannotComparePeriods
187
     */
188
    public function overlapsWith(Period $period): bool
189
    {
190
        $this->ensurePrecisionMatches($period);
191
192
        // if all Period have end
193
        if (null != $this->end && null != $period->end) {
194
            if ($this->getIncludedStart() > $period->getIncludedEnd()) {
195
                return false;
196
            }
197
198
            if ($period->getIncludedStart() > $this->getIncludedEnd()) {
199
                return false;
200
            }
201
202
            return true;
203
204
        // if one of the Periods does not have end
205
        } else {
206
207
            // if this Period end have null and another Period end don`t
208
            if (null == $this->end && null != $period->end) {
209
                if ($this->getIncludedStart() > $period->getIncludedEnd()) {
210
                    return false;
211
                }
212
213
                return true;
214
            }
215
216
            // if this Period end don`t null and another Period end have null
217
            if (null != $this->end && null == $period->end) {
218
                if ($period->getIncludedStart() > $this->getIncludedEnd()) {
219
                    return false;
220
                }
221
222
                return true;
223
            }
224
225
            // if above Period end have null
226
            if (null == $this->end && null == $period->end) {
227
                return true;
228
            }
229
        }
230
    }
231
232
    /**
233
     * @param Period $period
234
     * @return bool
235
     * @throws CannotComparePeriods
236
     */
237
    public function touchesWith(Period $period): bool
238
    {
239
        $this->ensurePrecisionMatches($period);
240
241
        if ($this->getIncludedEnd()->diff($period->getIncludedStart())->days <= 1) {
242
            return true;
243
        }
244
245
        if ($this->getIncludedStart()->diff($period->getIncludedEnd())->days <= 1) {
246
            return true;
247
        }
248
249
        return false;
250
    }
251
252
    /**
253
     * @param DateTimeInterface $date
254
     * @return bool
255
     */
256
    public function startsBefore(DateTimeInterface $date): bool
257
    {
258
        return $this->getIncludedStart() < $date;
259
    }
260
261
    /**
262
     * @param DateTimeInterface $date
263
     * @return bool
264
     */
265
    public function startsBeforeOrAt(DateTimeInterface $date): bool
266
    {
267
        return $this->getIncludedStart() <= $date;
268
    }
269
270
    /**
271
     * @param DateTimeInterface $date
272
     * @return bool
273
     */
274
    public function startsAfter(DateTimeInterface $date): bool
275
    {
276
        return $this->getIncludedStart() > $date;
277
    }
278
279
    /**
280
     * @param DateTimeInterface $date
281
     * @return bool
282
     */
283
    public function startsAfterOrAt(DateTimeInterface $date): bool
284
    {
285
        return $this->getIncludedStart() >= $date;
286
    }
287
288
    /**
289
     * @param DateTimeInterface $date
290
     * @return bool
291
     */
292
    public function startsAt(DateTimeInterface $date): bool
293
    {
294
        return $this->getIncludedStart()->getTimestamp() === $this->roundDate(
295
            $date,
296
            $this->precisionMask
297
        )->getTimestamp();
298
    }
299
300
    /**
301
     * @param DateTimeInterface $date
302
     * @return bool
303
     */
304
    public function endsBefore(DateTimeInterface $date): bool
305
    {
306
        return $this->getIncludedEnd() < $this->roundDate(
307
                $date,
308
                $this->precisionMask
309
            );
310
    }
311
312
    /**
313
     * @param DateTimeInterface $date
314
     * @return bool
315
     */
316
    public function endsBeforeOrAt(DateTimeInterface $date): bool
317
    {
318
        return $this->getIncludedEnd() <= $this->roundDate(
319
                $date,
320
                $this->precisionMask
321
            );
322
    }
323
324
    /**
325
     * @param DateTimeInterface $date
326
     * @return bool
327
     */
328
    public function endsAfter(DateTimeInterface $date): bool
329
    {
330
        return $this->getIncludedEnd() > $this->roundDate(
331
                $date,
332
                $this->precisionMask
333
            );
334
    }
335
336
    /**
337
     * @param DateTimeInterface $date
338
     * @return bool
339
     */
340
    public function endsAfterOrAt(DateTimeInterface $date): bool
341
    {
342
        return $this->getIncludedEnd() >= $this->roundDate(
343
                $date,
344
                $this->precisionMask
345
            );
346
    }
347
348
    /**
349
     * @param DateTimeInterface $date
350
     * @return bool
351
     */
352
    public function endsAt(DateTimeInterface $date): bool
353
    {
354
        return $this->getIncludedEnd()->getTimestamp() === $this->roundDate(
355
                $date,
356
                $this->precisionMask
357
            )->getTimestamp();
358
    }
359
360
    /**
361
     * @param DateTimeInterface $date
362
     * @return bool
363
     */
364
    public function contains(DateTimeInterface $date): bool
365
    {
366
        if ($this->roundDate($date, $this->precisionMask) < $this->getIncludedStart()) {
367
            return false;
368
        }
369
370
        if ($this->roundDate($date, $this->precisionMask) > $this->getIncludedEnd()) {
371
            return false;
372
        }
373
374
        return true;
375
    }
376
377
    /**
378
     * @param Period $period
379
     * @return bool
380
     * @throws CannotComparePeriods
381
     */
382
    public function equals(Period $period): bool
383
    {
384
        $this->ensurePrecisionMatches($period);
385
386
        if ($period->getIncludedStart()->getTimestamp() !== $this->getIncludedStart()->getTimestamp()) {
387
            return false;
388
        }
389
390
        if ($period->getIncludedEnd()->getTimestamp() !== $this->getIncludedEnd()->getTimestamp()) {
391
            return false;
392
        }
393
394
        return true;
395
    }
396
397
    /**
398
     * @param \Spatie\Period\Period $period
399
     *
400
     * @return static|null
401
     * @throws \Exception
402
     */
403
    public function gap(Period $period): ?Period
404
    {
405
        $this->ensurePrecisionMatches($period);
406
407
        if ($this->overlapsWith($period)) {
408
            return null;
409
        }
410
411
        if ($this->touchesWith($period)) {
412
            return null;
413
        }
414
415
        if ($this->getIncludedStart() >= $period->getIncludedEnd()) {
416
            return static::make(
417
                $period->getIncludedEnd()->add($this->interval),
418
                $this->getIncludedStart()->sub($this->interval),
0 ignored issues
show
Security Bug introduced by
It seems like $this->getIncludedStart()->sub($this->interval) targeting DateTimeImmutable::sub() can also be of type false; however, Spatie\Period\Period::make() does only seem to accept string|object<DateTimeInterface>, did you maybe forget to handle an error condition?
Loading history...
419
                $this->getPrecisionMask()
420
            );
421
        }
422
423
        return static::make(
424
            $this->getIncludedEnd()->add($this->interval),
425
            $period->getIncludedStart()->sub($this->interval),
0 ignored issues
show
Security Bug introduced by
It seems like $period->getIncludedStart()->sub($this->interval) targeting DateTimeImmutable::sub() can also be of type false; however, Spatie\Period\Period::make() does only seem to accept string|object<DateTimeInterface>, did you maybe forget to handle an error condition?
Loading history...
426
            $this->getPrecisionMask()
427
        );
428
    }
429
430
    /**
431
     * @param Period $period
432
     * @return Period|null
433
     * @throws CannotComparePeriods
434
     */
435
    public function overlapSingle(Period $period): ?Period
436
    {
437
        $this->ensurePrecisionMatches($period);
438
439
        $start = $this->getIncludedStart() > $period->getIncludedStart()
440
            ? $this->getIncludedStart()
441
            : $period->getIncludedStart();
442
443
        $end = $this->getIncludedEnd() < $period->getIncludedEnd()
444
            ? $this->getIncludedEnd()
445
            : $period->getIncludedEnd();
446
447
        if ($start > $end) {
448
            return null;
449
        }
450
451
        return static::make($start, $end, $this->getPrecisionMask());
452
    }
453
454
    /**
455
     * @param Period ...$periods
456
     * @return PeriodCollection
457
     * @throws CannotComparePeriods
458
     */
459
    public function overlap(Period ...$periods): PeriodCollection
460
    {
461
        $overlapCollection = new PeriodCollection();
462
463
        foreach ($periods as $period) {
464
            $overlap = $this->overlapSingle($period);
465
466
            if ($overlap === null) {
467
                continue;
468
            }
469
470
            $overlapCollection[] = $overlap;
471
        }
472
473
        return $overlapCollection;
474
    }
475
476
    /**
477
     * @param Period ...$periods
478
     * @return Period
479
     * @throws CannotComparePeriods
480
     */
481
    public function overlapAll(Period ...$periods): Period
482
    {
483
        $overlap = clone $this;
484
485
        if (! count($periods)) {
486
            return $overlap;
487
        }
488
489
        foreach ($periods as $period) {
490
            $overlap = $overlap->overlapSingle($period);
491
        }
492
493
        return $overlap;
494
    }
495
496
    /**
497
     * @param Period $period
498
     * @return PeriodCollection
499
     * @throws CannotComparePeriods
500
     */
501
    public function diffSingle(Period $period): PeriodCollection
502
    {
503
        $this->ensurePrecisionMatches($period);
504
505
        $periodCollection = new PeriodCollection();
506
507
        if (! $this->overlapsWith($period)) {
508
            $periodCollection[] = clone $this;
509
            $periodCollection[] = clone $period;
510
511
            return $periodCollection;
512
        }
513
514
        $overlap = $this->overlapSingle($period);
515
516
        $start = $this->getIncludedStart() < $period->getIncludedStart()
517
            ? $this->getIncludedStart()
518
            : $period->getIncludedStart();
519
520
        $end = $this->getIncludedEnd() > $period->getIncludedEnd()
521
            ? $this->getIncludedEnd()
522
            : $period->getIncludedEnd();
523
524
        if ($overlap->getIncludedStart() > $start) {
525
            $periodCollection[] = static::make(
526
                $start,
527
                $overlap->getIncludedStart()->sub($this->interval),
528
                $this->getPrecisionMask()
529
            );
530
        }
531
532
        if ($overlap->getIncludedEnd() < $end) {
533
            $periodCollection[] = static::make(
534
                $overlap->getIncludedEnd()->add($this->interval),
535
                $end,
536
                $this->getPrecisionMask()
537
            );
538
        }
539
540
        return $periodCollection;
541
    }
542
543
    /**
544
     * @param Period ...$periods
545
     * @return PeriodCollection
546
     * @throws CannotComparePeriods
547
     */
548
    public function diff(Period ...$periods): PeriodCollection
549
    {
550
        if (count($periods) === 1 && ! $this->overlapsWith($periods[0])) {
551
            $collection = new PeriodCollection();
552
553
            $gap = $this->gap($periods[0]);
554
555
            if ($gap !== null) {
556
                $collection[] = $gap;
557
            }
558
559
            return $collection;
560
        }
561
562
        $diffs = [];
563
564
        foreach ($periods as $period) {
565
            $diffs[] = $this->diffSingle($period);
566
        }
567
568
        $collection = (new PeriodCollection($this))->overlap(...$diffs);
569
570
        return $collection;
571
    }
572
573
    /**
574
     * @return int
575
     */
576
    public function getPrecisionMask(): int
577
    {
578
        return $this->precisionMask;
579
    }
580
581
    /**
582
     * @return DatePeriod|\Traversable
583
     */
584
    public function getIterator()
585
    {
586
        return new DatePeriod(
587
            $this->getIncludedStart(),
588
            $this->interval,
589
            $this->getIncludedEnd()->add($this->interval)
590
        );
591
    }
592
593
    /**
594
     * @param $date
595
     * @param string|null $format
596
     * @return DateTimeImmutable
597
     */
598
    protected static function resolveDate($date, ?string $format): DateTimeImmutable
599
    {
600
        if ($date instanceof DateTimeImmutable) {
601
            return $date;
602
        }
603
604
        if ($date instanceof DateTime) {
605
            return DateTimeImmutable::createFromMutable($date);
606
        }
607
608
        $format = static::resolveFormat($date, $format);
609
610
        if (! is_string($date)) {
611
            throw InvalidDate::forFormat($date, $format);
612
        }
613
614
        $dateTime = DateTimeImmutable::createFromFormat($format, $date);
615
616
        if ($dateTime === false) {
617
            throw InvalidDate::forFormat($date, $format);
618
        }
619
620
        if (strpos($format, ' ') === false) {
621
            $dateTime = $dateTime->setTime(0, 0, 0);
622
        }
623
624
        return $dateTime;
625
    }
626
627
    /**
628
     * @param $date
629
     * @param string|null $format
630
     * @return string
631
     */
632
    protected static function resolveFormat($date, ?string $format): string
633
    {
634
        if ($format !== null) {
635
            return $format;
636
        }
637
638
        if (strpos($format, ' ') === false && strpos($date, ' ') !== false) {
639
            return 'Y-m-d H:i:s';
640
        }
641
642
        return 'Y-m-d';
643
    }
644
645
    /**
646
     * @param DateTimeInterface $date
647
     * @param int $precision
648
     * @return DateTimeImmutable
649
     */
650
    protected function roundDate(DateTimeInterface $date, int $precision): DateTimeImmutable
651
    {
652
        [$year, $month, $day, $hour, $minute, $second] = explode(' ', $date->format('Y m d H i s'));
0 ignored issues
show
Bug introduced by
The variable $year does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $month seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $day seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $hour seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $minute seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $second seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
653
654
        $month = (Precision::MONTH & $precision) === Precision::MONTH ? $month : '01';
0 ignored issues
show
Bug introduced by
The variable $month seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
655
        $day = (Precision::DAY & $precision) === Precision::DAY ? $day : '01';
0 ignored issues
show
Bug introduced by
The variable $day seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
656
        $hour = (Precision::HOUR & $precision) === Precision::HOUR ? $hour : '00';
0 ignored issues
show
Bug introduced by
The variable $hour seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
657
        $minute = (Precision::MINUTE & $precision) === Precision::MINUTE ? $minute : '00';
0 ignored issues
show
Bug introduced by
The variable $minute seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
658
        $second = (Precision::SECOND & $precision) === Precision::SECOND ? $second : '00';
0 ignored issues
show
Bug introduced by
The variable $second seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
659
660
        return DateTimeImmutable::createFromFormat(
661
            'Y m d H i s',
662
            implode(' ', [$year, $month, $day, $hour, $minute, $second])
663
        );
664
    }
665
666
    /**
667
     * @param int $precision
668
     * @return DateInterval
669
     * @throws \Exception
670
     */
671
    protected function createDateInterval(int $precision): DateInterval
672
    {
673
        $interval = [
674
            Precision::SECOND => 'PT1S',
675
            Precision::MINUTE => 'PT1M',
676
            Precision::HOUR => 'PT1H',
677
            Precision::DAY => 'P1D',
678
            Precision::MONTH => 'P1M',
679
            Precision::YEAR => 'P1Y',
680
        ][$precision];
681
682
        return new DateInterval($interval);
683
    }
684
685
    /**
686
     * @param Period $period
687
     * @throws CannotComparePeriods
688
     */
689
    protected function ensurePrecisionMatches(Period $period): void
690
    {
691
        if ($this->precisionMask === $period->precisionMask) {
692
            return;
693
        }
694
695
        throw CannotComparePeriods::precisionDoesNotMatch();
696
    }
697
}
698