• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

azjezz / psl / 22519606807

28 Feb 2026 11:11AM UTC coverage: 97.532% (-1.2%) from 98.733%
22519606807

push

github

web-flow
feat(network): rewrite networking stack with TLS, UDP, SOCKS5, CIDR, and IO utilities (#585)

860 of 937 new or added lines in 31 files covered. (91.78%)

15 existing lines in 6 files now uncovered.

7470 of 7659 relevant lines covered (97.53%)

42.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.29
/src/Psl/DateTime/Duration.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Psl\DateTime;
6

7
use DateInterval;
8
use JsonSerializable;
9
use Psl\Comparison;
10
use Psl\Interoperability;
11
use Psl\Math;
12
use Psl\Str;
13
use Stringable;
14

15
/**
16
 * Defines a representation of a time duration with specific hours, minutes, seconds,
17
 * and nanoseconds.
18
 *
19
 * All instances are normalized as follows:
20
 *
21
 * - all non-zero parts (hours, minutes, seconds, nanoseconds) will have the same sign
22
 * - minutes, seconds will be between -59 and 59
23
 * - nanoseconds will be between -999999999 and 999999999 (less than 1 second)
24
 *
25
 * For example, Duration::hours(2, -183) normalizes to "-1 hour(s), -3 minute(s)".
26
 *
27
 * @implements Comparison\Comparable<Duration>
28
 * @implements Comparison\Equable<Duration>
29
 * @implements Interoperability\ToStdlib<DateInterval>
30
 *
31
 * @immutable
32
 */
33
final readonly class Duration implements
34
    Comparison\Comparable,
35
    Comparison\Equable,
36
    JsonSerializable,
37
    Stringable,
38
    Interoperability\ToStdlib
39
{
40
    /**
41
     * Initializes a new instance of Duration with specified hours, minutes, seconds, and
42
     * nanoseconds.
43
     *
44
     * @param int $hours
45
     * @param int<-59, 59> $minutes
46
     * @param int<-59, 59> $seconds
47
     * @param int<-999999999, 999999999> $nanoseconds
48
     *
49
     * @pure
50
     */
51
    private function __construct(
52
        private int $hours,
53
        private int $minutes,
54
        private int $seconds,
55
        private int $nanoseconds,
56
    ) {}
202✔
57

58
    /**
59
     * Returns an instance representing the specified number of hours (and
60
     * optionally minutes, seconds, nanoseconds). Due to normalization, the
61
     * actual values in the returned instance may differ from the provided ones.
62
     *
63
     * @pure
64
     *
65
     * @mago-expect lint:no-else-clause
66
     */
67
    public static function fromParts(int $hours, int $minutes = 0, int $seconds = 0, int $nanoseconds = 0): self
68
    {
69
        // This is where the normalization happens.
70
        $s =
201✔
71
            (SECONDS_PER_HOUR * $hours)
201✔
72
            + (SECONDS_PER_MINUTE * $minutes)
201✔
73
            + $seconds
201✔
74
            + (int) ($nanoseconds / NANOSECONDS_PER_SECOND);
201✔
75
        $ns = $nanoseconds % NANOSECONDS_PER_SECOND;
201✔
76
        if ($s < 0 && $ns > 0) {
201✔
77
            ++$s;
3✔
78
            $ns -= NANOSECONDS_PER_SECOND;
3✔
79
        } elseif ($s > 0 && $ns < 0) {
200✔
80
            --$s;
9✔
81
            $ns += NANOSECONDS_PER_SECOND;
9✔
82
        }
83

84
        $m = (int) ($s / 60);
201✔
85
        $s %= 60;
201✔
86
        $h = (int) ($m / 60);
201✔
87
        $m %= 60;
201✔
88
        return new self($h, $m, $s, $ns);
201✔
89
    }
90

91
    /**
92
     * Returns an instance representing the specified number of weeks, in hours.
93
     *
94
     * For example, `Duration::weeks(1)` is equivalent to `Duration::hours(168)`.
95
     *
96
     * @pure
97
     */
98
    public static function weeks(int $weeks): self
99
    {
100
        return self::fromParts($weeks * HOURS_PER_WEEK);
1✔
101
    }
102

103
    /**
104
     * Returns an instance representing the specified number of days, in hours.
105
     *
106
     * For example, `Duration::days(2)` is equivalent to `Duration::hours(48)`.
107
     *
108
     * @pure
109
     */
110
    public static function days(int $days): self
111
    {
112
        return self::fromParts($days * HOURS_PER_DAY);
3✔
113
    }
114

115
    /**
116
     * Returns an instance representing the specified number of hours.
117
     *
118
     * @pure
119
     */
120
    public static function hours(int $hours): self
121
    {
122
        return self::fromParts($hours);
6✔
123
    }
124

125
    /**
126
     * Returns an instance representing the specified number of minutes. Due to
127
     * normalization, the actual value in the returned instance may differ from
128
     * the provided one, and the resulting instance may contain larger units.
129
     *
130
     * For example, `Duration::minutes(63)` normalizes to "1 hour(s), 3 minute(s)".
131
     *
132
     * @pure
133
     */
134
    public static function minutes(int $minutes): self
135
    {
136
        return self::fromParts(0, $minutes);
6✔
137
    }
138

139
    /**
140
     * Returns an instance representing the specified number of seconds. Due to
141
     * normalization, the actual value in the returned instance may differ from
142
     * the provided one, and the resulting instance may contain larger units.
143
     *
144
     * For example, `Duration::seconds(63)` normalizes to "1 minute(s), 3 second(s)".
145
     *
146
     * @pure
147
     */
148
    public static function seconds(int $seconds): self
149
    {
150
        return self::fromParts(0, 0, $seconds);
27✔
151
    }
152

153
    /**
154
     * Returns an instance representing the specified number of milliseconds (ms).
155
     * The value is converted and stored as nanoseconds, since that is the only
156
     * unit smaller than a second that we support. Due to normalization, the
157
     * resulting instance may contain larger units.
158
     *
159
     * For example, `Duration::milliseconds(8042)` normalizes to "8 second(s), 42000000 nanosecond(s)".
160
     *
161
     * @pure
162
     */
163
    public static function milliseconds(int $milliseconds): self
164
    {
165
        return self::fromParts(0, 0, 0, NANOSECONDS_PER_MILLISECOND * $milliseconds);
99✔
166
    }
167

168
    /**
169
     * Returns an instance representing the specified number of microseconds (us).
170
     * The value is converted and stored as nanoseconds, since that is the only
171
     * unit smaller than a second that we support. Due to normalization, the
172
     * resulting instance may contain larger units.
173
     *
174
     * For example, `Duration::microseconds(8000042)` normalizes to "8 second(s), 42000 nanosecond(s)".
175
     *
176
     * @pure
177
     */
178
    public static function microseconds(int $microseconds): self
179
    {
180
        return self::fromParts(0, 0, 0, NANOSECONDS_PER_MICROSECOND * $microseconds);
4✔
181
    }
182

183
    /**
184
     * Returns an instance representing the specified number of nanoseconds (ns).
185
     * Due to normalization, the resulting instance may contain larger units.
186
     *
187
     * For example, `Duration::nanoseconds(8000000042)` normalizes to "8 second(s), 42 nanosecond(s)".
188
     *
189
     * @pure
190
     */
191
    public static function nanoseconds(int $nanoseconds): self
192
    {
193
        return self::fromParts(0, 0, 0, $nanoseconds);
6✔
194
    }
195

196
    /**
197
     * Returns an instance with all parts equal to 0.
198
     *
199
     * @pure
200
     */
201
    public static function zero(): self
202
    {
203
        return new self(0, 0, 0, 0);
4✔
204
    }
205

206
    /**
207
     * Compiles and returns the duration's components (hours, minutes, seconds, nanoseconds) in an
208
     * array, in descending order of significance.
209
     *
210
     * @return array{int, int, int, int}
211
     *
212
     * @psalm-mutation-free
213
     */
214
    public function getParts(): array
215
    {
216
        return [$this->hours, $this->minutes, $this->seconds, $this->nanoseconds];
27✔
217
    }
218

219
    /**
220
     * Returns the "hours" part of this time duration.
221
     *
222
     * @psalm-mutation-free
223
     */
224
    public function getHours(): int
225
    {
226
        return $this->hours;
1✔
227
    }
228

229
    /**
230
     * Returns the "minutes" part of this time duration.
231
     *
232
     * @psalm-mutation-free
233
     */
234
    public function getMinutes(): int
235
    {
236
        return $this->minutes;
1✔
237
    }
238

239
    /**
240
     * Returns the "seconds" part of this time duration.
241
     *
242
     * @psalm-mutation-free
243
     */
244
    public function getSeconds(): int
245
    {
246
        return $this->seconds;
2✔
247
    }
248

249
    /**
250
     * Returns the "nanoseconds" part of this time duration.
251
     *
252
     * @psalm-mutation-free
253
     */
254
    public function getNanoseconds(): int
255
    {
256
        return $this->nanoseconds;
3✔
257
    }
258

259
    /**
260
     * Computes, and returns the total duration of the instance in hours as a floating-point number,
261
     * including any fractional parts.
262
     *
263
     * @psalm-mutation-free
264
     */
265
    public function getTotalHours(): float
266
    {
267
        return (
11✔
268
            $this->hours
11✔
269
            + ($this->minutes / MINUTES_PER_HOUR)
11✔
270
            + ($this->seconds / SECONDS_PER_HOUR)
11✔
271
            + ($this->nanoseconds / (SECONDS_PER_HOUR * NANOSECONDS_PER_SECOND))
11✔
272
        );
11✔
273
    }
274

275
    /**
276
     * Computes, and returns the total duration of the instance in minutes as a floating-point number,
277
     * including any fractional parts.
278
     *
279
     * @psalm-mutation-free
280
     */
281
    public function getTotalMinutes(): float
282
    {
283
        return (
9✔
284
            ($this->hours * MINUTES_PER_HOUR)
9✔
285
            + $this->minutes
9✔
286
            + ($this->seconds / SECONDS_PER_MINUTE)
9✔
287
            + ($this->nanoseconds / (SECONDS_PER_MINUTE * NANOSECONDS_PER_SECOND))
9✔
288
        );
9✔
289
    }
290

291
    /**
292
     * Computes, and returns the total duration of the instance in seconds as a floating-point number,
293
     * including any fractional parts.
294
     *
295
     * @psalm-mutation-free
296
     */
297
    public function getTotalSeconds(): float
298
    {
299
        return (
114✔
300
            $this->seconds
114✔
301
            + ($this->minutes * SECONDS_PER_MINUTE)
114✔
302
            + ($this->hours * SECONDS_PER_HOUR)
114✔
303
            + ($this->nanoseconds / NANOSECONDS_PER_SECOND)
114✔
304
        );
114✔
305
    }
306

307
    /**
308
     * Computes, and returns the total duration of the instance in milliseconds as a floating-point number,
309
     * including any fractional parts.
310
     *
311
     * @psalm-mutation-free
312
     */
313
    public function getTotalMilliseconds(): float
314
    {
315
        return (
10✔
316
            ($this->hours * SECONDS_PER_HOUR * MILLISECONDS_PER_SECOND)
10✔
317
            + ($this->minutes * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND)
10✔
318
            + ($this->seconds * MILLISECONDS_PER_SECOND)
10✔
319
            + ($this->nanoseconds / NANOSECONDS_PER_MILLISECOND)
10✔
320
        );
10✔
321
    }
322

323
    /**
324
     * Computes, and returns the total duration of the instance in microseconds as a floating-point number,
325
     * including any fractional parts.
326
     *
327
     * @psalm-mutation-free
328
     */
329
    public function getTotalMicroseconds(): float
330
    {
331
        return (
9✔
332
            ($this->hours * SECONDS_PER_HOUR * MICROSECONDS_PER_SECOND)
9✔
333
            + ($this->minutes * SECONDS_PER_MINUTE * MICROSECONDS_PER_SECOND)
9✔
334
            + ($this->seconds * MICROSECONDS_PER_SECOND)
9✔
335
            + ($this->nanoseconds / NANOSECONDS_PER_MICROSECOND)
9✔
336
        );
9✔
337
    }
338

339
    /**
340
     * Determines whether the instance represents a zero duration.
341
     *
342
     * @psalm-mutation-free
343
     */
344
    public function isZero(): bool
345
    {
346
        return 0 === $this->hours && 0 === $this->minutes && 0 === $this->seconds && 0 === $this->nanoseconds;
6✔
347
    }
348

349
    /**
350
     * Checks if the duration is positive, implying that all non-zero components are positive.
351
     *
352
     * Due to normalization, it is guaranteed that a positive time duration will
353
     * have all of its parts (hours, minutes, seconds, nanoseconds) positive or
354
     * equal to 0.
355
     *
356
     * Note that this method returns false if all parts are equal to 0.
357
     *
358
     * @psalm-mutation-free
359
     */
360
    public function isPositive(): bool
361
    {
362
        return $this->hours > 0 || $this->minutes > 0 || $this->seconds > 0 || $this->nanoseconds > 0;
10✔
363
    }
364

365
    /**
366
     * Checks if the duration is negative, implying that all non-zero components are negative.
367
     *
368
     * Due to normalization, it is guaranteed that a negative time duration will
369
     * have all of its parts (hours, minutes, seconds, nanoseconds) negative or
370
     * equal to 0.
371
     *
372
     * Note that this method returns false if all parts are equal to 0.
373
     *
374
     * @psalm-mutation-free
375
     */
376
    public function isNegative(): bool
377
    {
378
        return $this->hours < 0 || $this->minutes < 0 || $this->seconds < 0 || $this->nanoseconds < 0;
4✔
379
    }
380

381
    /**
382
     * Returns a new instance with the "hours" part changed to the specified
383
     * value.
384
     *
385
     * Note that due to normalization, the actual value in the returned
386
     * instance may differ, and this may affect other parts of the returned
387
     * instance too.
388
     *
389
     * For example, `Duration::hours(2, 30)->withHours(-1)` is equivalent to
390
     * `Duration::hours(-1, 30)` which normalizes to "-30 minute(s)".
391
     *
392
     * @psalm-mutation-free
393
     */
394
    public function withHours(int $hours): self
395
    {
396
        return self::fromParts($hours, $this->minutes, $this->seconds, $this->nanoseconds);
1✔
397
    }
398

399
    /**
400
     * Returns a new instance with the "minutes" part changed to the specified
401
     * value.
402
     *
403
     * Note that due to normalization, the actual value in the returned
404
     * instance may differ, and this may affect other parts of the returned
405
     * instance too.
406
     *
407
     * For example, `Duration::minutes(2, 30)->withMinutes(-1)` is equivalent to
408
     * `Duration::minutes(-1, 30)` which normalizes to "-30 second(s)".
409
     *
410
     * @psalm-mutation-free
411
     */
412
    public function withMinutes(int $minutes): self
413
    {
414
        return self::fromParts($this->hours, $minutes, $this->seconds, $this->nanoseconds);
1✔
415
    }
416

417
    /**
418
     * Returns a new instance with the "seconds" part changed to the specified
419
     * value.
420
     *
421
     * Note that due to normalization, the actual value in the returned
422
     * instance may differ, and this may affect other parts of the returned
423
     * instance too.
424
     *
425
     * For example, `Duration::minutes(2, 30)->withSeconds(-30)` is equivalent
426
     * to `Duration::minutes(2, -30)` which normalizes to "1 minute(s), 30 second(s)".
427
     *
428
     * @psalm-mutation-free
429
     */
430
    public function withSeconds(int $seconds): self
431
    {
432
        return self::fromParts($this->hours, $this->minutes, $seconds, $this->nanoseconds);
1✔
433
    }
434

435
    /**
436
     * Returns a new instance with the "nanoseconds" part changed to the specified
437
     * value.
438
     *
439
     * Note that due to normalization, the actual value in the returned
440
     * instance may differ, and this may affect other parts of the returned
441
     * instance too.
442
     *
443
     * For example, `Duration::seconds(2)->withNanoseconds(-1)` is equivalent
444
     * to `Duration::seconds(2, -1)` which normalizes to "1 second(s), 999999999 nanosecond(s)".
445
     *
446
     * @psalm-mutation-free
447
     */
448
    public function withNanoseconds(int $nanoseconds): self
449
    {
450
        return self::fromParts($this->hours, $this->minutes, $this->seconds, $nanoseconds);
1✔
451
    }
452

453
    /**
454
     * Implements a comparison between this duration and another, based on their duration.
455
     *
456
     * @param Duration $other
457
     *
458
     * @psalm-mutation-free
459
     */
460
    #[\Override]
461
    public function compare(mixed $other): Comparison\Order
462
    {
463
        if ($this->hours !== $other->hours) {
7✔
464
            return Comparison\Order::from($this->hours <=> $other->hours);
1✔
465
        }
466

467
        if ($this->minutes !== $other->minutes) {
7✔
468
            return Comparison\Order::from($this->minutes <=> $other->minutes);
1✔
469
        }
470

471
        if ($this->seconds !== $other->seconds) {
6✔
472
            return Comparison\Order::from($this->seconds <=> $other->seconds);
2✔
473
        }
474

475
        return Comparison\Order::from($this->nanoseconds <=> $other->nanoseconds);
6✔
476
    }
477

478
    /**
479
     * Evaluates whether this duration is equivalent to another, considering all time components.
480
     *
481
     * @param Duration $other
482
     *
483
     * @psalm-mutation-free
484
     */
485
    #[\Override]
486
    public function equals(mixed $other): bool
487
    {
488
        return $this->compare($other) === Comparison\Order::Equal;
6✔
489
    }
490

491
    /**
492
     * Determines if this duration is shorter than another.
493
     *
494
     * @psalm-mutation-free
495
     */
496
    public function shorter(self $other): bool
497
    {
498
        return $this->compare($other) === Comparison\Order::Less;
6✔
499
    }
500

501
    /**
502
     * Determines if this duration is shorter than, or equivalent to another.
503
     *
504
     * @psalm-mutation-free
505
     */
506
    public function shorterOrEqual(self $other): bool
507
    {
508
        return $this->compare($other) !== Comparison\Order::Greater;
6✔
509
    }
510

511
    /**
512
     * Determines if this duration is longer than another.
513
     *
514
     * @psalm-mutation-free
515
     */
516
    public function longer(self $other): bool
517
    {
518
        return $this->compare($other) === Comparison\Order::Greater;
6✔
519
    }
520

521
    /**
522
     * Determines if this duration is longer than, or equivalent to another.
523
     *
524
     * @psalm-mutation-free
525
     */
526
    public function longerOrEqual(self $other): bool
527
    {
528
        return $this->compare($other) !== Comparison\Order::Less;
6✔
529
    }
530

531
    /**
532
     * Returns true if this instance represents a time duration longer than $a but
533
     * shorter than $b, or vice-versa (shorter than $a but longer than $b), or if
534
     * this instance is equal to $a and/or $b. Returns false if this instance is
535
     * shorter/longer than both.
536
     *
537
     * @psalm-mutation-free
538
     */
539
    public function betweenInclusive(self $a, self $b): bool
540
    {
541
        $ca = $this->compare($a);
7✔
542
        $cb = $this->compare($b);
7✔
543

544
        return $ca === Comparison\Order::Equal || $ca !== $cb;
7✔
545
    }
546

547
    /**
548
     * Returns true if this instance represents a time duration longer than $a but
549
     * shorter than $b, or vice-versa (shorter than $a but longer than $b).
550
     * Returns false if this instance is equal to $a and/or $b, or shorter/longer
551
     * than both.
552
     *
553
     * @psalm-mutation-free
554
     */
555
    public function betweenExclusive(self $a, self $b): bool
556
    {
557
        $ca = $this->compare($a);
7✔
558
        $cb = $this->compare($b);
7✔
559

560
        return $ca !== Comparison\Order::Equal && $cb !== Comparison\Order::Equal && $ca !== $cb;
7✔
561
    }
562

563
    /**
564
     * Returns a new instance, converting a positive/negative duration to the
565
     * opposite (negative/positive) duration of equal length. The resulting
566
     * instance has all parts equivalent to the current instance's parts
567
     * multiplied by -1.
568
     *
569
     * @psalm-mutation-free
570
     */
571
    public function invert(): self
572
    {
573
        if ($this->isZero()) {
1✔
574
            return $this;
1✔
575
        }
576

577
        return new self(-$this->hours, -$this->minutes, -$this->seconds, -$this->nanoseconds);
1✔
578
    }
579

580
    /**
581
     * Returns a new instance representing the sum of this instance and the
582
     * provided `$other` instance. Note that time duration can be negative, so
583
     * the resulting instance is not guaranteed to be shorter/longer than either
584
     * of the inputs.
585
     *
586
     * This operation is commutative: `$a->plus($b) === $b->plus($a)`
587
     *
588
     * @psalm-mutation-free
589
     */
590
    public function plus(self $other): self
591
    {
592
        if ($other->isZero()) {
1✔
593
            return $this;
1✔
594
        }
595

596
        if ($this->isZero()) {
1✔
597
            return $other;
1✔
598
        }
599

600
        return self::fromParts(
1✔
601
            $this->hours + $other->hours,
1✔
602
            $this->minutes + $other->minutes,
1✔
603
            $this->seconds + $other->seconds,
1✔
604
            $this->nanoseconds + $other->nanoseconds,
1✔
605
        );
1✔
606
    }
607

608
    /**
609
     * Returns a new instance representing the difference between this instance
610
     * and the provided `$other` instance (i.e. `$other` subtracted from `$this`).
611
     * Note that time duration can be negative, so the resulting instance is not
612
     * guaranteed to be shorter/longer than either of the inputs.
613
     *
614
     * This operation is not commutative: `$a->minus($b) !== $b->minus($a)`
615
     * But: `$a->minus($b) === $b->minus($a)->invert()`
616
     *
617
     * @psalm-mutation-free
618
     */
619
    public function minus(self $other): self
620
    {
621
        if ($other->isZero()) {
1✔
622
            return $this;
1✔
623
        }
624

625
        if ($this->isZero()) {
1✔
626
            return $other->invert();
1✔
627
        }
628

629
        return self::fromParts(
1✔
630
            $this->hours - $other->hours,
1✔
631
            $this->minutes - $other->minutes,
1✔
632
            $this->seconds - $other->seconds,
1✔
633
            $this->nanoseconds - $other->nanoseconds,
1✔
634
        );
1✔
635
    }
636

637
    /**
638
     * Returns the time duration as string, useful e.g. for debugging. This is not
639
     * meant to be a comprehensive way to format time durations for user-facing
640
     * output.
641
     *
642
     * @param int<0, max> $max_decimals
643
     *
644
     * @psalm-mutation-free
645
     */
646
    public function toString(int $max_decimals = 3): string
647
    {
648
        $decimal_part = '';
15✔
649
        if ($max_decimals > 0) {
15✔
650
            $decimal_part = (string) Math\abs($this->nanoseconds);
15✔
651
            $decimal_part = Str\pad_left($decimal_part, 9, '0');
15✔
652
            $decimal_part = Str\slice($decimal_part, 0, $max_decimals);
15✔
653
            $decimal_part = Str\trim_right($decimal_part, '0');
15✔
654
        }
655

656
        if ('' !== $decimal_part) {
15✔
657
            $decimal_part = '.' . $decimal_part;
4✔
658
        }
659

660
        $sec_sign = $this->seconds < 0 || $this->nanoseconds < 0 ? '-' : '';
15✔
661
        $sec = Math\abs($this->seconds);
15✔
662

663
        $containsHours = 0 !== $this->hours;
15✔
664
        $containsMinutes = 0 !== $this->minutes;
15✔
665
        $concatenatedSeconds = $sec_sign . (string) $sec . $decimal_part;
15✔
666
        $containsSeconds = '0' !== $concatenatedSeconds;
15✔
667

668
        /** @var list<string> $output */
669
        $output = [];
15✔
670
        if ($containsHours) {
15✔
671
            $output[] = (string) $this->hours . ' hour(s)';
7✔
672
        }
673

674
        if ($containsMinutes || $containsHours && $containsSeconds) {
15✔
675
            $output[] = (string) $this->minutes . ' minute(s)';
8✔
676
        }
677

678
        if ($containsSeconds) {
15✔
679
            $output[] = $concatenatedSeconds . ' second(s)';
10✔
680
        }
681

682
        return [] === $output ? '0 second(s)' : Str\join($output, ', ');
15✔
683
    }
684

685
    /**
686
     * Returns a string representation of the time duration.
687
     *
688
     * @psalm-mutation-free
689
     */
690
    #[\Override]
691
    public function __toString(): string
692
    {
UNCOV
693
        return $this->toString();
×
694
    }
695

696
    /**
697
     * Converts this {@see Duration} to a PHP {@see DateInterval}.
698
     *
699
     * Note: nanosecond precision is truncated to microseconds.
700
     *
701
     * @return DateInterval
702
     *
703
     * @psalm-mutation-free
704
     */
705
    #[\Override]
706
    public function toStdlib(): mixed
707
    {
708
        $total_seconds = (int) $this->getTotalSeconds();
3✔
709

710
        return DateInterval::createFromDateString($total_seconds . ' seconds');
3✔
711
    }
712

713
    /**
714
     * Returns data which can be serialized by json_encode().
715
     *
716
     * @return array{hours: int, minutes: int, seconds: int, nanoseconds: int}
717
     *
718
     * @psalm-mutation-free
719
     */
720
    #[\Override]
721
    public function jsonSerialize(): array
722
    {
723
        return [
1✔
724
            'hours' => $this->hours,
1✔
725
            'minutes' => $this->minutes,
1✔
726
            'seconds' => $this->seconds,
1✔
727
            'nanoseconds' => $this->nanoseconds,
1✔
728
        ];
1✔
729
    }
730
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc