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:10
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
    /**
234
     * @param Period $period
235
     * @return bool
236
     * @throws CannotComparePeriods
237
     */
238
    public function touchesWith(Period $period): bool
239
    {
240
        $this->ensurePrecisionMatches($period);
241
242
        if ($this->getIncludedEnd()->diff($period->getIncludedStart())->days <= 1) {
243
            return true;
244
        }
245
246
        if ($this->getIncludedStart()->diff($period->getIncludedEnd())->days <= 1) {
247
            return true;
248
        }
249
250
        return false;
251
    }
252
253
    /**
254
     * @param DateTimeInterface $date
255
     * @return bool
256
     */
257
    public function startsBefore(DateTimeInterface $date): bool
258
    {
259
        return $this->getIncludedStart() < $date;
260
    }
261
262
    /**
263
     * @param DateTimeInterface $date
264
     * @return bool
265
     */
266
    public function startsBeforeOrAt(DateTimeInterface $date): bool
267
    {
268
        return $this->getIncludedStart() <= $date;
269
    }
270
271
    /**
272
     * @param DateTimeInterface $date
273
     * @return bool
274
     */
275
    public function startsAfter(DateTimeInterface $date): bool
276
    {
277
        return $this->getIncludedStart() > $date;
278
    }
279
280
    /**
281
     * @param DateTimeInterface $date
282
     * @return bool
283
     */
284
    public function startsAfterOrAt(DateTimeInterface $date): bool
285
    {
286
        return $this->getIncludedStart() >= $date;
287
    }
288
289
    /**
290
     * @param DateTimeInterface $date
291
     * @return bool
292
     */
293
    public function startsAt(DateTimeInterface $date): bool
294
    {
295
        return $this->getIncludedStart()->getTimestamp() === $this->roundDate(
296
            $date,
297
            $this->precisionMask
298
        )->getTimestamp();
299
    }
300
301
    /**
302
     * @param DateTimeInterface $date
303
     * @return bool
304
     */
305
    public function endsBefore(DateTimeInterface $date): bool
306
    {
307
        return $this->getIncludedEnd() < $this->roundDate(
308
                $date,
309
                $this->precisionMask
310
            );
311
    }
312
313
    /**
314
     * @param DateTimeInterface $date
315
     * @return bool
316
     */
317
    public function endsBeforeOrAt(DateTimeInterface $date): bool
318
    {
319
        return $this->getIncludedEnd() <= $this->roundDate(
320
                $date,
321
                $this->precisionMask
322
            );
323
    }
324
325
    /**
326
     * @param DateTimeInterface $date
327
     * @return bool
328
     */
329
    public function endsAfter(DateTimeInterface $date): bool
330
    {
331
        return $this->getIncludedEnd() > $this->roundDate(
332
                $date,
333
                $this->precisionMask
334
            );
335
    }
336
337
    /**
338
     * @param DateTimeInterface $date
339
     * @return bool
340
     */
341
    public function endsAfterOrAt(DateTimeInterface $date): bool
342
    {
343
        return $this->getIncludedEnd() >= $this->roundDate(
344
                $date,
345
                $this->precisionMask
346
            );
347
    }
348
349
    /**
350
     * @param DateTimeInterface $date
351
     * @return bool
352
     */
353
    public function endsAt(DateTimeInterface $date): bool
354
    {
355
        return $this->getIncludedEnd()->getTimestamp() === $this->roundDate(
356
                $date,
357
                $this->precisionMask
358
            )->getTimestamp();
359
    }
360
361
    /**
362
     * @param DateTimeInterface $date
363
     * @return bool
364
     */
365
    public function contains(DateTimeInterface $date): bool
366
    {
367
        if ($this->roundDate($date, $this->precisionMask) < $this->getIncludedStart()) {
368
            return false;
369
        }
370
371
        if ($this->roundDate($date, $this->precisionMask) > $this->getIncludedEnd()) {
372
            return false;
373
        }
374
375
        return true;
376
    }
377
378
    /**
379
     * @param Period $period
380
     * @return bool
381
     * @throws CannotComparePeriods
382
     */
383
    public function equals(Period $period): bool
384
    {
385
        $this->ensurePrecisionMatches($period);
386
387
        if ($period->getIncludedStart()->getTimestamp() !== $this->getIncludedStart()->getTimestamp()) {
388
            return false;
389
        }
390
391
        if ($period->getIncludedEnd()->getTimestamp() !== $this->getIncludedEnd()->getTimestamp()) {
392
            return false;
393
        }
394
395
        return true;
396
    }
397
398
    /**
399
     * @param \Spatie\Period\Period $period
400
     *
401
     * @return static|null
402
     * @throws \Exception
403
     */
404
    public function gap(Period $period): ?Period
405
    {
406
        $this->ensurePrecisionMatches($period);
407
408
        if ($this->overlapsWith($period)) {
409
            return null;
410
        }
411
412
        if ($this->touchesWith($period)) {
413
            return null;
414
        }
415
416
        if ($this->getIncludedStart() >= $period->getIncludedEnd()) {
417
            return static::make(
418
                $period->getIncludedEnd()->add($this->interval),
419
                $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...
420
                $this->getPrecisionMask()
421
            );
422
        }
423
424
        return static::make(
425
            $this->getIncludedEnd()->add($this->interval),
426
            $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...
427
            $this->getPrecisionMask()
428
        );
429
    }
430
431
    /**
432
     * @param Period $period
433
     * @return Period|null
434
     * @throws CannotComparePeriods
435
     */
436
    public function overlapSingle(Period $period): ?Period
437
    {
438
        $this->ensurePrecisionMatches($period);
439
440
        $start = $this->getIncludedStart() > $period->getIncludedStart()
441
            ? $this->getIncludedStart()
442
            : $period->getIncludedStart();
443
444
        $end = $this->getIncludedEnd() < $period->getIncludedEnd()
445
            ? $this->getIncludedEnd()
446
            : $period->getIncludedEnd();
447
448
        if ($start > $end) {
449
            return null;
450
        }
451
452
        return static::make($start, $end, $this->getPrecisionMask());
453
    }
454
455
    /**
456
     * @param Period ...$periods
457
     * @return PeriodCollection
458
     * @throws CannotComparePeriods
459
     */
460
    public function overlap(Period ...$periods): PeriodCollection
461
    {
462
        $overlapCollection = new PeriodCollection();
463
464
        foreach ($periods as $period) {
465
            $overlap = $this->overlapSingle($period);
466
467
            if ($overlap === null) {
468
                continue;
469
            }
470
471
            $overlapCollection[] = $overlap;
472
        }
473
474
        return $overlapCollection;
475
    }
476
477
    /**
478
     * @param Period ...$periods
479
     * @return Period
480
     * @throws CannotComparePeriods
481
     */
482
    public function overlapAll(Period ...$periods): Period
483
    {
484
        $overlap = clone $this;
485
486
        if (! count($periods)) {
487
            return $overlap;
488
        }
489
490
        foreach ($periods as $period) {
491
            $overlap = $overlap->overlapSingle($period);
492
        }
493
494
        return $overlap;
495
    }
496
497
    /**
498
     * @param Period $period
499
     * @return PeriodCollection
500
     * @throws CannotComparePeriods
501
     */
502
    public function diffSingle(Period $period): PeriodCollection
503
    {
504
        $this->ensurePrecisionMatches($period);
505
506
        $periodCollection = new PeriodCollection();
507
508
        if (! $this->overlapsWith($period)) {
509
            $periodCollection[] = clone $this;
510
            $periodCollection[] = clone $period;
511
512
            return $periodCollection;
513
        }
514
515
        $overlap = $this->overlapSingle($period);
516
517
        $start = $this->getIncludedStart() < $period->getIncludedStart()
518
            ? $this->getIncludedStart()
519
            : $period->getIncludedStart();
520
521
        $end = $this->getIncludedEnd() > $period->getIncludedEnd()
522
            ? $this->getIncludedEnd()
523
            : $period->getIncludedEnd();
524
525
        if ($overlap->getIncludedStart() > $start) {
526
            $periodCollection[] = static::make(
527
                $start,
528
                $overlap->getIncludedStart()->sub($this->interval),
529
                $this->getPrecisionMask()
530
            );
531
        }
532
533
        if ($overlap->getIncludedEnd() < $end) {
534
            $periodCollection[] = static::make(
535
                $overlap->getIncludedEnd()->add($this->interval),
536
                $end,
537
                $this->getPrecisionMask()
538
            );
539
        }
540
541
        return $periodCollection;
542
    }
543
544
    /**
545
     * @param Period ...$periods
546
     * @return PeriodCollection
547
     * @throws CannotComparePeriods
548
     */
549
    public function diff(Period ...$periods): PeriodCollection
550
    {
551
        if (count($periods) === 1 && ! $this->overlapsWith($periods[0])) {
552
            $collection = new PeriodCollection();
553
554
            $gap = $this->gap($periods[0]);
555
556
            if ($gap !== null) {
557
                $collection[] = $gap;
558
            }
559
560
            return $collection;
561
        }
562
563
        $diffs = [];
564
565
        foreach ($periods as $period) {
566
            $diffs[] = $this->diffSingle($period);
567
        }
568
569
        $collection = (new PeriodCollection($this))->overlap(...$diffs);
570
571
        return $collection;
572
    }
573
574
    /**
575
     * @return int
576
     */
577
    public function getPrecisionMask(): int
578
    {
579
        return $this->precisionMask;
580
    }
581
582
    /**
583
     * @return DatePeriod|\Traversable
584
     */
585
    public function getIterator()
586
    {
587
        return new DatePeriod(
588
            $this->getIncludedStart(),
589
            $this->interval,
590
            $this->getIncludedEnd()->add($this->interval)
591
        );
592
    }
593
594
    /**
595
     * @param $date
596
     * @param string|null $format
597
     * @return DateTimeImmutable
598
     */
599
    protected static function resolveDate($date, ?string $format): DateTimeImmutable
600
    {
601
        if ($date instanceof DateTimeImmutable) {
602
            return $date;
603
        }
604
605
        if ($date instanceof DateTime) {
606
            return DateTimeImmutable::createFromMutable($date);
607
        }
608
609
        $format = static::resolveFormat($date, $format);
610
611
        if (! is_string($date)) {
612
            throw InvalidDate::forFormat($date, $format);
613
        }
614
615
        $dateTime = DateTimeImmutable::createFromFormat($format, $date);
616
617
        if ($dateTime === false) {
618
            throw InvalidDate::forFormat($date, $format);
619
        }
620
621
        if (strpos($format, ' ') === false) {
622
            $dateTime = $dateTime->setTime(0, 0, 0);
623
        }
624
625
        return $dateTime;
626
    }
627
628
    /**
629
     * @param $date
630
     * @param string|null $format
631
     * @return string
632
     */
633
    protected static function resolveFormat($date, ?string $format): string
634
    {
635
        if ($format !== null) {
636
            return $format;
637
        }
638
639
        if (strpos($format, ' ') === false && strpos($date, ' ') !== false) {
640
            return 'Y-m-d H:i:s';
641
        }
642
643
        return 'Y-m-d';
644
    }
645
646
    /**
647
     * @param DateTimeInterface $date
648
     * @param int $precision
649
     * @return DateTimeImmutable
650
     */
651
    protected function roundDate(DateTimeInterface $date, int $precision): DateTimeImmutable
652
    {
653
        [$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...
654
655
        $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...
656
        $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...
657
        $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...
658
        $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...
659
        $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...
660
661
        return DateTimeImmutable::createFromFormat(
662
            'Y m d H i s',
663
            implode(' ', [$year, $month, $day, $hour, $minute, $second])
664
        );
665
    }
666
667
    /**
668
     * @param int $precision
669
     * @return DateInterval
670
     * @throws \Exception
671
     */
672
    protected function createDateInterval(int $precision): DateInterval
673
    {
674
        $interval = [
675
            Precision::SECOND => 'PT1S',
676
            Precision::MINUTE => 'PT1M',
677
            Precision::HOUR => 'PT1H',
678
            Precision::DAY => 'P1D',
679
            Precision::MONTH => 'P1M',
680
            Precision::YEAR => 'P1Y',
681
        ][$precision];
682
683
        return new DateInterval($interval);
684
    }
685
686
    /**
687
     * @param Period $period
688
     * @throws CannotComparePeriods
689
     */
690
    protected function ensurePrecisionMatches(Period $period): void
691
    {
692
        if ($this->precisionMask === $period->precisionMask) {
693
            return;
694
        }
695
696
        throw CannotComparePeriods::precisionDoesNotMatch();
697
    }
698
}
699