Completed
Branch develop (eb876f)
by
unknown
21:14
created
webklex/php-imap/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php 1 patch
Indentation   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -24,55 +24,55 @@
 block discarded – undo
24 24
  */
25 25
 final class MacroExtension implements MethodsClassReflectionExtension
26 26
 {
27
-    /**
28
-     * @var PhpMethodReflectionFactory
29
-     */
30
-    protected $methodReflectionFactory;
27
+	/**
28
+	 * @var PhpMethodReflectionFactory
29
+	 */
30
+	protected $methodReflectionFactory;
31 31
 
32
-    /**
33
-     * @var MacroScanner
34
-     */
35
-    protected $scanner;
32
+	/**
33
+	 * @var MacroScanner
34
+	 */
35
+	protected $scanner;
36 36
 
37
-    /**
38
-     * Extension constructor.
39
-     *
40
-     * @param PhpMethodReflectionFactory $methodReflectionFactory
41
-     */
42
-    public function __construct(PhpMethodReflectionFactory $methodReflectionFactory)
43
-    {
44
-        $this->scanner = new MacroScanner();
45
-        $this->methodReflectionFactory = $methodReflectionFactory;
46
-    }
37
+	/**
38
+	 * Extension constructor.
39
+	 *
40
+	 * @param PhpMethodReflectionFactory $methodReflectionFactory
41
+	 */
42
+	public function __construct(PhpMethodReflectionFactory $methodReflectionFactory)
43
+	{
44
+		$this->scanner = new MacroScanner();
45
+		$this->methodReflectionFactory = $methodReflectionFactory;
46
+	}
47 47
 
48
-    /**
49
-     * {@inheritdoc}
50
-     */
51
-    public function hasMethod(ClassReflection $classReflection, string $methodName): bool
52
-    {
53
-        return $this->scanner->hasMethod($classReflection->getName(), $methodName);
54
-    }
48
+	/**
49
+	 * {@inheritdoc}
50
+	 */
51
+	public function hasMethod(ClassReflection $classReflection, string $methodName): bool
52
+	{
53
+		return $this->scanner->hasMethod($classReflection->getName(), $methodName);
54
+	}
55 55
 
56
-    /**
57
-     * {@inheritdoc}
58
-     */
59
-    public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
60
-    {
61
-        $builtinMacro = $this->scanner->getMethod($classReflection->getName(), $methodName);
56
+	/**
57
+	 * {@inheritdoc}
58
+	 */
59
+	public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
60
+	{
61
+		$builtinMacro = $this->scanner->getMethod($classReflection->getName(), $methodName);
62 62
 
63
-        return $this->methodReflectionFactory->create(
64
-            $classReflection,
65
-            null,
66
-            $builtinMacro,
67
-            $classReflection->getActiveTemplateTypeMap(),
68
-            [],
69
-            TypehintHelper::decideTypeFromReflection($builtinMacro->getReturnType()),
70
-            null,
71
-            null,
72
-            $builtinMacro->isDeprecated()->yes(),
73
-            $builtinMacro->isInternal(),
74
-            $builtinMacro->isFinal(),
75
-            $builtinMacro->getDocComment()
76
-        );
77
-    }
63
+		return $this->methodReflectionFactory->create(
64
+			$classReflection,
65
+			null,
66
+			$builtinMacro,
67
+			$classReflection->getActiveTemplateTypeMap(),
68
+			[],
69
+			TypehintHelper::decideTypeFromReflection($builtinMacro->getReturnType()),
70
+			null,
71
+			null,
72
+			$builtinMacro->isDeprecated()->yes(),
73
+			$builtinMacro->isInternal(),
74
+			$builtinMacro->isFinal(),
75
+			$builtinMacro->getDocComment()
76
+		);
77
+	}
78 78
 }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php 2 patches
Indentation   +2582 added lines, -2582 removed lines patch added patch discarded remove patch
@@ -182,2598 +182,2598 @@
 block discarded – undo
182 182
  */
183 183
 class CarbonInterval extends DateInterval implements CarbonConverterInterface
184 184
 {
185
-    use IntervalRounding;
186
-    use IntervalStep;
187
-    use Mixin {
188
-        Mixin::mixin as baseMixin;
189
-    }
190
-    use Options;
191
-
192
-    /**
193
-     * Interval spec period designators
194
-     */
195
-    public const PERIOD_PREFIX = 'P';
196
-    public const PERIOD_YEARS = 'Y';
197
-    public const PERIOD_MONTHS = 'M';
198
-    public const PERIOD_DAYS = 'D';
199
-    public const PERIOD_TIME_PREFIX = 'T';
200
-    public const PERIOD_HOURS = 'H';
201
-    public const PERIOD_MINUTES = 'M';
202
-    public const PERIOD_SECONDS = 'S';
203
-
204
-    /**
205
-     * A translator to ... er ... translate stuff
206
-     *
207
-     * @var \Symfony\Component\Translation\TranslatorInterface
208
-     */
209
-    protected static $translator;
210
-
211
-    /**
212
-     * @var array|null
213
-     */
214
-    protected static $cascadeFactors;
215
-
216
-    /**
217
-     * @var array
218
-     */
219
-    protected static $formats = [
220
-        'y' => 'y',
221
-        'Y' => 'y',
222
-        'o' => 'y',
223
-        'm' => 'm',
224
-        'n' => 'm',
225
-        'W' => 'weeks',
226
-        'd' => 'd',
227
-        'j' => 'd',
228
-        'z' => 'd',
229
-        'h' => 'h',
230
-        'g' => 'h',
231
-        'H' => 'h',
232
-        'G' => 'h',
233
-        'i' => 'i',
234
-        's' => 's',
235
-        'u' => 'micro',
236
-        'v' => 'milli',
237
-    ];
238
-
239
-    /**
240
-     * @var array|null
241
-     */
242
-    private static $flipCascadeFactors;
243
-
244
-    /**
245
-     * The registered macros.
246
-     *
247
-     * @var array
248
-     */
249
-    protected static $macros = [];
250
-
251
-    /**
252
-     * Timezone handler for settings() method.
253
-     *
254
-     * @var mixed
255
-     */
256
-    protected $tzName;
257
-
258
-    /**
259
-     * Set the instance's timezone from a string or object.
260
-     *
261
-     * @param \DateTimeZone|string $tzName
262
-     *
263
-     * @return static
264
-     */
265
-    public function setTimezone($tzName)
266
-    {
267
-        $this->tzName = $tzName;
268
-
269
-        return $this;
270
-    }
271
-
272
-    /**
273
-     * @internal
274
-     *
275
-     * Set the instance's timezone from a string or object and add/subtract the offset difference.
276
-     *
277
-     * @param \DateTimeZone|string $tzName
278
-     *
279
-     * @return static
280
-     */
281
-    public function shiftTimezone($tzName)
282
-    {
283
-        $this->tzName = $tzName;
284
-
285
-        return $this;
286
-    }
287
-
288
-    /**
289
-     * Mapping of units and factors for cascading.
290
-     *
291
-     * Should only be modified by changing the factors or referenced constants.
292
-     *
293
-     * @return array
294
-     */
295
-    public static function getCascadeFactors()
296
-    {
297
-        return static::$cascadeFactors ?: [
298
-            'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
299
-            'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
300
-            'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
301
-            'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
302
-            'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
303
-            'weeks' => [Carbon::DAYS_PER_WEEK, 'dayz'],
304
-            'months' => [Carbon::WEEKS_PER_MONTH, 'weeks'],
305
-            'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
306
-        ];
307
-    }
308
-
309
-    private static function standardizeUnit($unit)
310
-    {
311
-        $unit = rtrim($unit, 'sz').'s';
312
-
313
-        return $unit === 'days' ? 'dayz' : $unit;
314
-    }
315
-
316
-    private static function getFlipCascadeFactors()
317
-    {
318
-        if (!self::$flipCascadeFactors) {
319
-            self::$flipCascadeFactors = [];
320
-
321
-            foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
322
-                self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
323
-            }
324
-        }
325
-
326
-        return self::$flipCascadeFactors;
327
-    }
328
-
329
-    /**
330
-     * Set default cascading factors for ->cascade() method.
331
-     *
332
-     * @param array $cascadeFactors
333
-     */
334
-    public static function setCascadeFactors(array $cascadeFactors)
335
-    {
336
-        self::$flipCascadeFactors = null;
337
-        static::$cascadeFactors = $cascadeFactors;
338
-    }
339
-
340
-    ///////////////////////////////////////////////////////////////////
341
-    //////////////////////////// CONSTRUCTORS /////////////////////////
342
-    ///////////////////////////////////////////////////////////////////
343
-
344
-    /**
345
-     * Create a new CarbonInterval instance.
346
-     *
347
-     * @param Closure|DateInterval|string|int|null $years
348
-     * @param int|null                             $months
349
-     * @param int|null                             $weeks
350
-     * @param int|null                             $days
351
-     * @param int|null                             $hours
352
-     * @param int|null                             $minutes
353
-     * @param int|null                             $seconds
354
-     * @param int|null                             $microseconds
355
-     *
356
-     * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
357
-     */
358
-    public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
359
-    {
360
-        if ($years instanceof Closure) {
361
-            $this->step = $years;
362
-            $years = null;
363
-        }
364
-
365
-        if ($years instanceof DateInterval) {
366
-            parent::__construct(static::getDateIntervalSpec($years));
367
-            $this->f = $years->f;
368
-            self::copyNegativeUnits($years, $this);
369
-
370
-            return;
371
-        }
372
-
373
-        $spec = $years;
374
-
375
-        if (!\is_string($spec) || (float) $years || preg_match('/^[\d.]/', $years)) {
376
-            $spec = static::PERIOD_PREFIX;
377
-
378
-            $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
379
-            $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
380
-
381
-            $specDays = 0;
382
-            $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
383
-            $specDays += $days > 0 ? $days : 0;
384
-
385
-            $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
386
-
387
-            if ($hours > 0 || $minutes > 0 || $seconds > 0) {
388
-                $spec .= static::PERIOD_TIME_PREFIX;
389
-                $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
390
-                $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
391
-                $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
392
-            }
393
-
394
-            if ($spec === static::PERIOD_PREFIX) {
395
-                // Allow the zero interval.
396
-                $spec .= '0'.static::PERIOD_YEARS;
397
-            }
398
-        }
399
-
400
-        parent::__construct($spec);
401
-
402
-        if ($microseconds !== null) {
403
-            $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
404
-        }
405
-    }
406
-
407
-    /**
408
-     * Returns the factor for a given source-to-target couple.
409
-     *
410
-     * @param string $source
411
-     * @param string $target
412
-     *
413
-     * @return int|null
414
-     */
415
-    public static function getFactor($source, $target)
416
-    {
417
-        $source = self::standardizeUnit($source);
418
-        $target = self::standardizeUnit($target);
419
-        $factors = self::getFlipCascadeFactors();
420
-
421
-        if (isset($factors[$source])) {
422
-            [$to, $factor] = $factors[$source];
423
-
424
-            if ($to === $target) {
425
-                return $factor;
426
-            }
427
-
428
-            return $factor * static::getFactor($to, $target);
429
-        }
430
-
431
-        return null;
432
-    }
433
-
434
-    /**
435
-     * Returns the factor for a given source-to-target couple if set,
436
-     * else try to find the appropriate constant as the factor, such as Carbon::DAYS_PER_WEEK.
437
-     *
438
-     * @param string $source
439
-     * @param string $target
440
-     *
441
-     * @return int|null
442
-     */
443
-    public static function getFactorWithDefault($source, $target)
444
-    {
445
-        $factor = self::getFactor($source, $target);
446
-
447
-        if ($factor) {
448
-            return $factor;
449
-        }
450
-
451
-        static $defaults = [
452
-            'month' => ['year' => Carbon::MONTHS_PER_YEAR],
453
-            'week' => ['month' => Carbon::WEEKS_PER_MONTH],
454
-            'day' => ['week' => Carbon::DAYS_PER_WEEK],
455
-            'hour' => ['day' => Carbon::HOURS_PER_DAY],
456
-            'minute' => ['hour' => Carbon::MINUTES_PER_HOUR],
457
-            'second' => ['minute' => Carbon::SECONDS_PER_MINUTE],
458
-            'millisecond' => ['second' => Carbon::MILLISECONDS_PER_SECOND],
459
-            'microsecond' => ['millisecond' => Carbon::MICROSECONDS_PER_MILLISECOND],
460
-        ];
461
-
462
-        return $defaults[$source][$target] ?? null;
463
-    }
464
-
465
-    /**
466
-     * Returns current config for days per week.
467
-     *
468
-     * @return int
469
-     */
470
-    public static function getDaysPerWeek()
471
-    {
472
-        return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
473
-    }
474
-
475
-    /**
476
-     * Returns current config for hours per day.
477
-     *
478
-     * @return int
479
-     */
480
-    public static function getHoursPerDay()
481
-    {
482
-        return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
483
-    }
484
-
485
-    /**
486
-     * Returns current config for minutes per hour.
487
-     *
488
-     * @return int
489
-     */
490
-    public static function getMinutesPerHour()
491
-    {
492
-        return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
493
-    }
494
-
495
-    /**
496
-     * Returns current config for seconds per minute.
497
-     *
498
-     * @return int
499
-     */
500
-    public static function getSecondsPerMinute()
501
-    {
502
-        return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
503
-    }
504
-
505
-    /**
506
-     * Returns current config for microseconds per second.
507
-     *
508
-     * @return int
509
-     */
510
-    public static function getMillisecondsPerSecond()
511
-    {
512
-        return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
513
-    }
514
-
515
-    /**
516
-     * Returns current config for microseconds per second.
517
-     *
518
-     * @return int
519
-     */
520
-    public static function getMicrosecondsPerMillisecond()
521
-    {
522
-        return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
523
-    }
524
-
525
-    /**
526
-     * Create a new CarbonInterval instance from specific values.
527
-     * This is an alias for the constructor that allows better fluent
528
-     * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
529
-     * (new CarbonInterval(1))->fn().
530
-     *
531
-     * @param int $years
532
-     * @param int $months
533
-     * @param int $weeks
534
-     * @param int $days
535
-     * @param int $hours
536
-     * @param int $minutes
537
-     * @param int $seconds
538
-     * @param int $microseconds
539
-     *
540
-     * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
541
-     *
542
-     * @return static
543
-     */
544
-    public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
545
-    {
546
-        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
547
-    }
548
-
549
-    /**
550
-     * Parse a string into a new CarbonInterval object according to the specified format.
551
-     *
552
-     * @example
553
-     * ```
554
-     * echo Carboninterval::createFromFormat('H:i', '1:30');
555
-     * ```
556
-     *
557
-     * @param string      $format   Format of the $interval input string
558
-     * @param string|null $interval Input string to convert into an interval
559
-     *
560
-     * @throws \Carbon\Exceptions\ParseErrorException when the $interval cannot be parsed as an interval.
561
-     *
562
-     * @return static
563
-     */
564
-    public static function createFromFormat(string $format, ?string $interval)
565
-    {
566
-        $instance = new static(0);
567
-        $length = mb_strlen($format);
568
-
569
-        if (preg_match('/s([,.])([uv])$/', $format, $match)) {
570
-            $interval = explode($match[1], $interval);
571
-            $index = \count($interval) - 1;
572
-            $interval[$index] = str_pad($interval[$index], $match[2] === 'v' ? 3 : 6, '0');
573
-            $interval = implode($match[1], $interval);
574
-        }
575
-
576
-        $interval = $interval ?? '';
577
-
578
-        for ($index = 0; $index < $length; $index++) {
579
-            $expected = mb_substr($format, $index, 1);
580
-            $nextCharacter = mb_substr($interval, 0, 1);
581
-            $unit = static::$formats[$expected] ?? null;
582
-
583
-            if ($unit) {
584
-                if (!preg_match('/^-?\d+/', $interval, $match)) {
585
-                    throw new ParseErrorException('number', $nextCharacter);
586
-                }
587
-
588
-                $interval = mb_substr($interval, mb_strlen($match[0]));
589
-                $instance->$unit += (int) ($match[0]);
590
-
591
-                continue;
592
-            }
593
-
594
-            if ($nextCharacter !== $expected) {
595
-                throw new ParseErrorException(
596
-                    "'$expected'",
597
-                    $nextCharacter,
598
-                    'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
599
-                    'See https://php.net/manual/en/function.date.php for their meaning'
600
-                );
601
-            }
602
-
603
-            $interval = mb_substr($interval, 1);
604
-        }
605
-
606
-        if ($interval !== '') {
607
-            throw new ParseErrorException(
608
-                'end of string',
609
-                $interval
610
-            );
611
-        }
612
-
613
-        return $instance;
614
-    }
615
-
616
-    /**
617
-     * Get a copy of the instance.
618
-     *
619
-     * @return static
620
-     */
621
-    public function copy()
622
-    {
623
-        $date = new static(0);
624
-        $date->copyProperties($this);
625
-        $date->step = $this->step;
626
-
627
-        return $date;
628
-    }
629
-
630
-    /**
631
-     * Get a copy of the instance.
632
-     *
633
-     * @return static
634
-     */
635
-    public function clone()
636
-    {
637
-        return $this->copy();
638
-    }
639
-
640
-    /**
641
-     * Provide static helpers to create instances.  Allows CarbonInterval::years(3).
642
-     *
643
-     * Note: This is done using the magic method to allow static and instance methods to
644
-     *       have the same names.
645
-     *
646
-     * @param string $method     magic method name called
647
-     * @param array  $parameters parameters list
648
-     *
649
-     * @return static|null
650
-     */
651
-    public static function __callStatic($method, $parameters)
652
-    {
653
-        try {
654
-            $interval = new static(0);
655
-            $localStrictModeEnabled = $interval->localStrictModeEnabled;
656
-            $interval->localStrictModeEnabled = true;
657
-
658
-            $result = static::hasMacro($method)
659
-                ? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) {
660
-                    return $interval->callMacro($method, $parameters);
661
-                })
662
-                : $interval->$method(...$parameters);
663
-
664
-            $interval->localStrictModeEnabled = $localStrictModeEnabled;
665
-
666
-            return $result;
667
-        } catch (BadFluentSetterException $exception) {
668
-            if (Carbon::isStrictModeEnabled()) {
669
-                throw new BadFluentConstructorException($method, 0, $exception);
670
-            }
671
-
672
-            return null;
673
-        }
674
-    }
675
-
676
-    /**
677
-     * Return the current context from inside a macro callee or a new one if static.
678
-     *
679
-     * @return static
680
-     */
681
-    protected static function this()
682
-    {
683
-        return end(static::$macroContextStack) ?: new static(0);
684
-    }
685
-
686
-    /**
687
-     * Creates a CarbonInterval from string.
688
-     *
689
-     * Format:
690
-     *
691
-     * Suffix | Unit    | Example | DateInterval expression
692
-     * -------|---------|---------|------------------------
693
-     * y      | years   |   1y    | P1Y
694
-     * mo     | months  |   3mo   | P3M
695
-     * w      | weeks   |   2w    | P2W
696
-     * d      | days    |  28d    | P28D
697
-     * h      | hours   |   4h    | PT4H
698
-     * m      | minutes |  12m    | PT12M
699
-     * s      | seconds |  59s    | PT59S
700
-     *
701
-     * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
702
-     *
703
-     * Special cases:
704
-     *  - An empty string will return a zero interval
705
-     *  - Fractions are allowed for weeks, days, hours and minutes and will be converted
706
-     *    and rounded to the next smaller value (caution: 0.5w = 4d)
707
-     *
708
-     * @param string $intervalDefinition
709
-     *
710
-     * @return static
711
-     */
712
-    public static function fromString($intervalDefinition)
713
-    {
714
-        if (empty($intervalDefinition)) {
715
-            return new static(0);
716
-        }
717
-
718
-        $years = 0;
719
-        $months = 0;
720
-        $weeks = 0;
721
-        $days = 0;
722
-        $hours = 0;
723
-        $minutes = 0;
724
-        $seconds = 0;
725
-        $milliseconds = 0;
726
-        $microseconds = 0;
727
-
728
-        $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
729
-        preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
730
-
731
-        while ([$part, $value, $unit] = array_shift($parts)) {
732
-            $intValue = (int) $value;
733
-            $fraction = (float) $value - $intValue;
734
-
735
-            // Fix calculation precision
736
-            switch (round($fraction, 6)) {
737
-                case 1:
738
-                    $fraction = 0;
739
-                    $intValue++;
740
-
741
-                    break;
742
-                case 0:
743
-                    $fraction = 0;
744
-
745
-                    break;
746
-            }
747
-
748
-            switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
749
-                case 'millennia':
750
-                case 'millennium':
751
-                    $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
752
-
753
-                    break;
754
-
755
-                case 'century':
756
-                case 'centuries':
757
-                    $years += $intValue * CarbonInterface::YEARS_PER_CENTURY;
758
-
759
-                    break;
760
-
761
-                case 'decade':
762
-                case 'decades':
763
-                    $years += $intValue * CarbonInterface::YEARS_PER_DECADE;
764
-
765
-                    break;
766
-
767
-                case 'year':
768
-                case 'years':
769
-                case 'y':
770
-                    $years += $intValue;
771
-
772
-                    break;
773
-
774
-                case 'quarter':
775
-                case 'quarters':
776
-                    $months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;
777
-
778
-                    break;
779
-
780
-                case 'month':
781
-                case 'months':
782
-                case 'mo':
783
-                    $months += $intValue;
784
-
785
-                    break;
786
-
787
-                case 'week':
788
-                case 'weeks':
789
-                case 'w':
790
-                    $weeks += $intValue;
791
-
792
-                    if ($fraction) {
793
-                        $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
794
-                    }
795
-
796
-                    break;
797
-
798
-                case 'day':
799
-                case 'days':
800
-                case 'd':
801
-                    $days += $intValue;
802
-
803
-                    if ($fraction) {
804
-                        $parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
805
-                    }
806
-
807
-                    break;
808
-
809
-                case 'hour':
810
-                case 'hours':
811
-                case 'h':
812
-                    $hours += $intValue;
185
+	use IntervalRounding;
186
+	use IntervalStep;
187
+	use Mixin {
188
+		Mixin::mixin as baseMixin;
189
+	}
190
+	use Options;
191
+
192
+	/**
193
+	 * Interval spec period designators
194
+	 */
195
+	public const PERIOD_PREFIX = 'P';
196
+	public const PERIOD_YEARS = 'Y';
197
+	public const PERIOD_MONTHS = 'M';
198
+	public const PERIOD_DAYS = 'D';
199
+	public const PERIOD_TIME_PREFIX = 'T';
200
+	public const PERIOD_HOURS = 'H';
201
+	public const PERIOD_MINUTES = 'M';
202
+	public const PERIOD_SECONDS = 'S';
203
+
204
+	/**
205
+	 * A translator to ... er ... translate stuff
206
+	 *
207
+	 * @var \Symfony\Component\Translation\TranslatorInterface
208
+	 */
209
+	protected static $translator;
210
+
211
+	/**
212
+	 * @var array|null
213
+	 */
214
+	protected static $cascadeFactors;
215
+
216
+	/**
217
+	 * @var array
218
+	 */
219
+	protected static $formats = [
220
+		'y' => 'y',
221
+		'Y' => 'y',
222
+		'o' => 'y',
223
+		'm' => 'm',
224
+		'n' => 'm',
225
+		'W' => 'weeks',
226
+		'd' => 'd',
227
+		'j' => 'd',
228
+		'z' => 'd',
229
+		'h' => 'h',
230
+		'g' => 'h',
231
+		'H' => 'h',
232
+		'G' => 'h',
233
+		'i' => 'i',
234
+		's' => 's',
235
+		'u' => 'micro',
236
+		'v' => 'milli',
237
+	];
238
+
239
+	/**
240
+	 * @var array|null
241
+	 */
242
+	private static $flipCascadeFactors;
243
+
244
+	/**
245
+	 * The registered macros.
246
+	 *
247
+	 * @var array
248
+	 */
249
+	protected static $macros = [];
250
+
251
+	/**
252
+	 * Timezone handler for settings() method.
253
+	 *
254
+	 * @var mixed
255
+	 */
256
+	protected $tzName;
257
+
258
+	/**
259
+	 * Set the instance's timezone from a string or object.
260
+	 *
261
+	 * @param \DateTimeZone|string $tzName
262
+	 *
263
+	 * @return static
264
+	 */
265
+	public function setTimezone($tzName)
266
+	{
267
+		$this->tzName = $tzName;
268
+
269
+		return $this;
270
+	}
271
+
272
+	/**
273
+	 * @internal
274
+	 *
275
+	 * Set the instance's timezone from a string or object and add/subtract the offset difference.
276
+	 *
277
+	 * @param \DateTimeZone|string $tzName
278
+	 *
279
+	 * @return static
280
+	 */
281
+	public function shiftTimezone($tzName)
282
+	{
283
+		$this->tzName = $tzName;
284
+
285
+		return $this;
286
+	}
287
+
288
+	/**
289
+	 * Mapping of units and factors for cascading.
290
+	 *
291
+	 * Should only be modified by changing the factors or referenced constants.
292
+	 *
293
+	 * @return array
294
+	 */
295
+	public static function getCascadeFactors()
296
+	{
297
+		return static::$cascadeFactors ?: [
298
+			'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
299
+			'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
300
+			'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
301
+			'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
302
+			'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
303
+			'weeks' => [Carbon::DAYS_PER_WEEK, 'dayz'],
304
+			'months' => [Carbon::WEEKS_PER_MONTH, 'weeks'],
305
+			'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
306
+		];
307
+	}
308
+
309
+	private static function standardizeUnit($unit)
310
+	{
311
+		$unit = rtrim($unit, 'sz').'s';
312
+
313
+		return $unit === 'days' ? 'dayz' : $unit;
314
+	}
315
+
316
+	private static function getFlipCascadeFactors()
317
+	{
318
+		if (!self::$flipCascadeFactors) {
319
+			self::$flipCascadeFactors = [];
320
+
321
+			foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
322
+				self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
323
+			}
324
+		}
325
+
326
+		return self::$flipCascadeFactors;
327
+	}
328
+
329
+	/**
330
+	 * Set default cascading factors for ->cascade() method.
331
+	 *
332
+	 * @param array $cascadeFactors
333
+	 */
334
+	public static function setCascadeFactors(array $cascadeFactors)
335
+	{
336
+		self::$flipCascadeFactors = null;
337
+		static::$cascadeFactors = $cascadeFactors;
338
+	}
339
+
340
+	///////////////////////////////////////////////////////////////////
341
+	//////////////////////////// CONSTRUCTORS /////////////////////////
342
+	///////////////////////////////////////////////////////////////////
343
+
344
+	/**
345
+	 * Create a new CarbonInterval instance.
346
+	 *
347
+	 * @param Closure|DateInterval|string|int|null $years
348
+	 * @param int|null                             $months
349
+	 * @param int|null                             $weeks
350
+	 * @param int|null                             $days
351
+	 * @param int|null                             $hours
352
+	 * @param int|null                             $minutes
353
+	 * @param int|null                             $seconds
354
+	 * @param int|null                             $microseconds
355
+	 *
356
+	 * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
357
+	 */
358
+	public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
359
+	{
360
+		if ($years instanceof Closure) {
361
+			$this->step = $years;
362
+			$years = null;
363
+		}
364
+
365
+		if ($years instanceof DateInterval) {
366
+			parent::__construct(static::getDateIntervalSpec($years));
367
+			$this->f = $years->f;
368
+			self::copyNegativeUnits($years, $this);
369
+
370
+			return;
371
+		}
372
+
373
+		$spec = $years;
374
+
375
+		if (!\is_string($spec) || (float) $years || preg_match('/^[\d.]/', $years)) {
376
+			$spec = static::PERIOD_PREFIX;
377
+
378
+			$spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
379
+			$spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
380
+
381
+			$specDays = 0;
382
+			$specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
383
+			$specDays += $days > 0 ? $days : 0;
384
+
385
+			$spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
386
+
387
+			if ($hours > 0 || $minutes > 0 || $seconds > 0) {
388
+				$spec .= static::PERIOD_TIME_PREFIX;
389
+				$spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
390
+				$spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
391
+				$spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
392
+			}
393
+
394
+			if ($spec === static::PERIOD_PREFIX) {
395
+				// Allow the zero interval.
396
+				$spec .= '0'.static::PERIOD_YEARS;
397
+			}
398
+		}
399
+
400
+		parent::__construct($spec);
401
+
402
+		if ($microseconds !== null) {
403
+			$this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
404
+		}
405
+	}
406
+
407
+	/**
408
+	 * Returns the factor for a given source-to-target couple.
409
+	 *
410
+	 * @param string $source
411
+	 * @param string $target
412
+	 *
413
+	 * @return int|null
414
+	 */
415
+	public static function getFactor($source, $target)
416
+	{
417
+		$source = self::standardizeUnit($source);
418
+		$target = self::standardizeUnit($target);
419
+		$factors = self::getFlipCascadeFactors();
420
+
421
+		if (isset($factors[$source])) {
422
+			[$to, $factor] = $factors[$source];
423
+
424
+			if ($to === $target) {
425
+				return $factor;
426
+			}
427
+
428
+			return $factor * static::getFactor($to, $target);
429
+		}
430
+
431
+		return null;
432
+	}
433
+
434
+	/**
435
+	 * Returns the factor for a given source-to-target couple if set,
436
+	 * else try to find the appropriate constant as the factor, such as Carbon::DAYS_PER_WEEK.
437
+	 *
438
+	 * @param string $source
439
+	 * @param string $target
440
+	 *
441
+	 * @return int|null
442
+	 */
443
+	public static function getFactorWithDefault($source, $target)
444
+	{
445
+		$factor = self::getFactor($source, $target);
446
+
447
+		if ($factor) {
448
+			return $factor;
449
+		}
450
+
451
+		static $defaults = [
452
+			'month' => ['year' => Carbon::MONTHS_PER_YEAR],
453
+			'week' => ['month' => Carbon::WEEKS_PER_MONTH],
454
+			'day' => ['week' => Carbon::DAYS_PER_WEEK],
455
+			'hour' => ['day' => Carbon::HOURS_PER_DAY],
456
+			'minute' => ['hour' => Carbon::MINUTES_PER_HOUR],
457
+			'second' => ['minute' => Carbon::SECONDS_PER_MINUTE],
458
+			'millisecond' => ['second' => Carbon::MILLISECONDS_PER_SECOND],
459
+			'microsecond' => ['millisecond' => Carbon::MICROSECONDS_PER_MILLISECOND],
460
+		];
461
+
462
+		return $defaults[$source][$target] ?? null;
463
+	}
464
+
465
+	/**
466
+	 * Returns current config for days per week.
467
+	 *
468
+	 * @return int
469
+	 */
470
+	public static function getDaysPerWeek()
471
+	{
472
+		return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
473
+	}
474
+
475
+	/**
476
+	 * Returns current config for hours per day.
477
+	 *
478
+	 * @return int
479
+	 */
480
+	public static function getHoursPerDay()
481
+	{
482
+		return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
483
+	}
484
+
485
+	/**
486
+	 * Returns current config for minutes per hour.
487
+	 *
488
+	 * @return int
489
+	 */
490
+	public static function getMinutesPerHour()
491
+	{
492
+		return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
493
+	}
494
+
495
+	/**
496
+	 * Returns current config for seconds per minute.
497
+	 *
498
+	 * @return int
499
+	 */
500
+	public static function getSecondsPerMinute()
501
+	{
502
+		return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
503
+	}
504
+
505
+	/**
506
+	 * Returns current config for microseconds per second.
507
+	 *
508
+	 * @return int
509
+	 */
510
+	public static function getMillisecondsPerSecond()
511
+	{
512
+		return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
513
+	}
514
+
515
+	/**
516
+	 * Returns current config for microseconds per second.
517
+	 *
518
+	 * @return int
519
+	 */
520
+	public static function getMicrosecondsPerMillisecond()
521
+	{
522
+		return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
523
+	}
524
+
525
+	/**
526
+	 * Create a new CarbonInterval instance from specific values.
527
+	 * This is an alias for the constructor that allows better fluent
528
+	 * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
529
+	 * (new CarbonInterval(1))->fn().
530
+	 *
531
+	 * @param int $years
532
+	 * @param int $months
533
+	 * @param int $weeks
534
+	 * @param int $days
535
+	 * @param int $hours
536
+	 * @param int $minutes
537
+	 * @param int $seconds
538
+	 * @param int $microseconds
539
+	 *
540
+	 * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
541
+	 *
542
+	 * @return static
543
+	 */
544
+	public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
545
+	{
546
+		return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
547
+	}
548
+
549
+	/**
550
+	 * Parse a string into a new CarbonInterval object according to the specified format.
551
+	 *
552
+	 * @example
553
+	 * ```
554
+	 * echo Carboninterval::createFromFormat('H:i', '1:30');
555
+	 * ```
556
+	 *
557
+	 * @param string      $format   Format of the $interval input string
558
+	 * @param string|null $interval Input string to convert into an interval
559
+	 *
560
+	 * @throws \Carbon\Exceptions\ParseErrorException when the $interval cannot be parsed as an interval.
561
+	 *
562
+	 * @return static
563
+	 */
564
+	public static function createFromFormat(string $format, ?string $interval)
565
+	{
566
+		$instance = new static(0);
567
+		$length = mb_strlen($format);
568
+
569
+		if (preg_match('/s([,.])([uv])$/', $format, $match)) {
570
+			$interval = explode($match[1], $interval);
571
+			$index = \count($interval) - 1;
572
+			$interval[$index] = str_pad($interval[$index], $match[2] === 'v' ? 3 : 6, '0');
573
+			$interval = implode($match[1], $interval);
574
+		}
575
+
576
+		$interval = $interval ?? '';
577
+
578
+		for ($index = 0; $index < $length; $index++) {
579
+			$expected = mb_substr($format, $index, 1);
580
+			$nextCharacter = mb_substr($interval, 0, 1);
581
+			$unit = static::$formats[$expected] ?? null;
582
+
583
+			if ($unit) {
584
+				if (!preg_match('/^-?\d+/', $interval, $match)) {
585
+					throw new ParseErrorException('number', $nextCharacter);
586
+				}
587
+
588
+				$interval = mb_substr($interval, mb_strlen($match[0]));
589
+				$instance->$unit += (int) ($match[0]);
590
+
591
+				continue;
592
+			}
593
+
594
+			if ($nextCharacter !== $expected) {
595
+				throw new ParseErrorException(
596
+					"'$expected'",
597
+					$nextCharacter,
598
+					'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
599
+					'See https://php.net/manual/en/function.date.php for their meaning'
600
+				);
601
+			}
602
+
603
+			$interval = mb_substr($interval, 1);
604
+		}
605
+
606
+		if ($interval !== '') {
607
+			throw new ParseErrorException(
608
+				'end of string',
609
+				$interval
610
+			);
611
+		}
612
+
613
+		return $instance;
614
+	}
615
+
616
+	/**
617
+	 * Get a copy of the instance.
618
+	 *
619
+	 * @return static
620
+	 */
621
+	public function copy()
622
+	{
623
+		$date = new static(0);
624
+		$date->copyProperties($this);
625
+		$date->step = $this->step;
626
+
627
+		return $date;
628
+	}
629
+
630
+	/**
631
+	 * Get a copy of the instance.
632
+	 *
633
+	 * @return static
634
+	 */
635
+	public function clone()
636
+	{
637
+		return $this->copy();
638
+	}
639
+
640
+	/**
641
+	 * Provide static helpers to create instances.  Allows CarbonInterval::years(3).
642
+	 *
643
+	 * Note: This is done using the magic method to allow static and instance methods to
644
+	 *       have the same names.
645
+	 *
646
+	 * @param string $method     magic method name called
647
+	 * @param array  $parameters parameters list
648
+	 *
649
+	 * @return static|null
650
+	 */
651
+	public static function __callStatic($method, $parameters)
652
+	{
653
+		try {
654
+			$interval = new static(0);
655
+			$localStrictModeEnabled = $interval->localStrictModeEnabled;
656
+			$interval->localStrictModeEnabled = true;
657
+
658
+			$result = static::hasMacro($method)
659
+				? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) {
660
+					return $interval->callMacro($method, $parameters);
661
+				})
662
+				: $interval->$method(...$parameters);
663
+
664
+			$interval->localStrictModeEnabled = $localStrictModeEnabled;
665
+
666
+			return $result;
667
+		} catch (BadFluentSetterException $exception) {
668
+			if (Carbon::isStrictModeEnabled()) {
669
+				throw new BadFluentConstructorException($method, 0, $exception);
670
+			}
671
+
672
+			return null;
673
+		}
674
+	}
675
+
676
+	/**
677
+	 * Return the current context from inside a macro callee or a new one if static.
678
+	 *
679
+	 * @return static
680
+	 */
681
+	protected static function this()
682
+	{
683
+		return end(static::$macroContextStack) ?: new static(0);
684
+	}
685
+
686
+	/**
687
+	 * Creates a CarbonInterval from string.
688
+	 *
689
+	 * Format:
690
+	 *
691
+	 * Suffix | Unit    | Example | DateInterval expression
692
+	 * -------|---------|---------|------------------------
693
+	 * y      | years   |   1y    | P1Y
694
+	 * mo     | months  |   3mo   | P3M
695
+	 * w      | weeks   |   2w    | P2W
696
+	 * d      | days    |  28d    | P28D
697
+	 * h      | hours   |   4h    | PT4H
698
+	 * m      | minutes |  12m    | PT12M
699
+	 * s      | seconds |  59s    | PT59S
700
+	 *
701
+	 * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
702
+	 *
703
+	 * Special cases:
704
+	 *  - An empty string will return a zero interval
705
+	 *  - Fractions are allowed for weeks, days, hours and minutes and will be converted
706
+	 *    and rounded to the next smaller value (caution: 0.5w = 4d)
707
+	 *
708
+	 * @param string $intervalDefinition
709
+	 *
710
+	 * @return static
711
+	 */
712
+	public static function fromString($intervalDefinition)
713
+	{
714
+		if (empty($intervalDefinition)) {
715
+			return new static(0);
716
+		}
717
+
718
+		$years = 0;
719
+		$months = 0;
720
+		$weeks = 0;
721
+		$days = 0;
722
+		$hours = 0;
723
+		$minutes = 0;
724
+		$seconds = 0;
725
+		$milliseconds = 0;
726
+		$microseconds = 0;
727
+
728
+		$pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
729
+		preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
730
+
731
+		while ([$part, $value, $unit] = array_shift($parts)) {
732
+			$intValue = (int) $value;
733
+			$fraction = (float) $value - $intValue;
734
+
735
+			// Fix calculation precision
736
+			switch (round($fraction, 6)) {
737
+				case 1:
738
+					$fraction = 0;
739
+					$intValue++;
740
+
741
+					break;
742
+				case 0:
743
+					$fraction = 0;
744
+
745
+					break;
746
+			}
747
+
748
+			switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
749
+				case 'millennia':
750
+				case 'millennium':
751
+					$years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
752
+
753
+					break;
754
+
755
+				case 'century':
756
+				case 'centuries':
757
+					$years += $intValue * CarbonInterface::YEARS_PER_CENTURY;
758
+
759
+					break;
760
+
761
+				case 'decade':
762
+				case 'decades':
763
+					$years += $intValue * CarbonInterface::YEARS_PER_DECADE;
764
+
765
+					break;
766
+
767
+				case 'year':
768
+				case 'years':
769
+				case 'y':
770
+					$years += $intValue;
771
+
772
+					break;
773
+
774
+				case 'quarter':
775
+				case 'quarters':
776
+					$months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;
777
+
778
+					break;
779
+
780
+				case 'month':
781
+				case 'months':
782
+				case 'mo':
783
+					$months += $intValue;
784
+
785
+					break;
786
+
787
+				case 'week':
788
+				case 'weeks':
789
+				case 'w':
790
+					$weeks += $intValue;
791
+
792
+					if ($fraction) {
793
+						$parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
794
+					}
795
+
796
+					break;
797
+
798
+				case 'day':
799
+				case 'days':
800
+				case 'd':
801
+					$days += $intValue;
802
+
803
+					if ($fraction) {
804
+						$parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
805
+					}
806
+
807
+					break;
808
+
809
+				case 'hour':
810
+				case 'hours':
811
+				case 'h':
812
+					$hours += $intValue;
813 813
 
814
-                    if ($fraction) {
815
-                        $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
816
-                    }
814
+					if ($fraction) {
815
+						$parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
816
+					}
817 817
 
818
-                    break;
818
+					break;
819 819
 
820
-                case 'minute':
821
-                case 'minutes':
822
-                case 'm':
823
-                    $minutes += $intValue;
820
+				case 'minute':
821
+				case 'minutes':
822
+				case 'm':
823
+					$minutes += $intValue;
824 824
 
825
-                    if ($fraction) {
826
-                        $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
827
-                    }
825
+					if ($fraction) {
826
+						$parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
827
+					}
828 828
 
829
-                    break;
829
+					break;
830 830
 
831
-                case 'second':
832
-                case 'seconds':
833
-                case 's':
834
-                    $seconds += $intValue;
835
-
836
-                    if ($fraction) {
837
-                        $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
838
-                    }
839
-
840
-                    break;
841
-
842
-                case 'millisecond':
843
-                case 'milliseconds':
844
-                case 'milli':
845
-                case 'ms':
846
-                    $milliseconds += $intValue;
847
-
848
-                    if ($fraction) {
849
-                        $microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
850
-                    }
851
-
852
-                    break;
853
-
854
-                case 'microsecond':
855
-                case 'microseconds':
856
-                case 'micro':
857
-                case 'µs':
858
-                    $microseconds += $intValue;
859
-
860
-                    break;
861
-
862
-                default:
863
-                    throw new InvalidIntervalException(
864
-                        sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
865
-                    );
866
-            }
867
-        }
868
-
869
-        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
870
-    }
871
-
872
-    /**
873
-     * Creates a CarbonInterval from string using a different locale.
874
-     *
875
-     * @param string      $interval interval string in the given language (may also contain English).
876
-     * @param string|null $locale   if locale is null or not specified, current global locale will be used instead.
877
-     *
878
-     * @return static
879
-     */
880
-    public static function parseFromLocale($interval, $locale = null)
881
-    {
882
-        return static::fromString(Carbon::translateTimeString($interval, $locale ?: static::getLocale(), 'en'));
883
-    }
884
-
885
-    private static function castIntervalToClass(DateInterval $interval, string $className)
886
-    {
887
-        $mainClass = DateInterval::class;
888
-
889
-        if (!is_a($className, $mainClass, true)) {
890
-            throw new InvalidCastException("$className is not a sub-class of $mainClass.");
891
-        }
892
-
893
-        $microseconds = $interval->f;
894
-        $instance = new $className(static::getDateIntervalSpec($interval));
895
-
896
-        if ($microseconds) {
897
-            $instance->f = $microseconds;
898
-        }
899
-
900
-        if ($interval instanceof self && is_a($className, self::class, true)) {
901
-            self::copyStep($interval, $instance);
902
-        }
903
-
904
-        self::copyNegativeUnits($interval, $instance);
905
-
906
-        return $instance;
907
-    }
908
-
909
-    private static function copyNegativeUnits(DateInterval $from, DateInterval $to): void
910
-    {
911
-        $to->invert = $from->invert;
912
-
913
-        foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
914
-            if ($from->$unit < 0) {
915
-                $to->$unit *= -1;
916
-            }
917
-        }
918
-    }
919
-
920
-    private static function copyStep(self $from, self $to): void
921
-    {
922
-        $to->setStep($from->getStep());
923
-    }
924
-
925
-    /**
926
-     * Cast the current instance into the given class.
927
-     *
928
-     * @param string $className The $className::instance() method will be called to cast the current object.
929
-     *
930
-     * @return DateInterval
931
-     */
932
-    public function cast(string $className)
933
-    {
934
-        return self::castIntervalToClass($this, $className);
935
-    }
936
-
937
-    /**
938
-     * Create a CarbonInterval instance from a DateInterval one.  Can not instance
939
-     * DateInterval objects created from DateTime::diff() as you can't externally
940
-     * set the $days field.
941
-     *
942
-     * @param DateInterval $interval
943
-     *
944
-     * @return static
945
-     */
946
-    public static function instance(DateInterval $interval)
947
-    {
948
-        return self::castIntervalToClass($interval, static::class);
949
-    }
950
-
951
-    /**
952
-     * Make a CarbonInterval instance from given variable if possible.
953
-     *
954
-     * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
955
-     * and recurrences). Throw an exception for invalid format, but otherwise return null.
956
-     *
957
-     * @param mixed|int|DateInterval|string|Closure|null $interval interval or number of the given $unit
958
-     * @param string|null                                $unit     if specified, $interval must be an integer
959
-     *
960
-     * @return static|null
961
-     */
962
-    public static function make($interval, $unit = null)
963
-    {
964
-        if ($unit) {
965
-            $interval = "$interval ".Carbon::pluralUnit($unit);
966
-        }
967
-
968
-        if ($interval instanceof DateInterval) {
969
-            return static::instance($interval);
970
-        }
971
-
972
-        if ($interval instanceof Closure) {
973
-            return new static($interval);
974
-        }
975
-
976
-        if (!\is_string($interval)) {
977
-            return null;
978
-        }
979
-
980
-        return static::makeFromString($interval);
981
-    }
982
-
983
-    protected static function makeFromString(string $interval)
984
-    {
985
-        $interval = preg_replace('/\s+/', ' ', trim($interval));
986
-
987
-        if (preg_match('/^P[T\d]/', $interval)) {
988
-            return new static($interval);
989
-        }
990
-
991
-        if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $interval)) {
992
-            return static::fromString($interval);
993
-        }
994
-
995
-        /** @var static $interval */
996
-        $interval = static::createFromDateString($interval);
997
-
998
-        return !$interval || $interval->isEmpty() ? null : $interval;
999
-    }
1000
-
1001
-    protected function resolveInterval($interval)
1002
-    {
1003
-        if (!($interval instanceof self)) {
1004
-            return self::make($interval);
1005
-        }
1006
-
1007
-        return $interval;
1008
-    }
1009
-
1010
-    /**
1011
-     * Sets up a DateInterval from the relative parts of the string.
1012
-     *
1013
-     * @param string $time
1014
-     *
1015
-     * @return static
1016
-     *
1017
-     * @link https://php.net/manual/en/dateinterval.createfromdatestring.php
1018
-     */
1019
-    #[ReturnTypeWillChange]
1020
-    public static function createFromDateString($time)
1021
-    {
1022
-        $interval = @parent::createFromDateString(strtr($time, [
1023
-            ',' => ' ',
1024
-            ' and ' => ' ',
1025
-        ]));
1026
-
1027
-        if ($interval instanceof DateInterval) {
1028
-            $interval = static::instance($interval);
1029
-        }
1030
-
1031
-        return $interval;
1032
-    }
1033
-
1034
-    ///////////////////////////////////////////////////////////////////
1035
-    ///////////////////////// GETTERS AND SETTERS /////////////////////
1036
-    ///////////////////////////////////////////////////////////////////
1037
-
1038
-    /**
1039
-     * Get a part of the CarbonInterval object.
1040
-     *
1041
-     * @param string $name
1042
-     *
1043
-     * @throws UnknownGetterException
1044
-     *
1045
-     * @return int|float|string
1046
-     */
1047
-    public function get($name)
1048
-    {
1049
-        if (str_starts_with($name, 'total')) {
1050
-            return $this->total(substr($name, 5));
1051
-        }
1052
-
1053
-        switch ($name) {
1054
-            case 'years':
1055
-                return $this->y;
1056
-
1057
-            case 'months':
1058
-                return $this->m;
1059
-
1060
-            case 'dayz':
1061
-                return $this->d;
1062
-
1063
-            case 'hours':
1064
-                return $this->h;
1065
-
1066
-            case 'minutes':
1067
-                return $this->i;
1068
-
1069
-            case 'seconds':
1070
-                return $this->s;
1071
-
1072
-            case 'milli':
1073
-            case 'milliseconds':
1074
-                return (int) (round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
1075
-
1076
-            case 'micro':
1077
-            case 'microseconds':
1078
-                return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
1079
-
1080
-            case 'microExcludeMilli':
1081
-                return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND) % Carbon::MICROSECONDS_PER_MILLISECOND;
1082
-
1083
-            case 'weeks':
1084
-                return (int) ($this->d / static::getDaysPerWeek());
1085
-
1086
-            case 'daysExcludeWeeks':
1087
-            case 'dayzExcludeWeeks':
1088
-                return $this->d % static::getDaysPerWeek();
1089
-
1090
-            case 'locale':
1091
-                return $this->getTranslatorLocale();
1092
-
1093
-            default:
1094
-                throw new UnknownGetterException($name);
1095
-        }
1096
-    }
1097
-
1098
-    /**
1099
-     * Get a part of the CarbonInterval object.
1100
-     *
1101
-     * @param string $name
1102
-     *
1103
-     * @throws UnknownGetterException
1104
-     *
1105
-     * @return int|float|string
1106
-     */
1107
-    public function __get($name)
1108
-    {
1109
-        return $this->get($name);
1110
-    }
1111
-
1112
-    /**
1113
-     * Set a part of the CarbonInterval object.
1114
-     *
1115
-     * @param string|array $name
1116
-     * @param int          $value
1117
-     *
1118
-     * @throws UnknownSetterException
1119
-     *
1120
-     * @return $this
1121
-     */
1122
-    public function set($name, $value = null)
1123
-    {
1124
-        $properties = \is_array($name) ? $name : [$name => $value];
1125
-
1126
-        foreach ($properties as $key => $value) {
1127
-            switch (Carbon::singularUnit(rtrim($key, 'z'))) {
1128
-                case 'year':
1129
-                    $this->y = $value;
1130
-
1131
-                    break;
1132
-
1133
-                case 'month':
1134
-                    $this->m = $value;
1135
-
1136
-                    break;
1137
-
1138
-                case 'week':
1139
-                    $this->d = $value * static::getDaysPerWeek();
1140
-
1141
-                    break;
1142
-
1143
-                case 'day':
1144
-                    $this->d = $value;
1145
-
1146
-                    break;
1147
-
1148
-                case 'daysexcludeweek':
1149
-                case 'dayzexcludeweek':
1150
-                    $this->d = $this->weeks * static::getDaysPerWeek() + $value;
1151
-
1152
-                    break;
1153
-
1154
-                case 'hour':
1155
-                    $this->h = $value;
1156
-
1157
-                    break;
1158
-
1159
-                case 'minute':
1160
-                    $this->i = $value;
1161
-
1162
-                    break;
1163
-
1164
-                case 'second':
1165
-                    $this->s = $value;
1166
-
1167
-                    break;
1168
-
1169
-                case 'milli':
1170
-                case 'millisecond':
1171
-                    $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
1172
-
1173
-                    break;
1174
-
1175
-                case 'micro':
1176
-                case 'microsecond':
1177
-                    $this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
1178
-
1179
-                    break;
1180
-
1181
-                default:
1182
-                    if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
1183
-                        throw new UnknownSetterException($key);
1184
-                    }
1185
-
1186
-                    $this->$key = $value;
1187
-            }
1188
-        }
1189
-
1190
-        return $this;
1191
-    }
1192
-
1193
-    /**
1194
-     * Set a part of the CarbonInterval object.
1195
-     *
1196
-     * @param string $name
1197
-     * @param int    $value
1198
-     *
1199
-     * @throws UnknownSetterException
1200
-     */
1201
-    public function __set($name, $value)
1202
-    {
1203
-        $this->set($name, $value);
1204
-    }
1205
-
1206
-    /**
1207
-     * Allow setting of weeks and days to be cumulative.
1208
-     *
1209
-     * @param int $weeks Number of weeks to set
1210
-     * @param int $days  Number of days to set
1211
-     *
1212
-     * @return static
1213
-     */
1214
-    public function weeksAndDays($weeks, $days)
1215
-    {
1216
-        $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
1217
-
1218
-        return $this;
1219
-    }
1220
-
1221
-    /**
1222
-     * Returns true if the interval is empty for each unit.
1223
-     *
1224
-     * @return bool
1225
-     */
1226
-    public function isEmpty()
1227
-    {
1228
-        return $this->years === 0 &&
1229
-            $this->months === 0 &&
1230
-            $this->dayz === 0 &&
1231
-            !$this->days &&
1232
-            $this->hours === 0 &&
1233
-            $this->minutes === 0 &&
1234
-            $this->seconds === 0 &&
1235
-            $this->microseconds === 0;
1236
-    }
1237
-
1238
-    /**
1239
-     * Register a custom macro.
1240
-     *
1241
-     * @example
1242
-     * ```
1243
-     * CarbonInterval::macro('twice', function () {
1244
-     *   return $this->times(2);
1245
-     * });
1246
-     * echo CarbonInterval::hours(2)->twice();
1247
-     * ```
1248
-     *
1249
-     * @param string          $name
1250
-     * @param object|callable $macro
1251
-     *
1252
-     * @return void
1253
-     */
1254
-    public static function macro($name, $macro)
1255
-    {
1256
-        static::$macros[$name] = $macro;
1257
-    }
1258
-
1259
-    /**
1260
-     * Register macros from a mixin object.
1261
-     *
1262
-     * @example
1263
-     * ```
1264
-     * CarbonInterval::mixin(new class {
1265
-     *   public function daysToHours() {
1266
-     *     return function () {
1267
-     *       $this->hours += $this->days;
1268
-     *       $this->days = 0;
1269
-     *
1270
-     *       return $this;
1271
-     *     };
1272
-     *   }
1273
-     *   public function hoursToDays() {
1274
-     *     return function () {
1275
-     *       $this->days += $this->hours;
1276
-     *       $this->hours = 0;
1277
-     *
1278
-     *       return $this;
1279
-     *     };
1280
-     *   }
1281
-     * });
1282
-     * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
1283
-     * echo CarbonInterval::days(5)->daysToHours() . "\n";
1284
-     * ```
1285
-     *
1286
-     * @param object|string $mixin
1287
-     *
1288
-     * @throws ReflectionException
1289
-     *
1290
-     * @return void
1291
-     */
1292
-    public static function mixin($mixin)
1293
-    {
1294
-        static::baseMixin($mixin);
1295
-    }
1296
-
1297
-    /**
1298
-     * Check if macro is registered.
1299
-     *
1300
-     * @param string $name
1301
-     *
1302
-     * @return bool
1303
-     */
1304
-    public static function hasMacro($name)
1305
-    {
1306
-        return isset(static::$macros[$name]);
1307
-    }
1308
-
1309
-    /**
1310
-     * Call given macro.
1311
-     *
1312
-     * @param string $name
1313
-     * @param array  $parameters
1314
-     *
1315
-     * @return mixed
1316
-     */
1317
-    protected function callMacro($name, $parameters)
1318
-    {
1319
-        $macro = static::$macros[$name];
1320
-
1321
-        if ($macro instanceof Closure) {
1322
-            $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);
1323
-
1324
-            return ($boundMacro ?: $macro)(...$parameters);
1325
-        }
1326
-
1327
-        return $macro(...$parameters);
1328
-    }
1329
-
1330
-    /**
1331
-     * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
1332
-     *
1333
-     * Note: This is done using the magic method to allow static and instance methods to
1334
-     *       have the same names.
1335
-     *
1336
-     * @param string $method     magic method name called
1337
-     * @param array  $parameters parameters list
1338
-     *
1339
-     * @throws BadFluentSetterException|Throwable
1340
-     *
1341
-     * @return static
1342
-     */
1343
-    public function __call($method, $parameters)
1344
-    {
1345
-        if (static::hasMacro($method)) {
1346
-            return static::bindMacroContext($this, function () use (&$method, &$parameters) {
1347
-                return $this->callMacro($method, $parameters);
1348
-            });
1349
-        }
1350
-
1351
-        $roundedValue = $this->callRoundMethod($method, $parameters);
1352
-
1353
-        if ($roundedValue !== null) {
1354
-            return $roundedValue;
1355
-        }
1356
-
1357
-        if (preg_match('/^(?<method>add|sub)(?<unit>[A-Z].*)$/', $method, $match)) {
1358
-            return $this->{$match['method']}($parameters[0], $match['unit']);
1359
-        }
1360
-
1361
-        try {
1362
-            $this->set($method, \count($parameters) === 0 ? 1 : $parameters[0]);
1363
-        } catch (UnknownSetterException $exception) {
1364
-            if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
1365
-                throw new BadFluentSetterException($method, 0, $exception);
1366
-            }
1367
-        }
1368
-
1369
-        return $this;
1370
-    }
1371
-
1372
-    protected function getForHumansInitialVariables($syntax, $short)
1373
-    {
1374
-        if (\is_array($syntax)) {
1375
-            return $syntax;
1376
-        }
1377
-
1378
-        if (\is_int($short)) {
1379
-            return [
1380
-                'parts' => $short,
1381
-                'short' => false,
1382
-            ];
1383
-        }
1384
-
1385
-        if (\is_bool($syntax)) {
1386
-            return [
1387
-                'short' => $syntax,
1388
-                'syntax' => CarbonInterface::DIFF_ABSOLUTE,
1389
-            ];
1390
-        }
1391
-
1392
-        return [];
1393
-    }
1394
-
1395
-    /**
1396
-     * @param mixed $syntax
1397
-     * @param mixed $short
1398
-     * @param mixed $parts
1399
-     * @param mixed $options
1400
-     *
1401
-     * @return array
1402
-     */
1403
-    protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
1404
-    {
1405
-        $optionalSpace = ' ';
1406
-        $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
1407
-        $join = $default === '' ? '' : ' ';
1408
-        $altNumbers = false;
1409
-        $aUnit = false;
1410
-        $minimumUnit = 's';
1411
-        $skip = [];
1412
-        extract($this->getForHumansInitialVariables($syntax, $short));
1413
-        $skip = array_filter((array) $skip, static function ($value) {
1414
-            return \is_string($value) && $value !== '';
1415
-        });
1416
-
1417
-        if ($syntax === null) {
1418
-            $syntax = CarbonInterface::DIFF_ABSOLUTE;
1419
-        }
1420
-
1421
-        if ($parts === -1) {
1422
-            $parts = INF;
1423
-        }
1424
-
1425
-        if ($options === null) {
1426
-            $options = static::getHumanDiffOptions();
1427
-        }
1428
-
1429
-        if ($join === false) {
1430
-            $join = ' ';
1431
-        } elseif ($join === true) {
1432
-            $join = [
1433
-                $default,
1434
-                $this->getTranslationMessage('list.1') ?? $default,
1435
-            ];
1436
-        }
1437
-
1438
-        if ($altNumbers && $altNumbers !== true) {
1439
-            $language = new Language($this->locale);
1440
-            $altNumbers = \in_array($language->getCode(), (array) $altNumbers, true);
1441
-        }
1442
-
1443
-        if (\is_array($join)) {
1444
-            [$default, $last] = $join;
1445
-
1446
-            if ($default !== ' ') {
1447
-                $optionalSpace = '';
1448
-            }
1449
-
1450
-            $join = function ($list) use ($default, $last) {
1451
-                if (\count($list) < 2) {
1452
-                    return implode('', $list);
1453
-                }
1454
-
1455
-                $end = array_pop($list);
1456
-
1457
-                return implode($default, $list).$last.$end;
1458
-            };
1459
-        }
1460
-
1461
-        if (\is_string($join)) {
1462
-            if ($join !== ' ') {
1463
-                $optionalSpace = '';
1464
-            }
1465
-
1466
-            $glue = $join;
1467
-            $join = function ($list) use ($glue) {
1468
-                return implode($glue, $list);
1469
-            };
1470
-        }
1471
-
1472
-        $interpolations = [
1473
-            ':optional-space' => $optionalSpace,
1474
-        ];
1475
-
1476
-        return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip];
1477
-    }
1478
-
1479
-    protected static function getRoundingMethodFromOptions(int $options): ?string
1480
-    {
1481
-        if ($options & CarbonInterface::ROUND) {
1482
-            return 'round';
1483
-        }
1484
-
1485
-        if ($options & CarbonInterface::CEIL) {
1486
-            return 'ceil';
1487
-        }
1488
-
1489
-        if ($options & CarbonInterface::FLOOR) {
1490
-            return 'floor';
1491
-        }
1492
-
1493
-        return null;
1494
-    }
1495
-
1496
-    /**
1497
-     * Returns interval values as an array where key are the unit names and values the counts.
1498
-     *
1499
-     * @return int[]
1500
-     */
1501
-    public function toArray()
1502
-    {
1503
-        return [
1504
-            'years' => $this->years,
1505
-            'months' => $this->months,
1506
-            'weeks' => $this->weeks,
1507
-            'days' => $this->daysExcludeWeeks,
1508
-            'hours' => $this->hours,
1509
-            'minutes' => $this->minutes,
1510
-            'seconds' => $this->seconds,
1511
-            'microseconds' => $this->microseconds,
1512
-        ];
1513
-    }
1514
-
1515
-    /**
1516
-     * Returns interval non-zero values as an array where key are the unit names and values the counts.
1517
-     *
1518
-     * @return int[]
1519
-     */
1520
-    public function getNonZeroValues()
1521
-    {
1522
-        return array_filter($this->toArray(), 'intval');
1523
-    }
1524
-
1525
-    /**
1526
-     * Returns interval values as an array where key are the unit names and values the counts
1527
-     * from the biggest non-zero one the the smallest non-zero one.
1528
-     *
1529
-     * @return int[]
1530
-     */
1531
-    public function getValuesSequence()
1532
-    {
1533
-        $nonZeroValues = $this->getNonZeroValues();
1534
-
1535
-        if ($nonZeroValues === []) {
1536
-            return [];
1537
-        }
1538
-
1539
-        $keys = array_keys($nonZeroValues);
1540
-        $firstKey = $keys[0];
1541
-        $lastKey = $keys[\count($keys) - 1];
1542
-        $values = [];
1543
-        $record = false;
1544
-
1545
-        foreach ($this->toArray() as $unit => $count) {
1546
-            if ($unit === $firstKey) {
1547
-                $record = true;
1548
-            }
1549
-
1550
-            if ($record) {
1551
-                $values[$unit] = $count;
1552
-            }
1553
-
1554
-            if ($unit === $lastKey) {
1555
-                $record = false;
1556
-            }
1557
-        }
1558
-
1559
-        return $values;
1560
-    }
1561
-
1562
-    /**
1563
-     * Get the current interval in a human readable format in the current locale.
1564
-     *
1565
-     * @example
1566
-     * ```
1567
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
1568
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
1569
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
1570
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
1571
-     * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
1572
-     * echo CarbonInterval::fromString('1d 24h')->forHumans(['minimumUnit' => 'hour']) . "\n";
1573
-     * ```
1574
-     *
1575
-     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
1576
-     *                           - 'syntax' entry (see below)
1577
-     *                           - 'short' entry (see below)
1578
-     *                           - 'parts' entry (see below)
1579
-     *                           - 'options' entry (see below)
1580
-     *                           - 'skip' entry, list of units to skip (array of strings or a single string,
1581
-     *                           ` it can be the unit name (singular or plural) or its shortcut
1582
-     *                           ` (y, m, w, d, h, min, s, ms, µs).
1583
-     *                           - 'aUnit' entry, prefer "an hour" over "1 hour" if true
1584
-     *                           - 'join' entry determines how to join multiple parts of the string
1585
-     *                           `  - if $join is a string, it's used as a joiner glue
1586
-     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
1587
-     *                           `  - if $join is an array, the first item will be the default glue, and the second item
1588
-     *                           `    will be used instead of the glue for the last item
1589
-     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
1590
-     *                           `  - if $join is missing, a space will be used as glue
1591
-     *                           - 'minimumUnit' entry determines the smallest unit of time to display can be long or
1592
-     *                           `  short form of the units, e.g. 'hour' or 'h' (default value: s)
1593
-     *                           if int passed, it add modifiers:
1594
-     *                           Possible values:
1595
-     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
1596
-     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
1597
-     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
1598
-     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
1599
-     * @param bool      $short   displays short format of time units
1600
-     * @param int       $parts   maximum number of parts to display (default value: -1: no limits)
1601
-     * @param int       $options human diff options
1602
-     *
1603
-     * @throws Exception
1604
-     *
1605
-     * @return string
1606
-     */
1607
-    public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
1608
-    {
1609
-        [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip] = $this
1610
-            ->getForHumansParameters($syntax, $short, $parts, $options);
1611
-
1612
-        $interval = [];
1613
-
1614
-        $syntax = (int) ($syntax ?? CarbonInterface::DIFF_ABSOLUTE);
1615
-        $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
1616
-        $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
1617
-        $count = 1;
1618
-        $unit = $short ? 's' : 'second';
1619
-        $isFuture = $this->invert === 1;
1620
-        $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
1621
-        $declensionMode = null;
1622
-
1623
-        /** @var \Symfony\Component\Translation\Translator $translator */
1624
-        $translator = $this->getLocalTranslator();
1625
-
1626
-        $handleDeclensions = function ($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) {
1627
-            if (!$absolute) {
1628
-                $declensionMode = $declensionMode ?? $this->translate($transId.'_mode');
1629
-
1630
-                if ($this->needsDeclension($declensionMode, $index, $parts)) {
1631
-                    // Some languages have special pluralization for past and future tense.
1632
-                    $key = $unit.'_'.$transId;
1633
-                    $result = $this->translate($key, $interpolations, $count, $translator, $altNumbers);
1634
-
1635
-                    if ($result !== $key) {
1636
-                        return $result;
1637
-                    }
1638
-                }
1639
-            }
1640
-
1641
-            $result = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
1642
-
1643
-            if ($result !== $unit) {
1644
-                return $result;
1645
-            }
1646
-
1647
-            return null;
1648
-        };
1649
-
1650
-        $intervalValues = $this;
1651
-        $method = static::getRoundingMethodFromOptions($options);
1652
-
1653
-        if ($method) {
1654
-            $previousCount = INF;
1655
-
1656
-            while (
1657
-                \count($intervalValues->getNonZeroValues()) > $parts &&
1658
-                ($count = \count($keys = array_keys($intervalValues->getValuesSequence()))) > 1
1659
-            ) {
1660
-                $index = min($count, $previousCount - 1) - 2;
1661
-
1662
-                if ($index < 0) {
1663
-                    break;
1664
-                }
1665
-
1666
-                $intervalValues = $this->copy()->roundUnit(
1667
-                    $keys[$index],
1668
-                    1,
1669
-                    $method
1670
-                );
1671
-                $previousCount = $count;
1672
-            }
1673
-        }
1674
-
1675
-        $diffIntervalArray = [
1676
-            ['value' => $intervalValues->years,             'unit' => 'year',        'unitShort' => 'y'],
1677
-            ['value' => $intervalValues->months,            'unit' => 'month',       'unitShort' => 'm'],
1678
-            ['value' => $intervalValues->weeks,             'unit' => 'week',        'unitShort' => 'w'],
1679
-            ['value' => $intervalValues->daysExcludeWeeks,  'unit' => 'day',         'unitShort' => 'd'],
1680
-            ['value' => $intervalValues->hours,             'unit' => 'hour',        'unitShort' => 'h'],
1681
-            ['value' => $intervalValues->minutes,           'unit' => 'minute',      'unitShort' => 'min'],
1682
-            ['value' => $intervalValues->seconds,           'unit' => 'second',      'unitShort' => 's'],
1683
-            ['value' => $intervalValues->milliseconds,      'unit' => 'millisecond', 'unitShort' => 'ms'],
1684
-            ['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'],
1685
-        ];
1686
-
1687
-        if (!empty($skip)) {
1688
-            foreach ($diffIntervalArray as $index => &$unitData) {
1689
-                $nextIndex = $index + 1;
1690
-
1691
-                if ($unitData['value'] &&
1692
-                    isset($diffIntervalArray[$nextIndex]) &&
1693
-                    \count(array_intersect([$unitData['unit'], $unitData['unit'].'s', $unitData['unitShort']], $skip))
1694
-                ) {
1695
-                    $diffIntervalArray[$nextIndex]['value'] += $unitData['value'] *
1696
-                        self::getFactorWithDefault($diffIntervalArray[$nextIndex]['unit'], $unitData['unit']);
1697
-                    $unitData['value'] = 0;
1698
-                }
1699
-            }
1700
-        }
1701
-
1702
-        $transChoice = function ($short, $unitData, $index, $parts) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
1703
-            $count = $unitData['value'];
1704
-
1705
-            if ($short) {
1706
-                $result = $handleDeclensions($unitData['unitShort'], $count, $index, $parts);
1707
-
1708
-                if ($result !== null) {
1709
-                    return $result;
1710
-                }
1711
-            } elseif ($aUnit) {
1712
-                $result = $handleDeclensions('a_'.$unitData['unit'], $count, $index, $parts);
1713
-
1714
-                if ($result !== null) {
1715
-                    return $result;
1716
-                }
1717
-            }
1718
-
1719
-            if (!$absolute) {
1720
-                return $handleDeclensions($unitData['unit'], $count, $index, $parts);
1721
-            }
1722
-
1723
-            return $this->translate($unitData['unit'], $interpolations, $count, $translator, $altNumbers);
1724
-        };
1725
-
1726
-        $fallbackUnit = ['second', 's'];
1727
-
1728
-        foreach ($diffIntervalArray as $diffIntervalData) {
1729
-            if ($diffIntervalData['value'] > 0) {
1730
-                $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
1731
-                $count = $diffIntervalData['value'];
1732
-                $interval[] = [$short, $diffIntervalData];
1733
-            } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && \count($interval) > 0) {
1734
-                break;
1735
-            }
1736
-
1737
-            // break the loop after we get the required number of parts in array
1738
-            if (\count($interval) >= $parts) {
1739
-                break;
1740
-            }
1741
-
1742
-            // break the loop after we have reached the minimum unit
1743
-            if (\in_array($minimumUnit, [$diffIntervalData['unit'], $diffIntervalData['unitShort']], true)) {
1744
-                $fallbackUnit = [$diffIntervalData['unit'], $diffIntervalData['unitShort']];
1745
-
1746
-                break;
1747
-            }
1748
-        }
1749
-
1750
-        $actualParts = \count($interval);
1751
-
1752
-        foreach ($interval as $index => &$item) {
1753
-            $item = $transChoice($item[0], $item[1], $index, $actualParts);
1754
-        }
1755
-
1756
-        if (\count($interval) === 0) {
1757
-            if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
1758
-                $key = 'diff_now';
1759
-                $translation = $this->translate($key, $interpolations, null, $translator);
1760
-
1761
-                if ($translation !== $key) {
1762
-                    return $translation;
1763
-                }
1764
-            }
1765
-
1766
-            $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
1767
-            $unit = $fallbackUnit[$short ? 1 : 0];
1768
-            $interval[] = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
1769
-        }
1770
-
1771
-        // join the interval parts by a space
1772
-        $time = $join($interval);
1773
-
1774
-        unset($diffIntervalArray, $interval);
1775
-
1776
-        if ($absolute) {
1777
-            return $time;
1778
-        }
1779
-
1780
-        $isFuture = $this->invert === 1;
1781
-
1782
-        $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
1783
-
1784
-        if ($parts === 1) {
1785
-            if ($relativeToNow && $unit === 'day') {
1786
-                if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
1787
-                    $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
1788
-                    $translation = $this->translate($key, $interpolations, null, $translator);
1789
-
1790
-                    if ($translation !== $key) {
1791
-                        return $translation;
1792
-                    }
1793
-                }
1794
-
1795
-                if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
1796
-                    $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
1797
-                    $translation = $this->translate($key, $interpolations, null, $translator);
1798
-
1799
-                    if ($translation !== $key) {
1800
-                        return $translation;
1801
-                    }
1802
-                }
1803
-            }
1804
-
1805
-            $aTime = $aUnit ? $handleDeclensions('a_'.$unit, $count) : null;
1806
-
1807
-            $time = $aTime ?: $handleDeclensions($unit, $count) ?: $time;
1808
-        }
1809
-
1810
-        $time = [':time' => $time];
1811
-
1812
-        return $this->translate($transId, array_merge($time, $interpolations, $time), null, $translator);
1813
-    }
1814
-
1815
-    /**
1816
-     * Format the instance as a string using the forHumans() function.
1817
-     *
1818
-     * @throws Exception
1819
-     *
1820
-     * @return string
1821
-     */
1822
-    public function __toString()
1823
-    {
1824
-        $format = $this->localToStringFormat;
1825
-
1826
-        if (!$format) {
1827
-            return $this->forHumans();
1828
-        }
1829
-
1830
-        if ($format instanceof Closure) {
1831
-            return $format($this);
1832
-        }
1833
-
1834
-        return $this->format($format);
1835
-    }
1836
-
1837
-    /**
1838
-     * Return native DateInterval PHP object matching the current instance.
1839
-     *
1840
-     * @example
1841
-     * ```
1842
-     * var_dump(CarbonInterval::hours(2)->toDateInterval());
1843
-     * ```
1844
-     *
1845
-     * @return DateInterval
1846
-     */
1847
-    public function toDateInterval()
1848
-    {
1849
-        return self::castIntervalToClass($this, DateInterval::class);
1850
-    }
1851
-
1852
-    /**
1853
-     * Convert the interval to a CarbonPeriod.
1854
-     *
1855
-     * @param DateTimeInterface|string|int ...$params Start date, [end date or recurrences] and optional settings.
1856
-     *
1857
-     * @return CarbonPeriod
1858
-     */
1859
-    public function toPeriod(...$params)
1860
-    {
1861
-        if ($this->tzName) {
1862
-            $tz = \is_string($this->tzName) ? new DateTimeZone($this->tzName) : $this->tzName;
1863
-
1864
-            if ($tz instanceof DateTimeZone) {
1865
-                array_unshift($params, $tz);
1866
-            }
1867
-        }
1868
-
1869
-        return CarbonPeriod::create($this, ...$params);
1870
-    }
1871
-
1872
-    /**
1873
-     * Invert the interval.
1874
-     *
1875
-     * @param bool|int $inverted if a parameter is passed, the passed value casted as 1 or 0 is used
1876
-     *                           as the new value of the ->invert property.
1877
-     *
1878
-     * @return $this
1879
-     */
1880
-    public function invert($inverted = null)
1881
-    {
1882
-        $this->invert = (\func_num_args() === 0 ? !$this->invert : $inverted) ? 1 : 0;
1883
-
1884
-        return $this;
1885
-    }
1886
-
1887
-    protected function solveNegativeInterval()
1888
-    {
1889
-        if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
1890
-            $this->years *= -1;
1891
-            $this->months *= -1;
1892
-            $this->dayz *= -1;
1893
-            $this->hours *= -1;
1894
-            $this->minutes *= -1;
1895
-            $this->seconds *= -1;
1896
-            $this->microseconds *= -1;
1897
-            $this->invert();
1898
-        }
1899
-
1900
-        return $this;
1901
-    }
1902
-
1903
-    /**
1904
-     * Add the passed interval to the current instance.
1905
-     *
1906
-     * @param string|DateInterval $unit
1907
-     * @param int|float           $value
1908
-     *
1909
-     * @return $this
1910
-     */
1911
-    public function add($unit, $value = 1)
1912
-    {
1913
-        if (is_numeric($unit)) {
1914
-            [$value, $unit] = [$unit, $value];
1915
-        }
1916
-
1917
-        if (\is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
1918
-            $unit = "$value $unit";
1919
-            $value = 1;
1920
-        }
1921
-
1922
-        $interval = static::make($unit);
1923
-
1924
-        if (!$interval) {
1925
-            throw new InvalidIntervalException('This type of data cannot be added/subtracted.');
1926
-        }
1927
-
1928
-        if ($value !== 1) {
1929
-            $interval->times($value);
1930
-        }
1931
-
1932
-        $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
1933
-        $this->years += $interval->y * $sign;
1934
-        $this->months += $interval->m * $sign;
1935
-        $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
1936
-        $this->hours += $interval->h * $sign;
1937
-        $this->minutes += $interval->i * $sign;
1938
-        $this->seconds += $interval->s * $sign;
1939
-        $this->microseconds += $interval->microseconds * $sign;
1940
-
1941
-        $this->solveNegativeInterval();
1942
-
1943
-        return $this;
1944
-    }
1945
-
1946
-    /**
1947
-     * Subtract the passed interval to the current instance.
1948
-     *
1949
-     * @param string|DateInterval $unit
1950
-     * @param int|float           $value
1951
-     *
1952
-     * @return $this
1953
-     */
1954
-    public function sub($unit, $value = 1)
1955
-    {
1956
-        if (is_numeric($unit)) {
1957
-            [$value, $unit] = [$unit, $value];
1958
-        }
1959
-
1960
-        return $this->add($unit, -(float) $value);
1961
-    }
1962
-
1963
-    /**
1964
-     * Subtract the passed interval to the current instance.
1965
-     *
1966
-     * @param string|DateInterval $unit
1967
-     * @param int|float           $value
1968
-     *
1969
-     * @return $this
1970
-     */
1971
-    public function subtract($unit, $value = 1)
1972
-    {
1973
-        return $this->sub($unit, $value);
1974
-    }
1975
-
1976
-    /**
1977
-     * Add given parameters to the current interval.
1978
-     *
1979
-     * @param int       $years
1980
-     * @param int       $months
1981
-     * @param int|float $weeks
1982
-     * @param int|float $days
1983
-     * @param int|float $hours
1984
-     * @param int|float $minutes
1985
-     * @param int|float $seconds
1986
-     * @param int|float $microseconds
1987
-     *
1988
-     * @return $this
1989
-     */
1990
-    public function plus(
1991
-        $years = 0,
1992
-        $months = 0,
1993
-        $weeks = 0,
1994
-        $days = 0,
1995
-        $hours = 0,
1996
-        $minutes = 0,
1997
-        $seconds = 0,
1998
-        $microseconds = 0
1999
-    ): self {
2000
-        return $this->add("
831
+				case 'second':
832
+				case 'seconds':
833
+				case 's':
834
+					$seconds += $intValue;
835
+
836
+					if ($fraction) {
837
+						$parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
838
+					}
839
+
840
+					break;
841
+
842
+				case 'millisecond':
843
+				case 'milliseconds':
844
+				case 'milli':
845
+				case 'ms':
846
+					$milliseconds += $intValue;
847
+
848
+					if ($fraction) {
849
+						$microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
850
+					}
851
+
852
+					break;
853
+
854
+				case 'microsecond':
855
+				case 'microseconds':
856
+				case 'micro':
857
+				case 'µs':
858
+					$microseconds += $intValue;
859
+
860
+					break;
861
+
862
+				default:
863
+					throw new InvalidIntervalException(
864
+						sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
865
+					);
866
+			}
867
+		}
868
+
869
+		return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
870
+	}
871
+
872
+	/**
873
+	 * Creates a CarbonInterval from string using a different locale.
874
+	 *
875
+	 * @param string      $interval interval string in the given language (may also contain English).
876
+	 * @param string|null $locale   if locale is null or not specified, current global locale will be used instead.
877
+	 *
878
+	 * @return static
879
+	 */
880
+	public static function parseFromLocale($interval, $locale = null)
881
+	{
882
+		return static::fromString(Carbon::translateTimeString($interval, $locale ?: static::getLocale(), 'en'));
883
+	}
884
+
885
+	private static function castIntervalToClass(DateInterval $interval, string $className)
886
+	{
887
+		$mainClass = DateInterval::class;
888
+
889
+		if (!is_a($className, $mainClass, true)) {
890
+			throw new InvalidCastException("$className is not a sub-class of $mainClass.");
891
+		}
892
+
893
+		$microseconds = $interval->f;
894
+		$instance = new $className(static::getDateIntervalSpec($interval));
895
+
896
+		if ($microseconds) {
897
+			$instance->f = $microseconds;
898
+		}
899
+
900
+		if ($interval instanceof self && is_a($className, self::class, true)) {
901
+			self::copyStep($interval, $instance);
902
+		}
903
+
904
+		self::copyNegativeUnits($interval, $instance);
905
+
906
+		return $instance;
907
+	}
908
+
909
+	private static function copyNegativeUnits(DateInterval $from, DateInterval $to): void
910
+	{
911
+		$to->invert = $from->invert;
912
+
913
+		foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
914
+			if ($from->$unit < 0) {
915
+				$to->$unit *= -1;
916
+			}
917
+		}
918
+	}
919
+
920
+	private static function copyStep(self $from, self $to): void
921
+	{
922
+		$to->setStep($from->getStep());
923
+	}
924
+
925
+	/**
926
+	 * Cast the current instance into the given class.
927
+	 *
928
+	 * @param string $className The $className::instance() method will be called to cast the current object.
929
+	 *
930
+	 * @return DateInterval
931
+	 */
932
+	public function cast(string $className)
933
+	{
934
+		return self::castIntervalToClass($this, $className);
935
+	}
936
+
937
+	/**
938
+	 * Create a CarbonInterval instance from a DateInterval one.  Can not instance
939
+	 * DateInterval objects created from DateTime::diff() as you can't externally
940
+	 * set the $days field.
941
+	 *
942
+	 * @param DateInterval $interval
943
+	 *
944
+	 * @return static
945
+	 */
946
+	public static function instance(DateInterval $interval)
947
+	{
948
+		return self::castIntervalToClass($interval, static::class);
949
+	}
950
+
951
+	/**
952
+	 * Make a CarbonInterval instance from given variable if possible.
953
+	 *
954
+	 * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
955
+	 * and recurrences). Throw an exception for invalid format, but otherwise return null.
956
+	 *
957
+	 * @param mixed|int|DateInterval|string|Closure|null $interval interval or number of the given $unit
958
+	 * @param string|null                                $unit     if specified, $interval must be an integer
959
+	 *
960
+	 * @return static|null
961
+	 */
962
+	public static function make($interval, $unit = null)
963
+	{
964
+		if ($unit) {
965
+			$interval = "$interval ".Carbon::pluralUnit($unit);
966
+		}
967
+
968
+		if ($interval instanceof DateInterval) {
969
+			return static::instance($interval);
970
+		}
971
+
972
+		if ($interval instanceof Closure) {
973
+			return new static($interval);
974
+		}
975
+
976
+		if (!\is_string($interval)) {
977
+			return null;
978
+		}
979
+
980
+		return static::makeFromString($interval);
981
+	}
982
+
983
+	protected static function makeFromString(string $interval)
984
+	{
985
+		$interval = preg_replace('/\s+/', ' ', trim($interval));
986
+
987
+		if (preg_match('/^P[T\d]/', $interval)) {
988
+			return new static($interval);
989
+		}
990
+
991
+		if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $interval)) {
992
+			return static::fromString($interval);
993
+		}
994
+
995
+		/** @var static $interval */
996
+		$interval = static::createFromDateString($interval);
997
+
998
+		return !$interval || $interval->isEmpty() ? null : $interval;
999
+	}
1000
+
1001
+	protected function resolveInterval($interval)
1002
+	{
1003
+		if (!($interval instanceof self)) {
1004
+			return self::make($interval);
1005
+		}
1006
+
1007
+		return $interval;
1008
+	}
1009
+
1010
+	/**
1011
+	 * Sets up a DateInterval from the relative parts of the string.
1012
+	 *
1013
+	 * @param string $time
1014
+	 *
1015
+	 * @return static
1016
+	 *
1017
+	 * @link https://php.net/manual/en/dateinterval.createfromdatestring.php
1018
+	 */
1019
+	#[ReturnTypeWillChange]
1020
+	public static function createFromDateString($time)
1021
+	{
1022
+		$interval = @parent::createFromDateString(strtr($time, [
1023
+			',' => ' ',
1024
+			' and ' => ' ',
1025
+		]));
1026
+
1027
+		if ($interval instanceof DateInterval) {
1028
+			$interval = static::instance($interval);
1029
+		}
1030
+
1031
+		return $interval;
1032
+	}
1033
+
1034
+	///////////////////////////////////////////////////////////////////
1035
+	///////////////////////// GETTERS AND SETTERS /////////////////////
1036
+	///////////////////////////////////////////////////////////////////
1037
+
1038
+	/**
1039
+	 * Get a part of the CarbonInterval object.
1040
+	 *
1041
+	 * @param string $name
1042
+	 *
1043
+	 * @throws UnknownGetterException
1044
+	 *
1045
+	 * @return int|float|string
1046
+	 */
1047
+	public function get($name)
1048
+	{
1049
+		if (str_starts_with($name, 'total')) {
1050
+			return $this->total(substr($name, 5));
1051
+		}
1052
+
1053
+		switch ($name) {
1054
+			case 'years':
1055
+				return $this->y;
1056
+
1057
+			case 'months':
1058
+				return $this->m;
1059
+
1060
+			case 'dayz':
1061
+				return $this->d;
1062
+
1063
+			case 'hours':
1064
+				return $this->h;
1065
+
1066
+			case 'minutes':
1067
+				return $this->i;
1068
+
1069
+			case 'seconds':
1070
+				return $this->s;
1071
+
1072
+			case 'milli':
1073
+			case 'milliseconds':
1074
+				return (int) (round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
1075
+
1076
+			case 'micro':
1077
+			case 'microseconds':
1078
+				return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
1079
+
1080
+			case 'microExcludeMilli':
1081
+				return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND) % Carbon::MICROSECONDS_PER_MILLISECOND;
1082
+
1083
+			case 'weeks':
1084
+				return (int) ($this->d / static::getDaysPerWeek());
1085
+
1086
+			case 'daysExcludeWeeks':
1087
+			case 'dayzExcludeWeeks':
1088
+				return $this->d % static::getDaysPerWeek();
1089
+
1090
+			case 'locale':
1091
+				return $this->getTranslatorLocale();
1092
+
1093
+			default:
1094
+				throw new UnknownGetterException($name);
1095
+		}
1096
+	}
1097
+
1098
+	/**
1099
+	 * Get a part of the CarbonInterval object.
1100
+	 *
1101
+	 * @param string $name
1102
+	 *
1103
+	 * @throws UnknownGetterException
1104
+	 *
1105
+	 * @return int|float|string
1106
+	 */
1107
+	public function __get($name)
1108
+	{
1109
+		return $this->get($name);
1110
+	}
1111
+
1112
+	/**
1113
+	 * Set a part of the CarbonInterval object.
1114
+	 *
1115
+	 * @param string|array $name
1116
+	 * @param int          $value
1117
+	 *
1118
+	 * @throws UnknownSetterException
1119
+	 *
1120
+	 * @return $this
1121
+	 */
1122
+	public function set($name, $value = null)
1123
+	{
1124
+		$properties = \is_array($name) ? $name : [$name => $value];
1125
+
1126
+		foreach ($properties as $key => $value) {
1127
+			switch (Carbon::singularUnit(rtrim($key, 'z'))) {
1128
+				case 'year':
1129
+					$this->y = $value;
1130
+
1131
+					break;
1132
+
1133
+				case 'month':
1134
+					$this->m = $value;
1135
+
1136
+					break;
1137
+
1138
+				case 'week':
1139
+					$this->d = $value * static::getDaysPerWeek();
1140
+
1141
+					break;
1142
+
1143
+				case 'day':
1144
+					$this->d = $value;
1145
+
1146
+					break;
1147
+
1148
+				case 'daysexcludeweek':
1149
+				case 'dayzexcludeweek':
1150
+					$this->d = $this->weeks * static::getDaysPerWeek() + $value;
1151
+
1152
+					break;
1153
+
1154
+				case 'hour':
1155
+					$this->h = $value;
1156
+
1157
+					break;
1158
+
1159
+				case 'minute':
1160
+					$this->i = $value;
1161
+
1162
+					break;
1163
+
1164
+				case 'second':
1165
+					$this->s = $value;
1166
+
1167
+					break;
1168
+
1169
+				case 'milli':
1170
+				case 'millisecond':
1171
+					$this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
1172
+
1173
+					break;
1174
+
1175
+				case 'micro':
1176
+				case 'microsecond':
1177
+					$this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
1178
+
1179
+					break;
1180
+
1181
+				default:
1182
+					if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
1183
+						throw new UnknownSetterException($key);
1184
+					}
1185
+
1186
+					$this->$key = $value;
1187
+			}
1188
+		}
1189
+
1190
+		return $this;
1191
+	}
1192
+
1193
+	/**
1194
+	 * Set a part of the CarbonInterval object.
1195
+	 *
1196
+	 * @param string $name
1197
+	 * @param int    $value
1198
+	 *
1199
+	 * @throws UnknownSetterException
1200
+	 */
1201
+	public function __set($name, $value)
1202
+	{
1203
+		$this->set($name, $value);
1204
+	}
1205
+
1206
+	/**
1207
+	 * Allow setting of weeks and days to be cumulative.
1208
+	 *
1209
+	 * @param int $weeks Number of weeks to set
1210
+	 * @param int $days  Number of days to set
1211
+	 *
1212
+	 * @return static
1213
+	 */
1214
+	public function weeksAndDays($weeks, $days)
1215
+	{
1216
+		$this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
1217
+
1218
+		return $this;
1219
+	}
1220
+
1221
+	/**
1222
+	 * Returns true if the interval is empty for each unit.
1223
+	 *
1224
+	 * @return bool
1225
+	 */
1226
+	public function isEmpty()
1227
+	{
1228
+		return $this->years === 0 &&
1229
+			$this->months === 0 &&
1230
+			$this->dayz === 0 &&
1231
+			!$this->days &&
1232
+			$this->hours === 0 &&
1233
+			$this->minutes === 0 &&
1234
+			$this->seconds === 0 &&
1235
+			$this->microseconds === 0;
1236
+	}
1237
+
1238
+	/**
1239
+	 * Register a custom macro.
1240
+	 *
1241
+	 * @example
1242
+	 * ```
1243
+	 * CarbonInterval::macro('twice', function () {
1244
+	 *   return $this->times(2);
1245
+	 * });
1246
+	 * echo CarbonInterval::hours(2)->twice();
1247
+	 * ```
1248
+	 *
1249
+	 * @param string          $name
1250
+	 * @param object|callable $macro
1251
+	 *
1252
+	 * @return void
1253
+	 */
1254
+	public static function macro($name, $macro)
1255
+	{
1256
+		static::$macros[$name] = $macro;
1257
+	}
1258
+
1259
+	/**
1260
+	 * Register macros from a mixin object.
1261
+	 *
1262
+	 * @example
1263
+	 * ```
1264
+	 * CarbonInterval::mixin(new class {
1265
+	 *   public function daysToHours() {
1266
+	 *     return function () {
1267
+	 *       $this->hours += $this->days;
1268
+	 *       $this->days = 0;
1269
+	 *
1270
+	 *       return $this;
1271
+	 *     };
1272
+	 *   }
1273
+	 *   public function hoursToDays() {
1274
+	 *     return function () {
1275
+	 *       $this->days += $this->hours;
1276
+	 *       $this->hours = 0;
1277
+	 *
1278
+	 *       return $this;
1279
+	 *     };
1280
+	 *   }
1281
+	 * });
1282
+	 * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
1283
+	 * echo CarbonInterval::days(5)->daysToHours() . "\n";
1284
+	 * ```
1285
+	 *
1286
+	 * @param object|string $mixin
1287
+	 *
1288
+	 * @throws ReflectionException
1289
+	 *
1290
+	 * @return void
1291
+	 */
1292
+	public static function mixin($mixin)
1293
+	{
1294
+		static::baseMixin($mixin);
1295
+	}
1296
+
1297
+	/**
1298
+	 * Check if macro is registered.
1299
+	 *
1300
+	 * @param string $name
1301
+	 *
1302
+	 * @return bool
1303
+	 */
1304
+	public static function hasMacro($name)
1305
+	{
1306
+		return isset(static::$macros[$name]);
1307
+	}
1308
+
1309
+	/**
1310
+	 * Call given macro.
1311
+	 *
1312
+	 * @param string $name
1313
+	 * @param array  $parameters
1314
+	 *
1315
+	 * @return mixed
1316
+	 */
1317
+	protected function callMacro($name, $parameters)
1318
+	{
1319
+		$macro = static::$macros[$name];
1320
+
1321
+		if ($macro instanceof Closure) {
1322
+			$boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);
1323
+
1324
+			return ($boundMacro ?: $macro)(...$parameters);
1325
+		}
1326
+
1327
+		return $macro(...$parameters);
1328
+	}
1329
+
1330
+	/**
1331
+	 * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
1332
+	 *
1333
+	 * Note: This is done using the magic method to allow static and instance methods to
1334
+	 *       have the same names.
1335
+	 *
1336
+	 * @param string $method     magic method name called
1337
+	 * @param array  $parameters parameters list
1338
+	 *
1339
+	 * @throws BadFluentSetterException|Throwable
1340
+	 *
1341
+	 * @return static
1342
+	 */
1343
+	public function __call($method, $parameters)
1344
+	{
1345
+		if (static::hasMacro($method)) {
1346
+			return static::bindMacroContext($this, function () use (&$method, &$parameters) {
1347
+				return $this->callMacro($method, $parameters);
1348
+			});
1349
+		}
1350
+
1351
+		$roundedValue = $this->callRoundMethod($method, $parameters);
1352
+
1353
+		if ($roundedValue !== null) {
1354
+			return $roundedValue;
1355
+		}
1356
+
1357
+		if (preg_match('/^(?<method>add|sub)(?<unit>[A-Z].*)$/', $method, $match)) {
1358
+			return $this->{$match['method']}($parameters[0], $match['unit']);
1359
+		}
1360
+
1361
+		try {
1362
+			$this->set($method, \count($parameters) === 0 ? 1 : $parameters[0]);
1363
+		} catch (UnknownSetterException $exception) {
1364
+			if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
1365
+				throw new BadFluentSetterException($method, 0, $exception);
1366
+			}
1367
+		}
1368
+
1369
+		return $this;
1370
+	}
1371
+
1372
+	protected function getForHumansInitialVariables($syntax, $short)
1373
+	{
1374
+		if (\is_array($syntax)) {
1375
+			return $syntax;
1376
+		}
1377
+
1378
+		if (\is_int($short)) {
1379
+			return [
1380
+				'parts' => $short,
1381
+				'short' => false,
1382
+			];
1383
+		}
1384
+
1385
+		if (\is_bool($syntax)) {
1386
+			return [
1387
+				'short' => $syntax,
1388
+				'syntax' => CarbonInterface::DIFF_ABSOLUTE,
1389
+			];
1390
+		}
1391
+
1392
+		return [];
1393
+	}
1394
+
1395
+	/**
1396
+	 * @param mixed $syntax
1397
+	 * @param mixed $short
1398
+	 * @param mixed $parts
1399
+	 * @param mixed $options
1400
+	 *
1401
+	 * @return array
1402
+	 */
1403
+	protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
1404
+	{
1405
+		$optionalSpace = ' ';
1406
+		$default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
1407
+		$join = $default === '' ? '' : ' ';
1408
+		$altNumbers = false;
1409
+		$aUnit = false;
1410
+		$minimumUnit = 's';
1411
+		$skip = [];
1412
+		extract($this->getForHumansInitialVariables($syntax, $short));
1413
+		$skip = array_filter((array) $skip, static function ($value) {
1414
+			return \is_string($value) && $value !== '';
1415
+		});
1416
+
1417
+		if ($syntax === null) {
1418
+			$syntax = CarbonInterface::DIFF_ABSOLUTE;
1419
+		}
1420
+
1421
+		if ($parts === -1) {
1422
+			$parts = INF;
1423
+		}
1424
+
1425
+		if ($options === null) {
1426
+			$options = static::getHumanDiffOptions();
1427
+		}
1428
+
1429
+		if ($join === false) {
1430
+			$join = ' ';
1431
+		} elseif ($join === true) {
1432
+			$join = [
1433
+				$default,
1434
+				$this->getTranslationMessage('list.1') ?? $default,
1435
+			];
1436
+		}
1437
+
1438
+		if ($altNumbers && $altNumbers !== true) {
1439
+			$language = new Language($this->locale);
1440
+			$altNumbers = \in_array($language->getCode(), (array) $altNumbers, true);
1441
+		}
1442
+
1443
+		if (\is_array($join)) {
1444
+			[$default, $last] = $join;
1445
+
1446
+			if ($default !== ' ') {
1447
+				$optionalSpace = '';
1448
+			}
1449
+
1450
+			$join = function ($list) use ($default, $last) {
1451
+				if (\count($list) < 2) {
1452
+					return implode('', $list);
1453
+				}
1454
+
1455
+				$end = array_pop($list);
1456
+
1457
+				return implode($default, $list).$last.$end;
1458
+			};
1459
+		}
1460
+
1461
+		if (\is_string($join)) {
1462
+			if ($join !== ' ') {
1463
+				$optionalSpace = '';
1464
+			}
1465
+
1466
+			$glue = $join;
1467
+			$join = function ($list) use ($glue) {
1468
+				return implode($glue, $list);
1469
+			};
1470
+		}
1471
+
1472
+		$interpolations = [
1473
+			':optional-space' => $optionalSpace,
1474
+		];
1475
+
1476
+		return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip];
1477
+	}
1478
+
1479
+	protected static function getRoundingMethodFromOptions(int $options): ?string
1480
+	{
1481
+		if ($options & CarbonInterface::ROUND) {
1482
+			return 'round';
1483
+		}
1484
+
1485
+		if ($options & CarbonInterface::CEIL) {
1486
+			return 'ceil';
1487
+		}
1488
+
1489
+		if ($options & CarbonInterface::FLOOR) {
1490
+			return 'floor';
1491
+		}
1492
+
1493
+		return null;
1494
+	}
1495
+
1496
+	/**
1497
+	 * Returns interval values as an array where key are the unit names and values the counts.
1498
+	 *
1499
+	 * @return int[]
1500
+	 */
1501
+	public function toArray()
1502
+	{
1503
+		return [
1504
+			'years' => $this->years,
1505
+			'months' => $this->months,
1506
+			'weeks' => $this->weeks,
1507
+			'days' => $this->daysExcludeWeeks,
1508
+			'hours' => $this->hours,
1509
+			'minutes' => $this->minutes,
1510
+			'seconds' => $this->seconds,
1511
+			'microseconds' => $this->microseconds,
1512
+		];
1513
+	}
1514
+
1515
+	/**
1516
+	 * Returns interval non-zero values as an array where key are the unit names and values the counts.
1517
+	 *
1518
+	 * @return int[]
1519
+	 */
1520
+	public function getNonZeroValues()
1521
+	{
1522
+		return array_filter($this->toArray(), 'intval');
1523
+	}
1524
+
1525
+	/**
1526
+	 * Returns interval values as an array where key are the unit names and values the counts
1527
+	 * from the biggest non-zero one the the smallest non-zero one.
1528
+	 *
1529
+	 * @return int[]
1530
+	 */
1531
+	public function getValuesSequence()
1532
+	{
1533
+		$nonZeroValues = $this->getNonZeroValues();
1534
+
1535
+		if ($nonZeroValues === []) {
1536
+			return [];
1537
+		}
1538
+
1539
+		$keys = array_keys($nonZeroValues);
1540
+		$firstKey = $keys[0];
1541
+		$lastKey = $keys[\count($keys) - 1];
1542
+		$values = [];
1543
+		$record = false;
1544
+
1545
+		foreach ($this->toArray() as $unit => $count) {
1546
+			if ($unit === $firstKey) {
1547
+				$record = true;
1548
+			}
1549
+
1550
+			if ($record) {
1551
+				$values[$unit] = $count;
1552
+			}
1553
+
1554
+			if ($unit === $lastKey) {
1555
+				$record = false;
1556
+			}
1557
+		}
1558
+
1559
+		return $values;
1560
+	}
1561
+
1562
+	/**
1563
+	 * Get the current interval in a human readable format in the current locale.
1564
+	 *
1565
+	 * @example
1566
+	 * ```
1567
+	 * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
1568
+	 * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
1569
+	 * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
1570
+	 * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
1571
+	 * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
1572
+	 * echo CarbonInterval::fromString('1d 24h')->forHumans(['minimumUnit' => 'hour']) . "\n";
1573
+	 * ```
1574
+	 *
1575
+	 * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
1576
+	 *                           - 'syntax' entry (see below)
1577
+	 *                           - 'short' entry (see below)
1578
+	 *                           - 'parts' entry (see below)
1579
+	 *                           - 'options' entry (see below)
1580
+	 *                           - 'skip' entry, list of units to skip (array of strings or a single string,
1581
+	 *                           ` it can be the unit name (singular or plural) or its shortcut
1582
+	 *                           ` (y, m, w, d, h, min, s, ms, µs).
1583
+	 *                           - 'aUnit' entry, prefer "an hour" over "1 hour" if true
1584
+	 *                           - 'join' entry determines how to join multiple parts of the string
1585
+	 *                           `  - if $join is a string, it's used as a joiner glue
1586
+	 *                           `  - if $join is a callable/closure, it get the list of string and should return a string
1587
+	 *                           `  - if $join is an array, the first item will be the default glue, and the second item
1588
+	 *                           `    will be used instead of the glue for the last item
1589
+	 *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
1590
+	 *                           `  - if $join is missing, a space will be used as glue
1591
+	 *                           - 'minimumUnit' entry determines the smallest unit of time to display can be long or
1592
+	 *                           `  short form of the units, e.g. 'hour' or 'h' (default value: s)
1593
+	 *                           if int passed, it add modifiers:
1594
+	 *                           Possible values:
1595
+	 *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
1596
+	 *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
1597
+	 *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
1598
+	 *                           Default value: CarbonInterface::DIFF_ABSOLUTE
1599
+	 * @param bool      $short   displays short format of time units
1600
+	 * @param int       $parts   maximum number of parts to display (default value: -1: no limits)
1601
+	 * @param int       $options human diff options
1602
+	 *
1603
+	 * @throws Exception
1604
+	 *
1605
+	 * @return string
1606
+	 */
1607
+	public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
1608
+	{
1609
+		[$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip] = $this
1610
+			->getForHumansParameters($syntax, $short, $parts, $options);
1611
+
1612
+		$interval = [];
1613
+
1614
+		$syntax = (int) ($syntax ?? CarbonInterface::DIFF_ABSOLUTE);
1615
+		$absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
1616
+		$relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
1617
+		$count = 1;
1618
+		$unit = $short ? 's' : 'second';
1619
+		$isFuture = $this->invert === 1;
1620
+		$transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
1621
+		$declensionMode = null;
1622
+
1623
+		/** @var \Symfony\Component\Translation\Translator $translator */
1624
+		$translator = $this->getLocalTranslator();
1625
+
1626
+		$handleDeclensions = function ($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) {
1627
+			if (!$absolute) {
1628
+				$declensionMode = $declensionMode ?? $this->translate($transId.'_mode');
1629
+
1630
+				if ($this->needsDeclension($declensionMode, $index, $parts)) {
1631
+					// Some languages have special pluralization for past and future tense.
1632
+					$key = $unit.'_'.$transId;
1633
+					$result = $this->translate($key, $interpolations, $count, $translator, $altNumbers);
1634
+
1635
+					if ($result !== $key) {
1636
+						return $result;
1637
+					}
1638
+				}
1639
+			}
1640
+
1641
+			$result = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
1642
+
1643
+			if ($result !== $unit) {
1644
+				return $result;
1645
+			}
1646
+
1647
+			return null;
1648
+		};
1649
+
1650
+		$intervalValues = $this;
1651
+		$method = static::getRoundingMethodFromOptions($options);
1652
+
1653
+		if ($method) {
1654
+			$previousCount = INF;
1655
+
1656
+			while (
1657
+				\count($intervalValues->getNonZeroValues()) > $parts &&
1658
+				($count = \count($keys = array_keys($intervalValues->getValuesSequence()))) > 1
1659
+			) {
1660
+				$index = min($count, $previousCount - 1) - 2;
1661
+
1662
+				if ($index < 0) {
1663
+					break;
1664
+				}
1665
+
1666
+				$intervalValues = $this->copy()->roundUnit(
1667
+					$keys[$index],
1668
+					1,
1669
+					$method
1670
+				);
1671
+				$previousCount = $count;
1672
+			}
1673
+		}
1674
+
1675
+		$diffIntervalArray = [
1676
+			['value' => $intervalValues->years,             'unit' => 'year',        'unitShort' => 'y'],
1677
+			['value' => $intervalValues->months,            'unit' => 'month',       'unitShort' => 'm'],
1678
+			['value' => $intervalValues->weeks,             'unit' => 'week',        'unitShort' => 'w'],
1679
+			['value' => $intervalValues->daysExcludeWeeks,  'unit' => 'day',         'unitShort' => 'd'],
1680
+			['value' => $intervalValues->hours,             'unit' => 'hour',        'unitShort' => 'h'],
1681
+			['value' => $intervalValues->minutes,           'unit' => 'minute',      'unitShort' => 'min'],
1682
+			['value' => $intervalValues->seconds,           'unit' => 'second',      'unitShort' => 's'],
1683
+			['value' => $intervalValues->milliseconds,      'unit' => 'millisecond', 'unitShort' => 'ms'],
1684
+			['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'],
1685
+		];
1686
+
1687
+		if (!empty($skip)) {
1688
+			foreach ($diffIntervalArray as $index => &$unitData) {
1689
+				$nextIndex = $index + 1;
1690
+
1691
+				if ($unitData['value'] &&
1692
+					isset($diffIntervalArray[$nextIndex]) &&
1693
+					\count(array_intersect([$unitData['unit'], $unitData['unit'].'s', $unitData['unitShort']], $skip))
1694
+				) {
1695
+					$diffIntervalArray[$nextIndex]['value'] += $unitData['value'] *
1696
+						self::getFactorWithDefault($diffIntervalArray[$nextIndex]['unit'], $unitData['unit']);
1697
+					$unitData['value'] = 0;
1698
+				}
1699
+			}
1700
+		}
1701
+
1702
+		$transChoice = function ($short, $unitData, $index, $parts) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
1703
+			$count = $unitData['value'];
1704
+
1705
+			if ($short) {
1706
+				$result = $handleDeclensions($unitData['unitShort'], $count, $index, $parts);
1707
+
1708
+				if ($result !== null) {
1709
+					return $result;
1710
+				}
1711
+			} elseif ($aUnit) {
1712
+				$result = $handleDeclensions('a_'.$unitData['unit'], $count, $index, $parts);
1713
+
1714
+				if ($result !== null) {
1715
+					return $result;
1716
+				}
1717
+			}
1718
+
1719
+			if (!$absolute) {
1720
+				return $handleDeclensions($unitData['unit'], $count, $index, $parts);
1721
+			}
1722
+
1723
+			return $this->translate($unitData['unit'], $interpolations, $count, $translator, $altNumbers);
1724
+		};
1725
+
1726
+		$fallbackUnit = ['second', 's'];
1727
+
1728
+		foreach ($diffIntervalArray as $diffIntervalData) {
1729
+			if ($diffIntervalData['value'] > 0) {
1730
+				$unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
1731
+				$count = $diffIntervalData['value'];
1732
+				$interval[] = [$short, $diffIntervalData];
1733
+			} elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && \count($interval) > 0) {
1734
+				break;
1735
+			}
1736
+
1737
+			// break the loop after we get the required number of parts in array
1738
+			if (\count($interval) >= $parts) {
1739
+				break;
1740
+			}
1741
+
1742
+			// break the loop after we have reached the minimum unit
1743
+			if (\in_array($minimumUnit, [$diffIntervalData['unit'], $diffIntervalData['unitShort']], true)) {
1744
+				$fallbackUnit = [$diffIntervalData['unit'], $diffIntervalData['unitShort']];
1745
+
1746
+				break;
1747
+			}
1748
+		}
1749
+
1750
+		$actualParts = \count($interval);
1751
+
1752
+		foreach ($interval as $index => &$item) {
1753
+			$item = $transChoice($item[0], $item[1], $index, $actualParts);
1754
+		}
1755
+
1756
+		if (\count($interval) === 0) {
1757
+			if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
1758
+				$key = 'diff_now';
1759
+				$translation = $this->translate($key, $interpolations, null, $translator);
1760
+
1761
+				if ($translation !== $key) {
1762
+					return $translation;
1763
+				}
1764
+			}
1765
+
1766
+			$count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
1767
+			$unit = $fallbackUnit[$short ? 1 : 0];
1768
+			$interval[] = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
1769
+		}
1770
+
1771
+		// join the interval parts by a space
1772
+		$time = $join($interval);
1773
+
1774
+		unset($diffIntervalArray, $interval);
1775
+
1776
+		if ($absolute) {
1777
+			return $time;
1778
+		}
1779
+
1780
+		$isFuture = $this->invert === 1;
1781
+
1782
+		$transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
1783
+
1784
+		if ($parts === 1) {
1785
+			if ($relativeToNow && $unit === 'day') {
1786
+				if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
1787
+					$key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
1788
+					$translation = $this->translate($key, $interpolations, null, $translator);
1789
+
1790
+					if ($translation !== $key) {
1791
+						return $translation;
1792
+					}
1793
+				}
1794
+
1795
+				if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
1796
+					$key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
1797
+					$translation = $this->translate($key, $interpolations, null, $translator);
1798
+
1799
+					if ($translation !== $key) {
1800
+						return $translation;
1801
+					}
1802
+				}
1803
+			}
1804
+
1805
+			$aTime = $aUnit ? $handleDeclensions('a_'.$unit, $count) : null;
1806
+
1807
+			$time = $aTime ?: $handleDeclensions($unit, $count) ?: $time;
1808
+		}
1809
+
1810
+		$time = [':time' => $time];
1811
+
1812
+		return $this->translate($transId, array_merge($time, $interpolations, $time), null, $translator);
1813
+	}
1814
+
1815
+	/**
1816
+	 * Format the instance as a string using the forHumans() function.
1817
+	 *
1818
+	 * @throws Exception
1819
+	 *
1820
+	 * @return string
1821
+	 */
1822
+	public function __toString()
1823
+	{
1824
+		$format = $this->localToStringFormat;
1825
+
1826
+		if (!$format) {
1827
+			return $this->forHumans();
1828
+		}
1829
+
1830
+		if ($format instanceof Closure) {
1831
+			return $format($this);
1832
+		}
1833
+
1834
+		return $this->format($format);
1835
+	}
1836
+
1837
+	/**
1838
+	 * Return native DateInterval PHP object matching the current instance.
1839
+	 *
1840
+	 * @example
1841
+	 * ```
1842
+	 * var_dump(CarbonInterval::hours(2)->toDateInterval());
1843
+	 * ```
1844
+	 *
1845
+	 * @return DateInterval
1846
+	 */
1847
+	public function toDateInterval()
1848
+	{
1849
+		return self::castIntervalToClass($this, DateInterval::class);
1850
+	}
1851
+
1852
+	/**
1853
+	 * Convert the interval to a CarbonPeriod.
1854
+	 *
1855
+	 * @param DateTimeInterface|string|int ...$params Start date, [end date or recurrences] and optional settings.
1856
+	 *
1857
+	 * @return CarbonPeriod
1858
+	 */
1859
+	public function toPeriod(...$params)
1860
+	{
1861
+		if ($this->tzName) {
1862
+			$tz = \is_string($this->tzName) ? new DateTimeZone($this->tzName) : $this->tzName;
1863
+
1864
+			if ($tz instanceof DateTimeZone) {
1865
+				array_unshift($params, $tz);
1866
+			}
1867
+		}
1868
+
1869
+		return CarbonPeriod::create($this, ...$params);
1870
+	}
1871
+
1872
+	/**
1873
+	 * Invert the interval.
1874
+	 *
1875
+	 * @param bool|int $inverted if a parameter is passed, the passed value casted as 1 or 0 is used
1876
+	 *                           as the new value of the ->invert property.
1877
+	 *
1878
+	 * @return $this
1879
+	 */
1880
+	public function invert($inverted = null)
1881
+	{
1882
+		$this->invert = (\func_num_args() === 0 ? !$this->invert : $inverted) ? 1 : 0;
1883
+
1884
+		return $this;
1885
+	}
1886
+
1887
+	protected function solveNegativeInterval()
1888
+	{
1889
+		if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
1890
+			$this->years *= -1;
1891
+			$this->months *= -1;
1892
+			$this->dayz *= -1;
1893
+			$this->hours *= -1;
1894
+			$this->minutes *= -1;
1895
+			$this->seconds *= -1;
1896
+			$this->microseconds *= -1;
1897
+			$this->invert();
1898
+		}
1899
+
1900
+		return $this;
1901
+	}
1902
+
1903
+	/**
1904
+	 * Add the passed interval to the current instance.
1905
+	 *
1906
+	 * @param string|DateInterval $unit
1907
+	 * @param int|float           $value
1908
+	 *
1909
+	 * @return $this
1910
+	 */
1911
+	public function add($unit, $value = 1)
1912
+	{
1913
+		if (is_numeric($unit)) {
1914
+			[$value, $unit] = [$unit, $value];
1915
+		}
1916
+
1917
+		if (\is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
1918
+			$unit = "$value $unit";
1919
+			$value = 1;
1920
+		}
1921
+
1922
+		$interval = static::make($unit);
1923
+
1924
+		if (!$interval) {
1925
+			throw new InvalidIntervalException('This type of data cannot be added/subtracted.');
1926
+		}
1927
+
1928
+		if ($value !== 1) {
1929
+			$interval->times($value);
1930
+		}
1931
+
1932
+		$sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
1933
+		$this->years += $interval->y * $sign;
1934
+		$this->months += $interval->m * $sign;
1935
+		$this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
1936
+		$this->hours += $interval->h * $sign;
1937
+		$this->minutes += $interval->i * $sign;
1938
+		$this->seconds += $interval->s * $sign;
1939
+		$this->microseconds += $interval->microseconds * $sign;
1940
+
1941
+		$this->solveNegativeInterval();
1942
+
1943
+		return $this;
1944
+	}
1945
+
1946
+	/**
1947
+	 * Subtract the passed interval to the current instance.
1948
+	 *
1949
+	 * @param string|DateInterval $unit
1950
+	 * @param int|float           $value
1951
+	 *
1952
+	 * @return $this
1953
+	 */
1954
+	public function sub($unit, $value = 1)
1955
+	{
1956
+		if (is_numeric($unit)) {
1957
+			[$value, $unit] = [$unit, $value];
1958
+		}
1959
+
1960
+		return $this->add($unit, -(float) $value);
1961
+	}
1962
+
1963
+	/**
1964
+	 * Subtract the passed interval to the current instance.
1965
+	 *
1966
+	 * @param string|DateInterval $unit
1967
+	 * @param int|float           $value
1968
+	 *
1969
+	 * @return $this
1970
+	 */
1971
+	public function subtract($unit, $value = 1)
1972
+	{
1973
+		return $this->sub($unit, $value);
1974
+	}
1975
+
1976
+	/**
1977
+	 * Add given parameters to the current interval.
1978
+	 *
1979
+	 * @param int       $years
1980
+	 * @param int       $months
1981
+	 * @param int|float $weeks
1982
+	 * @param int|float $days
1983
+	 * @param int|float $hours
1984
+	 * @param int|float $minutes
1985
+	 * @param int|float $seconds
1986
+	 * @param int|float $microseconds
1987
+	 *
1988
+	 * @return $this
1989
+	 */
1990
+	public function plus(
1991
+		$years = 0,
1992
+		$months = 0,
1993
+		$weeks = 0,
1994
+		$days = 0,
1995
+		$hours = 0,
1996
+		$minutes = 0,
1997
+		$seconds = 0,
1998
+		$microseconds = 0
1999
+	): self {
2000
+		return $this->add("
2001 2001
             $years years $months months $weeks weeks $days days
2002 2002
             $hours hours $minutes minutes $seconds seconds $microseconds microseconds
2003 2003
         ");
2004
-    }
2005
-
2006
-    /**
2007
-     * Add given parameters to the current interval.
2008
-     *
2009
-     * @param int       $years
2010
-     * @param int       $months
2011
-     * @param int|float $weeks
2012
-     * @param int|float $days
2013
-     * @param int|float $hours
2014
-     * @param int|float $minutes
2015
-     * @param int|float $seconds
2016
-     * @param int|float $microseconds
2017
-     *
2018
-     * @return $this
2019
-     */
2020
-    public function minus(
2021
-        $years = 0,
2022
-        $months = 0,
2023
-        $weeks = 0,
2024
-        $days = 0,
2025
-        $hours = 0,
2026
-        $minutes = 0,
2027
-        $seconds = 0,
2028
-        $microseconds = 0
2029
-    ): self {
2030
-        return $this->sub("
2004
+	}
2005
+
2006
+	/**
2007
+	 * Add given parameters to the current interval.
2008
+	 *
2009
+	 * @param int       $years
2010
+	 * @param int       $months
2011
+	 * @param int|float $weeks
2012
+	 * @param int|float $days
2013
+	 * @param int|float $hours
2014
+	 * @param int|float $minutes
2015
+	 * @param int|float $seconds
2016
+	 * @param int|float $microseconds
2017
+	 *
2018
+	 * @return $this
2019
+	 */
2020
+	public function minus(
2021
+		$years = 0,
2022
+		$months = 0,
2023
+		$weeks = 0,
2024
+		$days = 0,
2025
+		$hours = 0,
2026
+		$minutes = 0,
2027
+		$seconds = 0,
2028
+		$microseconds = 0
2029
+	): self {
2030
+		return $this->sub("
2031 2031
             $years years $months months $weeks weeks $days days
2032 2032
             $hours hours $minutes minutes $seconds seconds $microseconds microseconds
2033 2033
         ");
2034
-    }
2035
-
2036
-    /**
2037
-     * Multiply current instance given number of times. times() is naive, it multiplies each unit
2038
-     * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
2039
-     * separately for each unit.
2040
-     *
2041
-     * Use times() when you want a fast and approximated calculation that does not cascade units.
2042
-     *
2043
-     * For a precise and cascaded calculation,
2044
-     *
2045
-     * @see multiply()
2046
-     *
2047
-     * @param float|int $factor
2048
-     *
2049
-     * @return $this
2050
-     */
2051
-    public function times($factor)
2052
-    {
2053
-        if ($factor < 0) {
2054
-            $this->invert = $this->invert ? 0 : 1;
2055
-            $factor = -$factor;
2056
-        }
2057
-
2058
-        $this->years = (int) round($this->years * $factor);
2059
-        $this->months = (int) round($this->months * $factor);
2060
-        $this->dayz = (int) round($this->dayz * $factor);
2061
-        $this->hours = (int) round($this->hours * $factor);
2062
-        $this->minutes = (int) round($this->minutes * $factor);
2063
-        $this->seconds = (int) round($this->seconds * $factor);
2064
-        $this->microseconds = (int) round($this->microseconds * $factor);
2065
-
2066
-        return $this;
2067
-    }
2068
-
2069
-    /**
2070
-     * Divide current instance by a given divider. shares() is naive, it divides each unit separately
2071
-     * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
2072
-     * and 7 minutes.
2073
-     *
2074
-     * Use shares() when you want a fast and approximated calculation that does not cascade units.
2075
-     *
2076
-     * For a precise and cascaded calculation,
2077
-     *
2078
-     * @see divide()
2079
-     *
2080
-     * @param float|int $divider
2081
-     *
2082
-     * @return $this
2083
-     */
2084
-    public function shares($divider)
2085
-    {
2086
-        return $this->times(1 / $divider);
2087
-    }
2088
-
2089
-    protected function copyProperties(self $interval, $ignoreSign = false)
2090
-    {
2091
-        $this->years = $interval->years;
2092
-        $this->months = $interval->months;
2093
-        $this->dayz = $interval->dayz;
2094
-        $this->hours = $interval->hours;
2095
-        $this->minutes = $interval->minutes;
2096
-        $this->seconds = $interval->seconds;
2097
-        $this->microseconds = $interval->microseconds;
2098
-
2099
-        if (!$ignoreSign) {
2100
-            $this->invert = $interval->invert;
2101
-        }
2102
-
2103
-        return $this;
2104
-    }
2105
-
2106
-    /**
2107
-     * Multiply and cascade current instance by a given factor.
2108
-     *
2109
-     * @param float|int $factor
2110
-     *
2111
-     * @return $this
2112
-     */
2113
-    public function multiply($factor)
2114
-    {
2115
-        if ($factor < 0) {
2116
-            $this->invert = $this->invert ? 0 : 1;
2117
-            $factor = -$factor;
2118
-        }
2119
-
2120
-        $yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision
2121
-
2122
-        if ($yearPart) {
2123
-            $this->years -= $yearPart / $factor;
2124
-        }
2125
-
2126
-        return $this->copyProperties(
2127
-            static::create($yearPart)
2128
-                ->microseconds(abs($this->totalMicroseconds) * $factor)
2129
-                ->cascade(),
2130
-            true
2131
-        );
2132
-    }
2133
-
2134
-    /**
2135
-     * Divide and cascade current instance by a given divider.
2136
-     *
2137
-     * @param float|int $divider
2138
-     *
2139
-     * @return $this
2140
-     */
2141
-    public function divide($divider)
2142
-    {
2143
-        return $this->multiply(1 / $divider);
2144
-    }
2145
-
2146
-    /**
2147
-     * Get the interval_spec string of a date interval.
2148
-     *
2149
-     * @param DateInterval $interval
2150
-     *
2151
-     * @return string
2152
-     */
2153
-    public static function getDateIntervalSpec(DateInterval $interval, bool $microseconds = false)
2154
-    {
2155
-        $date = array_filter([
2156
-            static::PERIOD_YEARS => abs($interval->y),
2157
-            static::PERIOD_MONTHS => abs($interval->m),
2158
-            static::PERIOD_DAYS => abs($interval->d),
2159
-        ]);
2160
-
2161
-        $seconds = abs($interval->s);
2162
-        if ($microseconds && $interval->f > 0) {
2163
-            $seconds = sprintf('%d.%06d', $seconds, abs($interval->f) * 1000000);
2164
-        }
2165
-
2166
-        $time = array_filter([
2167
-            static::PERIOD_HOURS => abs($interval->h),
2168
-            static::PERIOD_MINUTES => abs($interval->i),
2169
-            static::PERIOD_SECONDS => $seconds,
2170
-        ]);
2171
-
2172
-        $specString = static::PERIOD_PREFIX;
2173
-
2174
-        foreach ($date as $key => $value) {
2175
-            $specString .= $value.$key;
2176
-        }
2177
-
2178
-        if (\count($time) > 0) {
2179
-            $specString .= static::PERIOD_TIME_PREFIX;
2180
-            foreach ($time as $key => $value) {
2181
-                $specString .= $value.$key;
2182
-            }
2183
-        }
2184
-
2185
-        return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
2186
-    }
2187
-
2188
-    /**
2189
-     * Get the interval_spec string.
2190
-     *
2191
-     * @return string
2192
-     */
2193
-    public function spec(bool $microseconds = false)
2194
-    {
2195
-        return static::getDateIntervalSpec($this, $microseconds);
2196
-    }
2197
-
2198
-    /**
2199
-     * Comparing 2 date intervals.
2200
-     *
2201
-     * @param DateInterval $first
2202
-     * @param DateInterval $second
2203
-     *
2204
-     * @return int
2205
-     */
2206
-    public static function compareDateIntervals(DateInterval $first, DateInterval $second)
2207
-    {
2208
-        $current = Carbon::now();
2209
-        $passed = $current->avoidMutation()->add($second);
2210
-        $current->add($first);
2211
-
2212
-        if ($current < $passed) {
2213
-            return -1;
2214
-        }
2215
-        if ($current > $passed) {
2216
-            return 1;
2217
-        }
2218
-
2219
-        return 0;
2220
-    }
2221
-
2222
-    /**
2223
-     * Comparing with passed interval.
2224
-     *
2225
-     * @param DateInterval $interval
2226
-     *
2227
-     * @return int
2228
-     */
2229
-    public function compare(DateInterval $interval)
2230
-    {
2231
-        return static::compareDateIntervals($this, $interval);
2232
-    }
2233
-
2234
-    private function invertCascade(array $values)
2235
-    {
2236
-        return $this->set(array_map(function ($value) {
2237
-            return -$value;
2238
-        }, $values))->doCascade(true)->invert();
2239
-    }
2240
-
2241
-    private function doCascade(bool $deep)
2242
-    {
2243
-        $originalData = $this->toArray();
2244
-        $originalData['milliseconds'] = (int) ($originalData['microseconds'] / static::getMicrosecondsPerMillisecond());
2245
-        $originalData['microseconds'] = $originalData['microseconds'] % static::getMicrosecondsPerMillisecond();
2246
-        $originalData['daysExcludeWeeks'] = $originalData['days'];
2247
-        unset($originalData['days']);
2248
-        $newData = $originalData;
2249
-
2250
-        foreach (self::getFlipCascadeFactors() as $source => [$target, $factor]) {
2251
-            foreach (['source', 'target'] as $key) {
2252
-                if ($$key === 'dayz') {
2253
-                    $$key = 'daysExcludeWeeks';
2254
-                }
2255
-            }
2256
-
2257
-            $value = $newData[$source];
2258
-            $modulo = ($factor + ($value % $factor)) % $factor;
2259
-            $newData[$source] = $modulo;
2260
-            $newData[$target] += ($value - $modulo) / $factor;
2261
-        }
2262
-
2263
-        $positive = null;
2264
-
2265
-        if (!$deep) {
2266
-            foreach ($newData as $value) {
2267
-                if ($value) {
2268
-                    if ($positive === null) {
2269
-                        $positive = ($value > 0);
2270
-
2271
-                        continue;
2272
-                    }
2273
-
2274
-                    if (($value > 0) !== $positive) {
2275
-                        return $this->invertCascade($originalData)
2276
-                            ->solveNegativeInterval();
2277
-                    }
2278
-                }
2279
-            }
2280
-        }
2281
-
2282
-        return $this->set($newData)
2283
-            ->solveNegativeInterval();
2284
-    }
2285
-
2286
-    /**
2287
-     * Convert overflowed values into bigger units.
2288
-     *
2289
-     * @return $this
2290
-     */
2291
-    public function cascade()
2292
-    {
2293
-        return $this->doCascade(false);
2294
-    }
2295
-
2296
-    public function hasNegativeValues(): bool
2297
-    {
2298
-        foreach ($this->toArray() as $value) {
2299
-            if ($value < 0) {
2300
-                return true;
2301
-            }
2302
-        }
2303
-
2304
-        return false;
2305
-    }
2306
-
2307
-    public function hasPositiveValues(): bool
2308
-    {
2309
-        foreach ($this->toArray() as $value) {
2310
-            if ($value > 0) {
2311
-                return true;
2312
-            }
2313
-        }
2314
-
2315
-        return false;
2316
-    }
2317
-
2318
-    /**
2319
-     * Get amount of given unit equivalent to the interval.
2320
-     *
2321
-     * @param string $unit
2322
-     *
2323
-     * @throws UnknownUnitException|UnitNotConfiguredException
2324
-     *
2325
-     * @return float
2326
-     */
2327
-    public function total($unit)
2328
-    {
2329
-        $realUnit = $unit = strtolower($unit);
2330
-
2331
-        if (\in_array($unit, ['days', 'weeks'])) {
2332
-            $realUnit = 'dayz';
2333
-        } elseif (!\in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
2334
-            throw new UnknownUnitException($unit);
2335
-        }
2336
-
2337
-        $result = 0;
2338
-        $cumulativeFactor = 0;
2339
-        $unitFound = false;
2340
-        $factors = self::getFlipCascadeFactors();
2341
-        $daysPerWeek = static::getDaysPerWeek();
2342
-
2343
-        $values = [
2344
-            'years' => $this->years,
2345
-            'months' => $this->months,
2346
-            'weeks' => (int) ($this->d / $daysPerWeek),
2347
-            'dayz' => $this->d % $daysPerWeek,
2348
-            'hours' => $this->hours,
2349
-            'minutes' => $this->minutes,
2350
-            'seconds' => $this->seconds,
2351
-            'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
2352
-            'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND,
2353
-        ];
2354
-
2355
-        if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {
2356
-            $values['dayz'] += $values['weeks'] * $daysPerWeek;
2357
-            $values['weeks'] = 0;
2358
-        }
2359
-
2360
-        foreach ($factors as $source => [$target, $factor]) {
2361
-            if ($source === $realUnit) {
2362
-                $unitFound = true;
2363
-                $value = $values[$source];
2364
-                $result += $value;
2365
-                $cumulativeFactor = 1;
2366
-            }
2367
-
2368
-            if ($factor === false) {
2369
-                if ($unitFound) {
2370
-                    break;
2371
-                }
2372
-
2373
-                $result = 0;
2374
-                $cumulativeFactor = 0;
2375
-
2376
-                continue;
2377
-            }
2378
-
2379
-            if ($target === $realUnit) {
2380
-                $unitFound = true;
2381
-            }
2382
-
2383
-            if ($cumulativeFactor) {
2384
-                $cumulativeFactor *= $factor;
2385
-                $result += $values[$target] * $cumulativeFactor;
2386
-
2387
-                continue;
2388
-            }
2389
-
2390
-            $value = $values[$source];
2391
-
2392
-            $result = ($result + $value) / $factor;
2393
-        }
2394
-
2395
-        if (isset($target) && !$cumulativeFactor) {
2396
-            $result += $values[$target];
2397
-        }
2398
-
2399
-        if (!$unitFound) {
2400
-            throw new UnitNotConfiguredException($unit);
2401
-        }
2402
-
2403
-        if ($this->invert) {
2404
-            $result *= -1;
2405
-        }
2406
-
2407
-        if ($unit === 'weeks') {
2408
-            return $result / $daysPerWeek;
2409
-        }
2410
-
2411
-        return $result;
2412
-    }
2413
-
2414
-    /**
2415
-     * Determines if the instance is equal to another
2416
-     *
2417
-     * @param CarbonInterval|DateInterval|mixed $interval
2418
-     *
2419
-     * @see equalTo()
2420
-     *
2421
-     * @return bool
2422
-     */
2423
-    public function eq($interval): bool
2424
-    {
2425
-        return $this->equalTo($interval);
2426
-    }
2427
-
2428
-    /**
2429
-     * Determines if the instance is equal to another
2430
-     *
2431
-     * @param CarbonInterval|DateInterval|mixed $interval
2432
-     *
2433
-     * @return bool
2434
-     */
2435
-    public function equalTo($interval): bool
2436
-    {
2437
-        $interval = $this->resolveInterval($interval);
2438
-
2439
-        return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds;
2440
-    }
2441
-
2442
-    /**
2443
-     * Determines if the instance is not equal to another
2444
-     *
2445
-     * @param CarbonInterval|DateInterval|mixed $interval
2446
-     *
2447
-     * @see notEqualTo()
2448
-     *
2449
-     * @return bool
2450
-     */
2451
-    public function ne($interval): bool
2452
-    {
2453
-        return $this->notEqualTo($interval);
2454
-    }
2455
-
2456
-    /**
2457
-     * Determines if the instance is not equal to another
2458
-     *
2459
-     * @param CarbonInterval|DateInterval|mixed $interval
2460
-     *
2461
-     * @return bool
2462
-     */
2463
-    public function notEqualTo($interval): bool
2464
-    {
2465
-        return !$this->eq($interval);
2466
-    }
2467
-
2468
-    /**
2469
-     * Determines if the instance is greater (longer) than another
2470
-     *
2471
-     * @param CarbonInterval|DateInterval|mixed $interval
2472
-     *
2473
-     * @see greaterThan()
2474
-     *
2475
-     * @return bool
2476
-     */
2477
-    public function gt($interval): bool
2478
-    {
2479
-        return $this->greaterThan($interval);
2480
-    }
2481
-
2482
-    /**
2483
-     * Determines if the instance is greater (longer) than another
2484
-     *
2485
-     * @param CarbonInterval|DateInterval|mixed $interval
2486
-     *
2487
-     * @return bool
2488
-     */
2489
-    public function greaterThan($interval): bool
2490
-    {
2491
-        $interval = $this->resolveInterval($interval);
2492
-
2493
-        return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
2494
-    }
2495
-
2496
-    /**
2497
-     * Determines if the instance is greater (longer) than or equal to another
2498
-     *
2499
-     * @param CarbonInterval|DateInterval|mixed $interval
2500
-     *
2501
-     * @see greaterThanOrEqualTo()
2502
-     *
2503
-     * @return bool
2504
-     */
2505
-    public function gte($interval): bool
2506
-    {
2507
-        return $this->greaterThanOrEqualTo($interval);
2508
-    }
2509
-
2510
-    /**
2511
-     * Determines if the instance is greater (longer) than or equal to another
2512
-     *
2513
-     * @param CarbonInterval|DateInterval|mixed $interval
2514
-     *
2515
-     * @return bool
2516
-     */
2517
-    public function greaterThanOrEqualTo($interval): bool
2518
-    {
2519
-        return $this->greaterThan($interval) || $this->equalTo($interval);
2520
-    }
2521
-
2522
-    /**
2523
-     * Determines if the instance is less (shorter) than another
2524
-     *
2525
-     * @param CarbonInterval|DateInterval|mixed $interval
2526
-     *
2527
-     * @see lessThan()
2528
-     *
2529
-     * @return bool
2530
-     */
2531
-    public function lt($interval): bool
2532
-    {
2533
-        return $this->lessThan($interval);
2534
-    }
2535
-
2536
-    /**
2537
-     * Determines if the instance is less (shorter) than another
2538
-     *
2539
-     * @param CarbonInterval|DateInterval|mixed $interval
2540
-     *
2541
-     * @return bool
2542
-     */
2543
-    public function lessThan($interval): bool
2544
-    {
2545
-        $interval = $this->resolveInterval($interval);
2546
-
2547
-        return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
2548
-    }
2549
-
2550
-    /**
2551
-     * Determines if the instance is less (shorter) than or equal to another
2552
-     *
2553
-     * @param CarbonInterval|DateInterval|mixed $interval
2554
-     *
2555
-     * @see lessThanOrEqualTo()
2556
-     *
2557
-     * @return bool
2558
-     */
2559
-    public function lte($interval): bool
2560
-    {
2561
-        return $this->lessThanOrEqualTo($interval);
2562
-    }
2563
-
2564
-    /**
2565
-     * Determines if the instance is less (shorter) than or equal to another
2566
-     *
2567
-     * @param CarbonInterval|DateInterval|mixed $interval
2568
-     *
2569
-     * @return bool
2570
-     */
2571
-    public function lessThanOrEqualTo($interval): bool
2572
-    {
2573
-        return $this->lessThan($interval) || $this->equalTo($interval);
2574
-    }
2575
-
2576
-    /**
2577
-     * Determines if the instance is between two others.
2578
-     *
2579
-     * The third argument allow you to specify if bounds are included or not (true by default)
2580
-     * but for when you including/excluding bounds may produce different results in your application,
2581
-     * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
2582
-     *
2583
-     * @example
2584
-     * ```
2585
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
2586
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2587
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
2588
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
2589
-     * ```
2590
-     *
2591
-     * @param CarbonInterval|DateInterval|mixed $interval1
2592
-     * @param CarbonInterval|DateInterval|mixed $interval2
2593
-     * @param bool                              $equal     Indicates if an equal to comparison should be done
2594
-     *
2595
-     * @return bool
2596
-     */
2597
-    public function between($interval1, $interval2, $equal = true): bool
2598
-    {
2599
-        return $equal
2600
-            ? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
2601
-            : $this->greaterThan($interval1) && $this->lessThan($interval2);
2602
-    }
2603
-
2604
-    /**
2605
-     * Determines if the instance is between two others, bounds excluded.
2606
-     *
2607
-     * @example
2608
-     * ```
2609
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
2610
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2611
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // true
2612
-     * ```
2613
-     *
2614
-     * @param CarbonInterval|DateInterval|mixed $interval1
2615
-     * @param CarbonInterval|DateInterval|mixed $interval2
2616
-     *
2617
-     * @return bool
2618
-     */
2619
-    public function betweenIncluded($interval1, $interval2): bool
2620
-    {
2621
-        return $this->between($interval1, $interval2, true);
2622
-    }
2623
-
2624
-    /**
2625
-     * Determines if the instance is between two others, bounds excluded.
2626
-     *
2627
-     * @example
2628
-     * ```
2629
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
2630
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2631
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
2632
-     * ```
2633
-     *
2634
-     * @param CarbonInterval|DateInterval|mixed $interval1
2635
-     * @param CarbonInterval|DateInterval|mixed $interval2
2636
-     *
2637
-     * @return bool
2638
-     */
2639
-    public function betweenExcluded($interval1, $interval2): bool
2640
-    {
2641
-        return $this->between($interval1, $interval2, false);
2642
-    }
2643
-
2644
-    /**
2645
-     * Determines if the instance is between two others
2646
-     *
2647
-     * @example
2648
-     * ```
2649
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
2650
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2651
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
2652
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
2653
-     * ```
2654
-     *
2655
-     * @param CarbonInterval|DateInterval|mixed $interval1
2656
-     * @param CarbonInterval|DateInterval|mixed $interval2
2657
-     * @param bool                              $equal     Indicates if an equal to comparison should be done
2658
-     *
2659
-     * @return bool
2660
-     */
2661
-    public function isBetween($interval1, $interval2, $equal = true): bool
2662
-    {
2663
-        return $this->between($interval1, $interval2, $equal);
2664
-    }
2665
-
2666
-    /**
2667
-     * Round the current instance at the given unit with given precision if specified and the given function.
2668
-     *
2669
-     * @param string                             $unit
2670
-     * @param float|int|string|DateInterval|null $precision
2671
-     * @param string                             $function
2672
-     *
2673
-     * @throws Exception
2674
-     *
2675
-     * @return $this
2676
-     */
2677
-    public function roundUnit($unit, $precision = 1, $function = 'round')
2678
-    {
2679
-        $base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC')
2680
-            ->roundUnit($unit, $precision, $function);
2681
-        $next = $base->add($this);
2682
-        $inverted = $next < $base;
2683
-
2684
-        if ($inverted) {
2685
-            $next = $base->sub($this);
2686
-        }
2687
-
2688
-        $this->copyProperties(
2689
-            $next
2690
-                ->roundUnit($unit, $precision, $function)
2691
-                ->diffAsCarbonInterval($base)
2692
-        );
2693
-
2694
-        return $this->invert($inverted);
2695
-    }
2696
-
2697
-    /**
2698
-     * Truncate the current instance at the given unit with given precision if specified.
2699
-     *
2700
-     * @param string                             $unit
2701
-     * @param float|int|string|DateInterval|null $precision
2702
-     *
2703
-     * @throws Exception
2704
-     *
2705
-     * @return $this
2706
-     */
2707
-    public function floorUnit($unit, $precision = 1)
2708
-    {
2709
-        return $this->roundUnit($unit, $precision, 'floor');
2710
-    }
2711
-
2712
-    /**
2713
-     * Ceil the current instance at the given unit with given precision if specified.
2714
-     *
2715
-     * @param string                             $unit
2716
-     * @param float|int|string|DateInterval|null $precision
2717
-     *
2718
-     * @throws Exception
2719
-     *
2720
-     * @return $this
2721
-     */
2722
-    public function ceilUnit($unit, $precision = 1)
2723
-    {
2724
-        return $this->roundUnit($unit, $precision, 'ceil');
2725
-    }
2726
-
2727
-    /**
2728
-     * Round the current instance second with given precision if specified.
2729
-     *
2730
-     * @param float|int|string|DateInterval|null $precision
2731
-     * @param string                             $function
2732
-     *
2733
-     * @throws Exception
2734
-     *
2735
-     * @return $this
2736
-     */
2737
-    public function round($precision = 1, $function = 'round')
2738
-    {
2739
-        return $this->roundWith($precision, $function);
2740
-    }
2741
-
2742
-    /**
2743
-     * Round the current instance second with given precision if specified.
2744
-     *
2745
-     * @param float|int|string|DateInterval|null $precision
2746
-     *
2747
-     * @throws Exception
2748
-     *
2749
-     * @return $this
2750
-     */
2751
-    public function floor($precision = 1)
2752
-    {
2753
-        return $this->round($precision, 'floor');
2754
-    }
2755
-
2756
-    /**
2757
-     * Ceil the current instance second with given precision if specified.
2758
-     *
2759
-     * @param float|int|string|DateInterval|null $precision
2760
-     *
2761
-     * @throws Exception
2762
-     *
2763
-     * @return $this
2764
-     */
2765
-    public function ceil($precision = 1)
2766
-    {
2767
-        return $this->round($precision, 'ceil');
2768
-    }
2769
-
2770
-    private function needsDeclension(string $mode, int $index, int $parts): bool
2771
-    {
2772
-        switch ($mode) {
2773
-            case 'last':
2774
-                return $index === $parts - 1;
2775
-            default:
2776
-                return true;
2777
-        }
2778
-    }
2034
+	}
2035
+
2036
+	/**
2037
+	 * Multiply current instance given number of times. times() is naive, it multiplies each unit
2038
+	 * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
2039
+	 * separately for each unit.
2040
+	 *
2041
+	 * Use times() when you want a fast and approximated calculation that does not cascade units.
2042
+	 *
2043
+	 * For a precise and cascaded calculation,
2044
+	 *
2045
+	 * @see multiply()
2046
+	 *
2047
+	 * @param float|int $factor
2048
+	 *
2049
+	 * @return $this
2050
+	 */
2051
+	public function times($factor)
2052
+	{
2053
+		if ($factor < 0) {
2054
+			$this->invert = $this->invert ? 0 : 1;
2055
+			$factor = -$factor;
2056
+		}
2057
+
2058
+		$this->years = (int) round($this->years * $factor);
2059
+		$this->months = (int) round($this->months * $factor);
2060
+		$this->dayz = (int) round($this->dayz * $factor);
2061
+		$this->hours = (int) round($this->hours * $factor);
2062
+		$this->minutes = (int) round($this->minutes * $factor);
2063
+		$this->seconds = (int) round($this->seconds * $factor);
2064
+		$this->microseconds = (int) round($this->microseconds * $factor);
2065
+
2066
+		return $this;
2067
+	}
2068
+
2069
+	/**
2070
+	 * Divide current instance by a given divider. shares() is naive, it divides each unit separately
2071
+	 * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
2072
+	 * and 7 minutes.
2073
+	 *
2074
+	 * Use shares() when you want a fast and approximated calculation that does not cascade units.
2075
+	 *
2076
+	 * For a precise and cascaded calculation,
2077
+	 *
2078
+	 * @see divide()
2079
+	 *
2080
+	 * @param float|int $divider
2081
+	 *
2082
+	 * @return $this
2083
+	 */
2084
+	public function shares($divider)
2085
+	{
2086
+		return $this->times(1 / $divider);
2087
+	}
2088
+
2089
+	protected function copyProperties(self $interval, $ignoreSign = false)
2090
+	{
2091
+		$this->years = $interval->years;
2092
+		$this->months = $interval->months;
2093
+		$this->dayz = $interval->dayz;
2094
+		$this->hours = $interval->hours;
2095
+		$this->minutes = $interval->minutes;
2096
+		$this->seconds = $interval->seconds;
2097
+		$this->microseconds = $interval->microseconds;
2098
+
2099
+		if (!$ignoreSign) {
2100
+			$this->invert = $interval->invert;
2101
+		}
2102
+
2103
+		return $this;
2104
+	}
2105
+
2106
+	/**
2107
+	 * Multiply and cascade current instance by a given factor.
2108
+	 *
2109
+	 * @param float|int $factor
2110
+	 *
2111
+	 * @return $this
2112
+	 */
2113
+	public function multiply($factor)
2114
+	{
2115
+		if ($factor < 0) {
2116
+			$this->invert = $this->invert ? 0 : 1;
2117
+			$factor = -$factor;
2118
+		}
2119
+
2120
+		$yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision
2121
+
2122
+		if ($yearPart) {
2123
+			$this->years -= $yearPart / $factor;
2124
+		}
2125
+
2126
+		return $this->copyProperties(
2127
+			static::create($yearPart)
2128
+				->microseconds(abs($this->totalMicroseconds) * $factor)
2129
+				->cascade(),
2130
+			true
2131
+		);
2132
+	}
2133
+
2134
+	/**
2135
+	 * Divide and cascade current instance by a given divider.
2136
+	 *
2137
+	 * @param float|int $divider
2138
+	 *
2139
+	 * @return $this
2140
+	 */
2141
+	public function divide($divider)
2142
+	{
2143
+		return $this->multiply(1 / $divider);
2144
+	}
2145
+
2146
+	/**
2147
+	 * Get the interval_spec string of a date interval.
2148
+	 *
2149
+	 * @param DateInterval $interval
2150
+	 *
2151
+	 * @return string
2152
+	 */
2153
+	public static function getDateIntervalSpec(DateInterval $interval, bool $microseconds = false)
2154
+	{
2155
+		$date = array_filter([
2156
+			static::PERIOD_YEARS => abs($interval->y),
2157
+			static::PERIOD_MONTHS => abs($interval->m),
2158
+			static::PERIOD_DAYS => abs($interval->d),
2159
+		]);
2160
+
2161
+		$seconds = abs($interval->s);
2162
+		if ($microseconds && $interval->f > 0) {
2163
+			$seconds = sprintf('%d.%06d', $seconds, abs($interval->f) * 1000000);
2164
+		}
2165
+
2166
+		$time = array_filter([
2167
+			static::PERIOD_HOURS => abs($interval->h),
2168
+			static::PERIOD_MINUTES => abs($interval->i),
2169
+			static::PERIOD_SECONDS => $seconds,
2170
+		]);
2171
+
2172
+		$specString = static::PERIOD_PREFIX;
2173
+
2174
+		foreach ($date as $key => $value) {
2175
+			$specString .= $value.$key;
2176
+		}
2177
+
2178
+		if (\count($time) > 0) {
2179
+			$specString .= static::PERIOD_TIME_PREFIX;
2180
+			foreach ($time as $key => $value) {
2181
+				$specString .= $value.$key;
2182
+			}
2183
+		}
2184
+
2185
+		return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
2186
+	}
2187
+
2188
+	/**
2189
+	 * Get the interval_spec string.
2190
+	 *
2191
+	 * @return string
2192
+	 */
2193
+	public function spec(bool $microseconds = false)
2194
+	{
2195
+		return static::getDateIntervalSpec($this, $microseconds);
2196
+	}
2197
+
2198
+	/**
2199
+	 * Comparing 2 date intervals.
2200
+	 *
2201
+	 * @param DateInterval $first
2202
+	 * @param DateInterval $second
2203
+	 *
2204
+	 * @return int
2205
+	 */
2206
+	public static function compareDateIntervals(DateInterval $first, DateInterval $second)
2207
+	{
2208
+		$current = Carbon::now();
2209
+		$passed = $current->avoidMutation()->add($second);
2210
+		$current->add($first);
2211
+
2212
+		if ($current < $passed) {
2213
+			return -1;
2214
+		}
2215
+		if ($current > $passed) {
2216
+			return 1;
2217
+		}
2218
+
2219
+		return 0;
2220
+	}
2221
+
2222
+	/**
2223
+	 * Comparing with passed interval.
2224
+	 *
2225
+	 * @param DateInterval $interval
2226
+	 *
2227
+	 * @return int
2228
+	 */
2229
+	public function compare(DateInterval $interval)
2230
+	{
2231
+		return static::compareDateIntervals($this, $interval);
2232
+	}
2233
+
2234
+	private function invertCascade(array $values)
2235
+	{
2236
+		return $this->set(array_map(function ($value) {
2237
+			return -$value;
2238
+		}, $values))->doCascade(true)->invert();
2239
+	}
2240
+
2241
+	private function doCascade(bool $deep)
2242
+	{
2243
+		$originalData = $this->toArray();
2244
+		$originalData['milliseconds'] = (int) ($originalData['microseconds'] / static::getMicrosecondsPerMillisecond());
2245
+		$originalData['microseconds'] = $originalData['microseconds'] % static::getMicrosecondsPerMillisecond();
2246
+		$originalData['daysExcludeWeeks'] = $originalData['days'];
2247
+		unset($originalData['days']);
2248
+		$newData = $originalData;
2249
+
2250
+		foreach (self::getFlipCascadeFactors() as $source => [$target, $factor]) {
2251
+			foreach (['source', 'target'] as $key) {
2252
+				if ($$key === 'dayz') {
2253
+					$$key = 'daysExcludeWeeks';
2254
+				}
2255
+			}
2256
+
2257
+			$value = $newData[$source];
2258
+			$modulo = ($factor + ($value % $factor)) % $factor;
2259
+			$newData[$source] = $modulo;
2260
+			$newData[$target] += ($value - $modulo) / $factor;
2261
+		}
2262
+
2263
+		$positive = null;
2264
+
2265
+		if (!$deep) {
2266
+			foreach ($newData as $value) {
2267
+				if ($value) {
2268
+					if ($positive === null) {
2269
+						$positive = ($value > 0);
2270
+
2271
+						continue;
2272
+					}
2273
+
2274
+					if (($value > 0) !== $positive) {
2275
+						return $this->invertCascade($originalData)
2276
+							->solveNegativeInterval();
2277
+					}
2278
+				}
2279
+			}
2280
+		}
2281
+
2282
+		return $this->set($newData)
2283
+			->solveNegativeInterval();
2284
+	}
2285
+
2286
+	/**
2287
+	 * Convert overflowed values into bigger units.
2288
+	 *
2289
+	 * @return $this
2290
+	 */
2291
+	public function cascade()
2292
+	{
2293
+		return $this->doCascade(false);
2294
+	}
2295
+
2296
+	public function hasNegativeValues(): bool
2297
+	{
2298
+		foreach ($this->toArray() as $value) {
2299
+			if ($value < 0) {
2300
+				return true;
2301
+			}
2302
+		}
2303
+
2304
+		return false;
2305
+	}
2306
+
2307
+	public function hasPositiveValues(): bool
2308
+	{
2309
+		foreach ($this->toArray() as $value) {
2310
+			if ($value > 0) {
2311
+				return true;
2312
+			}
2313
+		}
2314
+
2315
+		return false;
2316
+	}
2317
+
2318
+	/**
2319
+	 * Get amount of given unit equivalent to the interval.
2320
+	 *
2321
+	 * @param string $unit
2322
+	 *
2323
+	 * @throws UnknownUnitException|UnitNotConfiguredException
2324
+	 *
2325
+	 * @return float
2326
+	 */
2327
+	public function total($unit)
2328
+	{
2329
+		$realUnit = $unit = strtolower($unit);
2330
+
2331
+		if (\in_array($unit, ['days', 'weeks'])) {
2332
+			$realUnit = 'dayz';
2333
+		} elseif (!\in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
2334
+			throw new UnknownUnitException($unit);
2335
+		}
2336
+
2337
+		$result = 0;
2338
+		$cumulativeFactor = 0;
2339
+		$unitFound = false;
2340
+		$factors = self::getFlipCascadeFactors();
2341
+		$daysPerWeek = static::getDaysPerWeek();
2342
+
2343
+		$values = [
2344
+			'years' => $this->years,
2345
+			'months' => $this->months,
2346
+			'weeks' => (int) ($this->d / $daysPerWeek),
2347
+			'dayz' => $this->d % $daysPerWeek,
2348
+			'hours' => $this->hours,
2349
+			'minutes' => $this->minutes,
2350
+			'seconds' => $this->seconds,
2351
+			'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
2352
+			'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND,
2353
+		];
2354
+
2355
+		if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {
2356
+			$values['dayz'] += $values['weeks'] * $daysPerWeek;
2357
+			$values['weeks'] = 0;
2358
+		}
2359
+
2360
+		foreach ($factors as $source => [$target, $factor]) {
2361
+			if ($source === $realUnit) {
2362
+				$unitFound = true;
2363
+				$value = $values[$source];
2364
+				$result += $value;
2365
+				$cumulativeFactor = 1;
2366
+			}
2367
+
2368
+			if ($factor === false) {
2369
+				if ($unitFound) {
2370
+					break;
2371
+				}
2372
+
2373
+				$result = 0;
2374
+				$cumulativeFactor = 0;
2375
+
2376
+				continue;
2377
+			}
2378
+
2379
+			if ($target === $realUnit) {
2380
+				$unitFound = true;
2381
+			}
2382
+
2383
+			if ($cumulativeFactor) {
2384
+				$cumulativeFactor *= $factor;
2385
+				$result += $values[$target] * $cumulativeFactor;
2386
+
2387
+				continue;
2388
+			}
2389
+
2390
+			$value = $values[$source];
2391
+
2392
+			$result = ($result + $value) / $factor;
2393
+		}
2394
+
2395
+		if (isset($target) && !$cumulativeFactor) {
2396
+			$result += $values[$target];
2397
+		}
2398
+
2399
+		if (!$unitFound) {
2400
+			throw new UnitNotConfiguredException($unit);
2401
+		}
2402
+
2403
+		if ($this->invert) {
2404
+			$result *= -1;
2405
+		}
2406
+
2407
+		if ($unit === 'weeks') {
2408
+			return $result / $daysPerWeek;
2409
+		}
2410
+
2411
+		return $result;
2412
+	}
2413
+
2414
+	/**
2415
+	 * Determines if the instance is equal to another
2416
+	 *
2417
+	 * @param CarbonInterval|DateInterval|mixed $interval
2418
+	 *
2419
+	 * @see equalTo()
2420
+	 *
2421
+	 * @return bool
2422
+	 */
2423
+	public function eq($interval): bool
2424
+	{
2425
+		return $this->equalTo($interval);
2426
+	}
2427
+
2428
+	/**
2429
+	 * Determines if the instance is equal to another
2430
+	 *
2431
+	 * @param CarbonInterval|DateInterval|mixed $interval
2432
+	 *
2433
+	 * @return bool
2434
+	 */
2435
+	public function equalTo($interval): bool
2436
+	{
2437
+		$interval = $this->resolveInterval($interval);
2438
+
2439
+		return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds;
2440
+	}
2441
+
2442
+	/**
2443
+	 * Determines if the instance is not equal to another
2444
+	 *
2445
+	 * @param CarbonInterval|DateInterval|mixed $interval
2446
+	 *
2447
+	 * @see notEqualTo()
2448
+	 *
2449
+	 * @return bool
2450
+	 */
2451
+	public function ne($interval): bool
2452
+	{
2453
+		return $this->notEqualTo($interval);
2454
+	}
2455
+
2456
+	/**
2457
+	 * Determines if the instance is not equal to another
2458
+	 *
2459
+	 * @param CarbonInterval|DateInterval|mixed $interval
2460
+	 *
2461
+	 * @return bool
2462
+	 */
2463
+	public function notEqualTo($interval): bool
2464
+	{
2465
+		return !$this->eq($interval);
2466
+	}
2467
+
2468
+	/**
2469
+	 * Determines if the instance is greater (longer) than another
2470
+	 *
2471
+	 * @param CarbonInterval|DateInterval|mixed $interval
2472
+	 *
2473
+	 * @see greaterThan()
2474
+	 *
2475
+	 * @return bool
2476
+	 */
2477
+	public function gt($interval): bool
2478
+	{
2479
+		return $this->greaterThan($interval);
2480
+	}
2481
+
2482
+	/**
2483
+	 * Determines if the instance is greater (longer) than another
2484
+	 *
2485
+	 * @param CarbonInterval|DateInterval|mixed $interval
2486
+	 *
2487
+	 * @return bool
2488
+	 */
2489
+	public function greaterThan($interval): bool
2490
+	{
2491
+		$interval = $this->resolveInterval($interval);
2492
+
2493
+		return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
2494
+	}
2495
+
2496
+	/**
2497
+	 * Determines if the instance is greater (longer) than or equal to another
2498
+	 *
2499
+	 * @param CarbonInterval|DateInterval|mixed $interval
2500
+	 *
2501
+	 * @see greaterThanOrEqualTo()
2502
+	 *
2503
+	 * @return bool
2504
+	 */
2505
+	public function gte($interval): bool
2506
+	{
2507
+		return $this->greaterThanOrEqualTo($interval);
2508
+	}
2509
+
2510
+	/**
2511
+	 * Determines if the instance is greater (longer) than or equal to another
2512
+	 *
2513
+	 * @param CarbonInterval|DateInterval|mixed $interval
2514
+	 *
2515
+	 * @return bool
2516
+	 */
2517
+	public function greaterThanOrEqualTo($interval): bool
2518
+	{
2519
+		return $this->greaterThan($interval) || $this->equalTo($interval);
2520
+	}
2521
+
2522
+	/**
2523
+	 * Determines if the instance is less (shorter) than another
2524
+	 *
2525
+	 * @param CarbonInterval|DateInterval|mixed $interval
2526
+	 *
2527
+	 * @see lessThan()
2528
+	 *
2529
+	 * @return bool
2530
+	 */
2531
+	public function lt($interval): bool
2532
+	{
2533
+		return $this->lessThan($interval);
2534
+	}
2535
+
2536
+	/**
2537
+	 * Determines if the instance is less (shorter) than another
2538
+	 *
2539
+	 * @param CarbonInterval|DateInterval|mixed $interval
2540
+	 *
2541
+	 * @return bool
2542
+	 */
2543
+	public function lessThan($interval): bool
2544
+	{
2545
+		$interval = $this->resolveInterval($interval);
2546
+
2547
+		return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
2548
+	}
2549
+
2550
+	/**
2551
+	 * Determines if the instance is less (shorter) than or equal to another
2552
+	 *
2553
+	 * @param CarbonInterval|DateInterval|mixed $interval
2554
+	 *
2555
+	 * @see lessThanOrEqualTo()
2556
+	 *
2557
+	 * @return bool
2558
+	 */
2559
+	public function lte($interval): bool
2560
+	{
2561
+		return $this->lessThanOrEqualTo($interval);
2562
+	}
2563
+
2564
+	/**
2565
+	 * Determines if the instance is less (shorter) than or equal to another
2566
+	 *
2567
+	 * @param CarbonInterval|DateInterval|mixed $interval
2568
+	 *
2569
+	 * @return bool
2570
+	 */
2571
+	public function lessThanOrEqualTo($interval): bool
2572
+	{
2573
+		return $this->lessThan($interval) || $this->equalTo($interval);
2574
+	}
2575
+
2576
+	/**
2577
+	 * Determines if the instance is between two others.
2578
+	 *
2579
+	 * The third argument allow you to specify if bounds are included or not (true by default)
2580
+	 * but for when you including/excluding bounds may produce different results in your application,
2581
+	 * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
2582
+	 *
2583
+	 * @example
2584
+	 * ```
2585
+	 * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
2586
+	 * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2587
+	 * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
2588
+	 * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
2589
+	 * ```
2590
+	 *
2591
+	 * @param CarbonInterval|DateInterval|mixed $interval1
2592
+	 * @param CarbonInterval|DateInterval|mixed $interval2
2593
+	 * @param bool                              $equal     Indicates if an equal to comparison should be done
2594
+	 *
2595
+	 * @return bool
2596
+	 */
2597
+	public function between($interval1, $interval2, $equal = true): bool
2598
+	{
2599
+		return $equal
2600
+			? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
2601
+			: $this->greaterThan($interval1) && $this->lessThan($interval2);
2602
+	}
2603
+
2604
+	/**
2605
+	 * Determines if the instance is between two others, bounds excluded.
2606
+	 *
2607
+	 * @example
2608
+	 * ```
2609
+	 * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
2610
+	 * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2611
+	 * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // true
2612
+	 * ```
2613
+	 *
2614
+	 * @param CarbonInterval|DateInterval|mixed $interval1
2615
+	 * @param CarbonInterval|DateInterval|mixed $interval2
2616
+	 *
2617
+	 * @return bool
2618
+	 */
2619
+	public function betweenIncluded($interval1, $interval2): bool
2620
+	{
2621
+		return $this->between($interval1, $interval2, true);
2622
+	}
2623
+
2624
+	/**
2625
+	 * Determines if the instance is between two others, bounds excluded.
2626
+	 *
2627
+	 * @example
2628
+	 * ```
2629
+	 * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
2630
+	 * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2631
+	 * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
2632
+	 * ```
2633
+	 *
2634
+	 * @param CarbonInterval|DateInterval|mixed $interval1
2635
+	 * @param CarbonInterval|DateInterval|mixed $interval2
2636
+	 *
2637
+	 * @return bool
2638
+	 */
2639
+	public function betweenExcluded($interval1, $interval2): bool
2640
+	{
2641
+		return $this->between($interval1, $interval2, false);
2642
+	}
2643
+
2644
+	/**
2645
+	 * Determines if the instance is between two others
2646
+	 *
2647
+	 * @example
2648
+	 * ```
2649
+	 * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
2650
+	 * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
2651
+	 * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
2652
+	 * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
2653
+	 * ```
2654
+	 *
2655
+	 * @param CarbonInterval|DateInterval|mixed $interval1
2656
+	 * @param CarbonInterval|DateInterval|mixed $interval2
2657
+	 * @param bool                              $equal     Indicates if an equal to comparison should be done
2658
+	 *
2659
+	 * @return bool
2660
+	 */
2661
+	public function isBetween($interval1, $interval2, $equal = true): bool
2662
+	{
2663
+		return $this->between($interval1, $interval2, $equal);
2664
+	}
2665
+
2666
+	/**
2667
+	 * Round the current instance at the given unit with given precision if specified and the given function.
2668
+	 *
2669
+	 * @param string                             $unit
2670
+	 * @param float|int|string|DateInterval|null $precision
2671
+	 * @param string                             $function
2672
+	 *
2673
+	 * @throws Exception
2674
+	 *
2675
+	 * @return $this
2676
+	 */
2677
+	public function roundUnit($unit, $precision = 1, $function = 'round')
2678
+	{
2679
+		$base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC')
2680
+			->roundUnit($unit, $precision, $function);
2681
+		$next = $base->add($this);
2682
+		$inverted = $next < $base;
2683
+
2684
+		if ($inverted) {
2685
+			$next = $base->sub($this);
2686
+		}
2687
+
2688
+		$this->copyProperties(
2689
+			$next
2690
+				->roundUnit($unit, $precision, $function)
2691
+				->diffAsCarbonInterval($base)
2692
+		);
2693
+
2694
+		return $this->invert($inverted);
2695
+	}
2696
+
2697
+	/**
2698
+	 * Truncate the current instance at the given unit with given precision if specified.
2699
+	 *
2700
+	 * @param string                             $unit
2701
+	 * @param float|int|string|DateInterval|null $precision
2702
+	 *
2703
+	 * @throws Exception
2704
+	 *
2705
+	 * @return $this
2706
+	 */
2707
+	public function floorUnit($unit, $precision = 1)
2708
+	{
2709
+		return $this->roundUnit($unit, $precision, 'floor');
2710
+	}
2711
+
2712
+	/**
2713
+	 * Ceil the current instance at the given unit with given precision if specified.
2714
+	 *
2715
+	 * @param string                             $unit
2716
+	 * @param float|int|string|DateInterval|null $precision
2717
+	 *
2718
+	 * @throws Exception
2719
+	 *
2720
+	 * @return $this
2721
+	 */
2722
+	public function ceilUnit($unit, $precision = 1)
2723
+	{
2724
+		return $this->roundUnit($unit, $precision, 'ceil');
2725
+	}
2726
+
2727
+	/**
2728
+	 * Round the current instance second with given precision if specified.
2729
+	 *
2730
+	 * @param float|int|string|DateInterval|null $precision
2731
+	 * @param string                             $function
2732
+	 *
2733
+	 * @throws Exception
2734
+	 *
2735
+	 * @return $this
2736
+	 */
2737
+	public function round($precision = 1, $function = 'round')
2738
+	{
2739
+		return $this->roundWith($precision, $function);
2740
+	}
2741
+
2742
+	/**
2743
+	 * Round the current instance second with given precision if specified.
2744
+	 *
2745
+	 * @param float|int|string|DateInterval|null $precision
2746
+	 *
2747
+	 * @throws Exception
2748
+	 *
2749
+	 * @return $this
2750
+	 */
2751
+	public function floor($precision = 1)
2752
+	{
2753
+		return $this->round($precision, 'floor');
2754
+	}
2755
+
2756
+	/**
2757
+	 * Ceil the current instance second with given precision if specified.
2758
+	 *
2759
+	 * @param float|int|string|DateInterval|null $precision
2760
+	 *
2761
+	 * @throws Exception
2762
+	 *
2763
+	 * @return $this
2764
+	 */
2765
+	public function ceil($precision = 1)
2766
+	{
2767
+		return $this->round($precision, 'ceil');
2768
+	}
2769
+
2770
+	private function needsDeclension(string $mode, int $index, int $parts): bool
2771
+	{
2772
+		switch ($mode) {
2773
+			case 'last':
2774
+				return $index === $parts - 1;
2775
+			default:
2776
+				return true;
2777
+		}
2778
+	}
2779 2779
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -19 removed lines patch added patch discarded remove patch
@@ -656,7 +656,7 @@  discard block
 block discarded – undo
656 656
             $interval->localStrictModeEnabled = true;
657 657
 
658 658
             $result = static::hasMacro($method)
659
-                ? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) {
659
+                ? static::bindMacroContext(null, function() use (&$method, &$parameters, &$interval) {
660 660
                     return $interval->callMacro($method, $parameters);
661 661
                 })
662 662
                 : $interval->$method(...$parameters);
@@ -746,9 +746,7 @@  discard block
 block discarded – undo
746 746
             }
747 747
 
748 748
             switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
749
-                case 'millennia':
750
-                case 'millennium':
751
-                    $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
749
+                case 'millennia' : case 'millennium' : $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
752 750
 
753 751
                     break;
754 752
 
@@ -1343,7 +1341,7 @@  discard block
 block discarded – undo
1343 1341
     public function __call($method, $parameters)
1344 1342
     {
1345 1343
         if (static::hasMacro($method)) {
1346
-            return static::bindMacroContext($this, function () use (&$method, &$parameters) {
1344
+            return static::bindMacroContext($this, function() use (&$method, &$parameters) {
1347 1345
                 return $this->callMacro($method, $parameters);
1348 1346
             });
1349 1347
         }
@@ -1410,7 +1408,7 @@  discard block
 block discarded – undo
1410 1408
         $minimumUnit = 's';
1411 1409
         $skip = [];
1412 1410
         extract($this->getForHumansInitialVariables($syntax, $short));
1413
-        $skip = array_filter((array) $skip, static function ($value) {
1411
+        $skip = array_filter((array) $skip, static function($value) {
1414 1412
             return \is_string($value) && $value !== '';
1415 1413
         });
1416 1414
 
@@ -1447,7 +1445,7 @@  discard block
 block discarded – undo
1447 1445
                 $optionalSpace = '';
1448 1446
             }
1449 1447
 
1450
-            $join = function ($list) use ($default, $last) {
1448
+            $join = function($list) use ($default, $last) {
1451 1449
                 if (\count($list) < 2) {
1452 1450
                     return implode('', $list);
1453 1451
                 }
@@ -1464,7 +1462,7 @@  discard block
 block discarded – undo
1464 1462
             }
1465 1463
 
1466 1464
             $glue = $join;
1467
-            $join = function ($list) use ($glue) {
1465
+            $join = function($list) use ($glue) {
1468 1466
                 return implode($glue, $list);
1469 1467
             };
1470 1468
         }
@@ -1623,7 +1621,7 @@  discard block
 block discarded – undo
1623 1621
         /** @var \Symfony\Component\Translation\Translator $translator */
1624 1622
         $translator = $this->getLocalTranslator();
1625 1623
 
1626
-        $handleDeclensions = function ($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) {
1624
+        $handleDeclensions = function($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) {
1627 1625
             if (!$absolute) {
1628 1626
                 $declensionMode = $declensionMode ?? $this->translate($transId.'_mode');
1629 1627
 
@@ -1673,14 +1671,14 @@  discard block
 block discarded – undo
1673 1671
         }
1674 1672
 
1675 1673
         $diffIntervalArray = [
1676
-            ['value' => $intervalValues->years,             'unit' => 'year',        'unitShort' => 'y'],
1677
-            ['value' => $intervalValues->months,            'unit' => 'month',       'unitShort' => 'm'],
1678
-            ['value' => $intervalValues->weeks,             'unit' => 'week',        'unitShort' => 'w'],
1679
-            ['value' => $intervalValues->daysExcludeWeeks,  'unit' => 'day',         'unitShort' => 'd'],
1680
-            ['value' => $intervalValues->hours,             'unit' => 'hour',        'unitShort' => 'h'],
1681
-            ['value' => $intervalValues->minutes,           'unit' => 'minute',      'unitShort' => 'min'],
1682
-            ['value' => $intervalValues->seconds,           'unit' => 'second',      'unitShort' => 's'],
1683
-            ['value' => $intervalValues->milliseconds,      'unit' => 'millisecond', 'unitShort' => 'ms'],
1674
+            ['value' => $intervalValues->years, 'unit' => 'year', 'unitShort' => 'y'],
1675
+            ['value' => $intervalValues->months, 'unit' => 'month', 'unitShort' => 'm'],
1676
+            ['value' => $intervalValues->weeks, 'unit' => 'week', 'unitShort' => 'w'],
1677
+            ['value' => $intervalValues->daysExcludeWeeks, 'unit' => 'day', 'unitShort' => 'd'],
1678
+            ['value' => $intervalValues->hours, 'unit' => 'hour', 'unitShort' => 'h'],
1679
+            ['value' => $intervalValues->minutes, 'unit' => 'minute', 'unitShort' => 'min'],
1680
+            ['value' => $intervalValues->seconds, 'unit' => 'second', 'unitShort' => 's'],
1681
+            ['value' => $intervalValues->milliseconds, 'unit' => 'millisecond', 'unitShort' => 'ms'],
1684 1682
             ['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'],
1685 1683
         ];
1686 1684
 
@@ -1699,7 +1697,7 @@  discard block
 block discarded – undo
1699 1697
             }
1700 1698
         }
1701 1699
 
1702
-        $transChoice = function ($short, $unitData, $index, $parts) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
1700
+        $transChoice = function($short, $unitData, $index, $parts) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
1703 1701
             $count = $unitData['value'];
1704 1702
 
1705 1703
             if ($short) {
@@ -2233,7 +2231,7 @@  discard block
 block discarded – undo
2233 2231
 
2234 2232
     private function invertCascade(array $values)
2235 2233
     {
2236
-        return $this->set(array_map(function ($value) {
2234
+        return $this->set(array_map(function($value) {
2237 2235
             return -$value;
2238 2236
         }, $values))->doCascade(true)->invert();
2239 2237
     }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php 1 patch
Indentation   +298 added lines, -298 removed lines patch added patch discarded remove patch
@@ -19,302 +19,302 @@
 block discarded – undo
19 19
 
20 20
 class CarbonTimeZone extends DateTimeZone
21 21
 {
22
-    public function __construct($timezone = null)
23
-    {
24
-        parent::__construct(static::getDateTimeZoneNameFromMixed($timezone));
25
-    }
26
-
27
-    protected static function parseNumericTimezone($timezone)
28
-    {
29
-        if ($timezone <= -100 || $timezone >= 100) {
30
-            throw new InvalidTimeZoneException('Absolute timezone offset cannot be greater than 100.');
31
-        }
32
-
33
-        return ($timezone >= 0 ? '+' : '').ltrim($timezone, '+').':00';
34
-    }
35
-
36
-    protected static function getDateTimeZoneNameFromMixed($timezone)
37
-    {
38
-        if ($timezone === null) {
39
-            return date_default_timezone_get();
40
-        }
41
-
42
-        if (\is_string($timezone)) {
43
-            $timezone = preg_replace('/^\s*([+-]\d+)(\d{2})\s*$/', '$1:$2', $timezone);
44
-        }
45
-
46
-        if (is_numeric($timezone)) {
47
-            return static::parseNumericTimezone($timezone);
48
-        }
49
-
50
-        return $timezone;
51
-    }
52
-
53
-    protected static function getDateTimeZoneFromName(&$name)
54
-    {
55
-        return @timezone_open($name = (string) static::getDateTimeZoneNameFromMixed($name));
56
-    }
57
-
58
-    /**
59
-     * Cast the current instance into the given class.
60
-     *
61
-     * @param string $className The $className::instance() method will be called to cast the current object.
62
-     *
63
-     * @return DateTimeZone
64
-     */
65
-    public function cast(string $className)
66
-    {
67
-        if (!method_exists($className, 'instance')) {
68
-            if (is_a($className, DateTimeZone::class, true)) {
69
-                return new $className($this->getName());
70
-            }
71
-
72
-            throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
73
-        }
74
-
75
-        return $className::instance($this);
76
-    }
77
-
78
-    /**
79
-     * Create a CarbonTimeZone from mixed input.
80
-     *
81
-     * @param DateTimeZone|string|int|null $object     original value to get CarbonTimeZone from it.
82
-     * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages.
83
-     *
84
-     * @throws InvalidTimeZoneException
85
-     *
86
-     * @return false|static
87
-     */
88
-    public static function instance($object = null, $objectDump = null)
89
-    {
90
-        $tz = $object;
91
-
92
-        if ($tz instanceof static) {
93
-            return $tz;
94
-        }
95
-
96
-        if ($tz === null) {
97
-            return new static();
98
-        }
99
-
100
-        if (!$tz instanceof DateTimeZone) {
101
-            $tz = static::getDateTimeZoneFromName($object);
102
-        }
103
-
104
-        if ($tz !== false) {
105
-            return new static($tz->getName());
106
-        }
107
-
108
-        if (Carbon::isStrictModeEnabled()) {
109
-            throw new InvalidTimeZoneException('Unknown or bad timezone ('.($objectDump ?: $object).')');
110
-        }
111
-
112
-        return false;
113
-    }
114
-
115
-    /**
116
-     * Returns abbreviated name of the current timezone according to DST setting.
117
-     *
118
-     * @param bool $dst
119
-     *
120
-     * @return string
121
-     */
122
-    public function getAbbreviatedName($dst = false)
123
-    {
124
-        $name = $this->getName();
125
-
126
-        foreach ($this->listAbbreviations() as $abbreviation => $zones) {
127
-            foreach ($zones as $zone) {
128
-                if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) {
129
-                    return $abbreviation;
130
-                }
131
-            }
132
-        }
133
-
134
-        return 'unknown';
135
-    }
136
-
137
-    /**
138
-     * @alias getAbbreviatedName
139
-     *
140
-     * Returns abbreviated name of the current timezone according to DST setting.
141
-     *
142
-     * @param bool $dst
143
-     *
144
-     * @return string
145
-     */
146
-    public function getAbbr($dst = false)
147
-    {
148
-        return $this->getAbbreviatedName($dst);
149
-    }
150
-
151
-    /**
152
-     * Get the offset as string "sHH:MM" (such as "+00:00" or "-12:30").
153
-     *
154
-     * @param DateTimeInterface|null $date
155
-     *
156
-     * @return string
157
-     */
158
-    public function toOffsetName(DateTimeInterface $date = null)
159
-    {
160
-        return static::getOffsetNameFromMinuteOffset(
161
-            $this->getOffset($date ?: Carbon::now($this)) / 60
162
-        );
163
-    }
164
-
165
-    /**
166
-     * Returns a new CarbonTimeZone object using the offset string instead of region string.
167
-     *
168
-     * @param DateTimeInterface|null $date
169
-     *
170
-     * @return CarbonTimeZone
171
-     */
172
-    public function toOffsetTimeZone(DateTimeInterface $date = null)
173
-    {
174
-        return new static($this->toOffsetName($date));
175
-    }
176
-
177
-    /**
178
-     * Returns the first region string (such as "America/Toronto") that matches the current timezone or
179
-     * false if no match is found.
180
-     *
181
-     * @see timezone_name_from_abbr native PHP function.
182
-     *
183
-     * @param DateTimeInterface|null $date
184
-     * @param int                    $isDst
185
-     *
186
-     * @return string|false
187
-     */
188
-    public function toRegionName(DateTimeInterface $date = null, $isDst = 1)
189
-    {
190
-        $name = $this->getName();
191
-        $firstChar = substr($name, 0, 1);
192
-
193
-        if ($firstChar !== '+' && $firstChar !== '-') {
194
-            return $name;
195
-        }
196
-
197
-        $date = $date ?: Carbon::now($this);
198
-
199
-        // Integer construction no longer supported since PHP 8
200
-        // @codeCoverageIgnoreStart
201
-        try {
202
-            $offset = @$this->getOffset($date) ?: 0;
203
-        } catch (Throwable $e) {
204
-            $offset = 0;
205
-        }
206
-        // @codeCoverageIgnoreEnd
207
-
208
-        $name = @timezone_name_from_abbr('', $offset, $isDst);
209
-
210
-        if ($name) {
211
-            return $name;
212
-        }
213
-
214
-        foreach (timezone_identifiers_list() as $timezone) {
215
-            if (Carbon::instance($date)->tz($timezone)->getOffset() === $offset) {
216
-                return $timezone;
217
-            }
218
-        }
219
-
220
-        return false;
221
-    }
222
-
223
-    /**
224
-     * Returns a new CarbonTimeZone object using the region string instead of offset string.
225
-     *
226
-     * @param DateTimeInterface|null $date
227
-     *
228
-     * @return CarbonTimeZone|false
229
-     */
230
-    public function toRegionTimeZone(DateTimeInterface $date = null)
231
-    {
232
-        $tz = $this->toRegionName($date);
233
-
234
-        if ($tz !== false) {
235
-            return new static($tz);
236
-        }
237
-
238
-        if (Carbon::isStrictModeEnabled()) {
239
-            throw new InvalidTimeZoneException('Unknown timezone for offset '.$this->getOffset($date ?: Carbon::now($this)).' seconds.');
240
-        }
241
-
242
-        return false;
243
-    }
244
-
245
-    /**
246
-     * Cast to string (get timezone name).
247
-     *
248
-     * @return string
249
-     */
250
-    public function __toString()
251
-    {
252
-        return $this->getName();
253
-    }
254
-
255
-    /**
256
-     * Return the type number:
257
-     *
258
-     * Type 1; A UTC offset, such as -0300
259
-     * Type 2; A timezone abbreviation, such as GMT
260
-     * Type 3: A timezone identifier, such as Europe/London
261
-     */
262
-    public function getType(): int
263
-    {
264
-        return preg_match('/"timezone_type";i:(\d)/', serialize($this), $match) ? (int) $match[1] : 3;
265
-    }
266
-
267
-    /**
268
-     * Create a CarbonTimeZone from mixed input.
269
-     *
270
-     * @param DateTimeZone|string|int|null $object
271
-     *
272
-     * @return false|static
273
-     */
274
-    public static function create($object = null)
275
-    {
276
-        return static::instance($object);
277
-    }
278
-
279
-    /**
280
-     * Create a CarbonTimeZone from int/float hour offset.
281
-     *
282
-     * @param float $hourOffset number of hour of the timezone shift (can be decimal).
283
-     *
284
-     * @return false|static
285
-     */
286
-    public static function createFromHourOffset(float $hourOffset)
287
-    {
288
-        return static::createFromMinuteOffset($hourOffset * Carbon::MINUTES_PER_HOUR);
289
-    }
290
-
291
-    /**
292
-     * Create a CarbonTimeZone from int/float minute offset.
293
-     *
294
-     * @param float $minuteOffset number of total minutes of the timezone shift.
295
-     *
296
-     * @return false|static
297
-     */
298
-    public static function createFromMinuteOffset(float $minuteOffset)
299
-    {
300
-        return static::instance(static::getOffsetNameFromMinuteOffset($minuteOffset));
301
-    }
302
-
303
-    /**
304
-     * Convert a total minutes offset into a standardized timezone offset string.
305
-     *
306
-     * @param float $minutes number of total minutes of the timezone shift.
307
-     *
308
-     * @return string
309
-     */
310
-    public static function getOffsetNameFromMinuteOffset(float $minutes): string
311
-    {
312
-        $minutes = round($minutes);
313
-        $unsignedMinutes = abs($minutes);
314
-
315
-        return ($minutes < 0 ? '-' : '+').
316
-            str_pad((string) floor($unsignedMinutes / 60), 2, '0', STR_PAD_LEFT).
317
-            ':'.
318
-            str_pad((string) ($unsignedMinutes % 60), 2, '0', STR_PAD_LEFT);
319
-    }
22
+	public function __construct($timezone = null)
23
+	{
24
+		parent::__construct(static::getDateTimeZoneNameFromMixed($timezone));
25
+	}
26
+
27
+	protected static function parseNumericTimezone($timezone)
28
+	{
29
+		if ($timezone <= -100 || $timezone >= 100) {
30
+			throw new InvalidTimeZoneException('Absolute timezone offset cannot be greater than 100.');
31
+		}
32
+
33
+		return ($timezone >= 0 ? '+' : '').ltrim($timezone, '+').':00';
34
+	}
35
+
36
+	protected static function getDateTimeZoneNameFromMixed($timezone)
37
+	{
38
+		if ($timezone === null) {
39
+			return date_default_timezone_get();
40
+		}
41
+
42
+		if (\is_string($timezone)) {
43
+			$timezone = preg_replace('/^\s*([+-]\d+)(\d{2})\s*$/', '$1:$2', $timezone);
44
+		}
45
+
46
+		if (is_numeric($timezone)) {
47
+			return static::parseNumericTimezone($timezone);
48
+		}
49
+
50
+		return $timezone;
51
+	}
52
+
53
+	protected static function getDateTimeZoneFromName(&$name)
54
+	{
55
+		return @timezone_open($name = (string) static::getDateTimeZoneNameFromMixed($name));
56
+	}
57
+
58
+	/**
59
+	 * Cast the current instance into the given class.
60
+	 *
61
+	 * @param string $className The $className::instance() method will be called to cast the current object.
62
+	 *
63
+	 * @return DateTimeZone
64
+	 */
65
+	public function cast(string $className)
66
+	{
67
+		if (!method_exists($className, 'instance')) {
68
+			if (is_a($className, DateTimeZone::class, true)) {
69
+				return new $className($this->getName());
70
+			}
71
+
72
+			throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
73
+		}
74
+
75
+		return $className::instance($this);
76
+	}
77
+
78
+	/**
79
+	 * Create a CarbonTimeZone from mixed input.
80
+	 *
81
+	 * @param DateTimeZone|string|int|null $object     original value to get CarbonTimeZone from it.
82
+	 * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages.
83
+	 *
84
+	 * @throws InvalidTimeZoneException
85
+	 *
86
+	 * @return false|static
87
+	 */
88
+	public static function instance($object = null, $objectDump = null)
89
+	{
90
+		$tz = $object;
91
+
92
+		if ($tz instanceof static) {
93
+			return $tz;
94
+		}
95
+
96
+		if ($tz === null) {
97
+			return new static();
98
+		}
99
+
100
+		if (!$tz instanceof DateTimeZone) {
101
+			$tz = static::getDateTimeZoneFromName($object);
102
+		}
103
+
104
+		if ($tz !== false) {
105
+			return new static($tz->getName());
106
+		}
107
+
108
+		if (Carbon::isStrictModeEnabled()) {
109
+			throw new InvalidTimeZoneException('Unknown or bad timezone ('.($objectDump ?: $object).')');
110
+		}
111
+
112
+		return false;
113
+	}
114
+
115
+	/**
116
+	 * Returns abbreviated name of the current timezone according to DST setting.
117
+	 *
118
+	 * @param bool $dst
119
+	 *
120
+	 * @return string
121
+	 */
122
+	public function getAbbreviatedName($dst = false)
123
+	{
124
+		$name = $this->getName();
125
+
126
+		foreach ($this->listAbbreviations() as $abbreviation => $zones) {
127
+			foreach ($zones as $zone) {
128
+				if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) {
129
+					return $abbreviation;
130
+				}
131
+			}
132
+		}
133
+
134
+		return 'unknown';
135
+	}
136
+
137
+	/**
138
+	 * @alias getAbbreviatedName
139
+	 *
140
+	 * Returns abbreviated name of the current timezone according to DST setting.
141
+	 *
142
+	 * @param bool $dst
143
+	 *
144
+	 * @return string
145
+	 */
146
+	public function getAbbr($dst = false)
147
+	{
148
+		return $this->getAbbreviatedName($dst);
149
+	}
150
+
151
+	/**
152
+	 * Get the offset as string "sHH:MM" (such as "+00:00" or "-12:30").
153
+	 *
154
+	 * @param DateTimeInterface|null $date
155
+	 *
156
+	 * @return string
157
+	 */
158
+	public function toOffsetName(DateTimeInterface $date = null)
159
+	{
160
+		return static::getOffsetNameFromMinuteOffset(
161
+			$this->getOffset($date ?: Carbon::now($this)) / 60
162
+		);
163
+	}
164
+
165
+	/**
166
+	 * Returns a new CarbonTimeZone object using the offset string instead of region string.
167
+	 *
168
+	 * @param DateTimeInterface|null $date
169
+	 *
170
+	 * @return CarbonTimeZone
171
+	 */
172
+	public function toOffsetTimeZone(DateTimeInterface $date = null)
173
+	{
174
+		return new static($this->toOffsetName($date));
175
+	}
176
+
177
+	/**
178
+	 * Returns the first region string (such as "America/Toronto") that matches the current timezone or
179
+	 * false if no match is found.
180
+	 *
181
+	 * @see timezone_name_from_abbr native PHP function.
182
+	 *
183
+	 * @param DateTimeInterface|null $date
184
+	 * @param int                    $isDst
185
+	 *
186
+	 * @return string|false
187
+	 */
188
+	public function toRegionName(DateTimeInterface $date = null, $isDst = 1)
189
+	{
190
+		$name = $this->getName();
191
+		$firstChar = substr($name, 0, 1);
192
+
193
+		if ($firstChar !== '+' && $firstChar !== '-') {
194
+			return $name;
195
+		}
196
+
197
+		$date = $date ?: Carbon::now($this);
198
+
199
+		// Integer construction no longer supported since PHP 8
200
+		// @codeCoverageIgnoreStart
201
+		try {
202
+			$offset = @$this->getOffset($date) ?: 0;
203
+		} catch (Throwable $e) {
204
+			$offset = 0;
205
+		}
206
+		// @codeCoverageIgnoreEnd
207
+
208
+		$name = @timezone_name_from_abbr('', $offset, $isDst);
209
+
210
+		if ($name) {
211
+			return $name;
212
+		}
213
+
214
+		foreach (timezone_identifiers_list() as $timezone) {
215
+			if (Carbon::instance($date)->tz($timezone)->getOffset() === $offset) {
216
+				return $timezone;
217
+			}
218
+		}
219
+
220
+		return false;
221
+	}
222
+
223
+	/**
224
+	 * Returns a new CarbonTimeZone object using the region string instead of offset string.
225
+	 *
226
+	 * @param DateTimeInterface|null $date
227
+	 *
228
+	 * @return CarbonTimeZone|false
229
+	 */
230
+	public function toRegionTimeZone(DateTimeInterface $date = null)
231
+	{
232
+		$tz = $this->toRegionName($date);
233
+
234
+		if ($tz !== false) {
235
+			return new static($tz);
236
+		}
237
+
238
+		if (Carbon::isStrictModeEnabled()) {
239
+			throw new InvalidTimeZoneException('Unknown timezone for offset '.$this->getOffset($date ?: Carbon::now($this)).' seconds.');
240
+		}
241
+
242
+		return false;
243
+	}
244
+
245
+	/**
246
+	 * Cast to string (get timezone name).
247
+	 *
248
+	 * @return string
249
+	 */
250
+	public function __toString()
251
+	{
252
+		return $this->getName();
253
+	}
254
+
255
+	/**
256
+	 * Return the type number:
257
+	 *
258
+	 * Type 1; A UTC offset, such as -0300
259
+	 * Type 2; A timezone abbreviation, such as GMT
260
+	 * Type 3: A timezone identifier, such as Europe/London
261
+	 */
262
+	public function getType(): int
263
+	{
264
+		return preg_match('/"timezone_type";i:(\d)/', serialize($this), $match) ? (int) $match[1] : 3;
265
+	}
266
+
267
+	/**
268
+	 * Create a CarbonTimeZone from mixed input.
269
+	 *
270
+	 * @param DateTimeZone|string|int|null $object
271
+	 *
272
+	 * @return false|static
273
+	 */
274
+	public static function create($object = null)
275
+	{
276
+		return static::instance($object);
277
+	}
278
+
279
+	/**
280
+	 * Create a CarbonTimeZone from int/float hour offset.
281
+	 *
282
+	 * @param float $hourOffset number of hour of the timezone shift (can be decimal).
283
+	 *
284
+	 * @return false|static
285
+	 */
286
+	public static function createFromHourOffset(float $hourOffset)
287
+	{
288
+		return static::createFromMinuteOffset($hourOffset * Carbon::MINUTES_PER_HOUR);
289
+	}
290
+
291
+	/**
292
+	 * Create a CarbonTimeZone from int/float minute offset.
293
+	 *
294
+	 * @param float $minuteOffset number of total minutes of the timezone shift.
295
+	 *
296
+	 * @return false|static
297
+	 */
298
+	public static function createFromMinuteOffset(float $minuteOffset)
299
+	{
300
+		return static::instance(static::getOffsetNameFromMinuteOffset($minuteOffset));
301
+	}
302
+
303
+	/**
304
+	 * Convert a total minutes offset into a standardized timezone offset string.
305
+	 *
306
+	 * @param float $minutes number of total minutes of the timezone shift.
307
+	 *
308
+	 * @return string
309
+	 */
310
+	public static function getOffsetNameFromMinuteOffset(float $minutes): string
311
+	{
312
+		$minutes = round($minutes);
313
+		$unsignedMinutes = abs($minutes);
314
+
315
+		return ($minutes < 0 ? '-' : '+').
316
+			str_pad((string) floor($unsignedMinutes / 60), 2, '0', STR_PAD_LEFT).
317
+			':'.
318
+			str_pad((string) ($unsignedMinutes % 60), 2, '0', STR_PAD_LEFT);
319
+	}
320 320
 }
Please login to merge, or discard this patch.
includes/webklex/php-imap/vendor/nesbot/carbon/src/Carbon/Translator.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -16,17 +16,17 @@
 block discarded – undo
16 16
 use Symfony\Contracts\Translation\TranslatorInterface;
17 17
 
18 18
 $transMethod = new ReflectionMethod(
19
-    class_exists(TranslatorInterface::class)
20
-        ? TranslatorInterface::class
21
-        : Translation\Translator::class,
22
-    'trans'
19
+	class_exists(TranslatorInterface::class)
20
+		? TranslatorInterface::class
21
+		: Translation\Translator::class,
22
+	'trans'
23 23
 );
24 24
 
25 25
 require $transMethod->hasReturnType()
26
-    ? __DIR__.'/../../lazy/Carbon/TranslatorStrongType.php'
27
-    : __DIR__.'/../../lazy/Carbon/TranslatorWeakType.php';
26
+	? __DIR__.'/../../lazy/Carbon/TranslatorStrongType.php'
27
+	: __DIR__.'/../../lazy/Carbon/TranslatorWeakType.php';
28 28
 
29 29
 class Translator extends LazyTranslator
30 30
 {
31
-    // Proxy dynamically loaded LazyTranslator in a static way
31
+	// Proxy dynamically loaded LazyTranslator in a static way
32 32
 }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php 1 patch
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -509,74 +509,74 @@
 block discarded – undo
509 509
  */
510 510
 class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
511 511
 {
512
-    use Date {
513
-        __clone as dateTraitClone;
514
-    }
512
+	use Date {
513
+		__clone as dateTraitClone;
514
+	}
515 515
 
516
-    public function __clone()
517
-    {
518
-        $this->dateTraitClone();
519
-        $this->endOfTime = false;
520
-        $this->startOfTime = false;
521
-    }
516
+	public function __clone()
517
+	{
518
+		$this->dateTraitClone();
519
+		$this->endOfTime = false;
520
+		$this->startOfTime = false;
521
+	}
522 522
 
523
-    /**
524
-     * Create a very old date representing start of time.
525
-     *
526
-     * @return static
527
-     */
528
-    public static function startOfTime(): self
529
-    {
530
-        $date = static::parse('0001-01-01')->years(self::getStartOfTimeYear());
531
-        $date->startOfTime = true;
523
+	/**
524
+	 * Create a very old date representing start of time.
525
+	 *
526
+	 * @return static
527
+	 */
528
+	public static function startOfTime(): self
529
+	{
530
+		$date = static::parse('0001-01-01')->years(self::getStartOfTimeYear());
531
+		$date->startOfTime = true;
532 532
 
533
-        return $date;
534
-    }
533
+		return $date;
534
+	}
535 535
 
536
-    /**
537
-     * Create a very far date representing end of time.
538
-     *
539
-     * @return static
540
-     */
541
-    public static function endOfTime(): self
542
-    {
543
-        $date = static::parse('9999-12-31 23:59:59.999999')->years(self::getEndOfTimeYear());
544
-        $date->endOfTime = true;
536
+	/**
537
+	 * Create a very far date representing end of time.
538
+	 *
539
+	 * @return static
540
+	 */
541
+	public static function endOfTime(): self
542
+	{
543
+		$date = static::parse('9999-12-31 23:59:59.999999')->years(self::getEndOfTimeYear());
544
+		$date->endOfTime = true;
545 545
 
546
-        return $date;
547
-    }
546
+		return $date;
547
+	}
548 548
 
549
-    /**
550
-     * @codeCoverageIgnore
551
-     */
552
-    private static function getEndOfTimeYear(): int
553
-    {
554
-        if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
555
-            return 145261681241552;
556
-        }
549
+	/**
550
+	 * @codeCoverageIgnore
551
+	 */
552
+	private static function getEndOfTimeYear(): int
553
+	{
554
+		if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
555
+			return 145261681241552;
556
+		}
557 557
 
558
-        // Remove if https://bugs.php.net/bug.php?id=81107 is fixed
559
-        if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
560
-            return 1118290769066902787;
561
-        }
558
+		// Remove if https://bugs.php.net/bug.php?id=81107 is fixed
559
+		if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
560
+			return 1118290769066902787;
561
+		}
562 562
 
563
-        return PHP_INT_MAX;
564
-    }
563
+		return PHP_INT_MAX;
564
+	}
565 565
 
566
-    /**
567
-     * @codeCoverageIgnore
568
-     */
569
-    private static function getStartOfTimeYear(): int
570
-    {
571
-        if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
572
-            return -135908816449551;
573
-        }
566
+	/**
567
+	 * @codeCoverageIgnore
568
+	 */
569
+	private static function getStartOfTimeYear(): int
570
+	{
571
+		if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
572
+			return -135908816449551;
573
+		}
574 574
 
575
-        // Remove if https://bugs.php.net/bug.php?id=81107 is fixed
576
-        if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
577
-            return -1118290769066898816;
578
-        }
575
+		// Remove if https://bugs.php.net/bug.php?id=81107 is fixed
576
+		if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
577
+			return -1118290769066898816;
578
+		}
579 579
 
580
-        return max(PHP_INT_MIN, -9223372036854773760);
581
-    }
580
+		return max(PHP_INT_MIN, -9223372036854773760);
581
+	}
582 582
 }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -239,5 +239,5 @@
 block discarded – undo
239 239
  */
240 240
 class FactoryImmutable extends Factory
241 241
 {
242
-    protected $className = CarbonImmutable::class;
242
+	protected $className = CarbonImmutable::class;
243 243
 }
Please login to merge, or discard this patch.
includes/webklex/php-imap/vendor/nesbot/carbon/src/Carbon/Language.php 1 patch
Indentation   +323 added lines, -323 removed lines patch added patch discarded remove patch
@@ -16,327 +16,327 @@
 block discarded – undo
16 16
 
17 17
 class Language implements JsonSerializable
18 18
 {
19
-    /**
20
-     * @var array
21
-     */
22
-    protected static $languagesNames;
23
-
24
-    /**
25
-     * @var array
26
-     */
27
-    protected static $regionsNames;
28
-
29
-    /**
30
-     * @var string
31
-     */
32
-    protected $id;
33
-
34
-    /**
35
-     * @var string
36
-     */
37
-    protected $code;
38
-
39
-    /**
40
-     * @var string|null
41
-     */
42
-    protected $variant;
43
-
44
-    /**
45
-     * @var string|null
46
-     */
47
-    protected $region;
48
-
49
-    /**
50
-     * @var array
51
-     */
52
-    protected $names;
53
-
54
-    /**
55
-     * @var string
56
-     */
57
-    protected $isoName;
58
-
59
-    /**
60
-     * @var string
61
-     */
62
-    protected $nativeName;
63
-
64
-    public function __construct(string $id)
65
-    {
66
-        $this->id = str_replace('-', '_', $id);
67
-        $parts = explode('_', $this->id);
68
-        $this->code = $parts[0];
69
-
70
-        if (isset($parts[1])) {
71
-            if (!preg_match('/^[A-Z]+$/', $parts[1])) {
72
-                $this->variant = $parts[1];
73
-                $parts[1] = $parts[2] ?? null;
74
-            }
75
-            if ($parts[1]) {
76
-                $this->region = $parts[1];
77
-            }
78
-        }
79
-    }
80
-
81
-    /**
82
-     * Get the list of the known languages.
83
-     *
84
-     * @return array
85
-     */
86
-    public static function all()
87
-    {
88
-        if (!static::$languagesNames) {
89
-            static::$languagesNames = require __DIR__.'/List/languages.php';
90
-        }
91
-
92
-        return static::$languagesNames;
93
-    }
94
-
95
-    /**
96
-     * Get the list of the known regions.
97
-     *
98
-     * @return array
99
-     */
100
-    public static function regions()
101
-    {
102
-        if (!static::$regionsNames) {
103
-            static::$regionsNames = require __DIR__.'/List/regions.php';
104
-        }
105
-
106
-        return static::$regionsNames;
107
-    }
108
-
109
-    /**
110
-     * Get both isoName and nativeName as an array.
111
-     *
112
-     * @return array
113
-     */
114
-    public function getNames(): array
115
-    {
116
-        if (!$this->names) {
117
-            $this->names = static::all()[$this->code] ?? [
118
-                'isoName' => $this->code,
119
-                'nativeName' => $this->code,
120
-            ];
121
-        }
122
-
123
-        return $this->names;
124
-    }
125
-
126
-    /**
127
-     * Returns the original locale ID.
128
-     *
129
-     * @return string
130
-     */
131
-    public function getId(): string
132
-    {
133
-        return $this->id;
134
-    }
135
-
136
-    /**
137
-     * Returns the code of the locale "en"/"fr".
138
-     *
139
-     * @return string
140
-     */
141
-    public function getCode(): string
142
-    {
143
-        return $this->code;
144
-    }
145
-
146
-    /**
147
-     * Returns the variant code such as cyrl/latn.
148
-     *
149
-     * @return string|null
150
-     */
151
-    public function getVariant(): ?string
152
-    {
153
-        return $this->variant;
154
-    }
155
-
156
-    /**
157
-     * Returns the variant such as Cyrillic/Latin.
158
-     *
159
-     * @return string|null
160
-     */
161
-    public function getVariantName(): ?string
162
-    {
163
-        if ($this->variant === 'Latn') {
164
-            return 'Latin';
165
-        }
166
-
167
-        if ($this->variant === 'Cyrl') {
168
-            return 'Cyrillic';
169
-        }
170
-
171
-        return $this->variant;
172
-    }
173
-
174
-    /**
175
-     * Returns the region part of the locale.
176
-     *
177
-     * @return string|null
178
-     */
179
-    public function getRegion(): ?string
180
-    {
181
-        return $this->region;
182
-    }
183
-
184
-    /**
185
-     * Returns the region name for the current language.
186
-     *
187
-     * @return string|null
188
-     */
189
-    public function getRegionName(): ?string
190
-    {
191
-        return $this->region ? (static::regions()[$this->region] ?? $this->region) : null;
192
-    }
193
-
194
-    /**
195
-     * Returns the long ISO language name.
196
-     *
197
-     * @return string
198
-     */
199
-    public function getFullIsoName(): string
200
-    {
201
-        if (!$this->isoName) {
202
-            $this->isoName = $this->getNames()['isoName'];
203
-        }
204
-
205
-        return $this->isoName;
206
-    }
207
-
208
-    /**
209
-     * Set the ISO language name.
210
-     *
211
-     * @param string $isoName
212
-     */
213
-    public function setIsoName(string $isoName): self
214
-    {
215
-        $this->isoName = $isoName;
216
-
217
-        return $this;
218
-    }
219
-
220
-    /**
221
-     * Return the full name of the language in this language.
222
-     *
223
-     * @return string
224
-     */
225
-    public function getFullNativeName(): string
226
-    {
227
-        if (!$this->nativeName) {
228
-            $this->nativeName = $this->getNames()['nativeName'];
229
-        }
230
-
231
-        return $this->nativeName;
232
-    }
233
-
234
-    /**
235
-     * Set the name of the language in this language.
236
-     *
237
-     * @param string $nativeName
238
-     */
239
-    public function setNativeName(string $nativeName): self
240
-    {
241
-        $this->nativeName = $nativeName;
242
-
243
-        return $this;
244
-    }
245
-
246
-    /**
247
-     * Returns the short ISO language name.
248
-     *
249
-     * @return string
250
-     */
251
-    public function getIsoName(): string
252
-    {
253
-        $name = $this->getFullIsoName();
254
-
255
-        return trim(strstr($name, ',', true) ?: $name);
256
-    }
257
-
258
-    /**
259
-     * Get the short name of the language in this language.
260
-     *
261
-     * @return string
262
-     */
263
-    public function getNativeName(): string
264
-    {
265
-        $name = $this->getFullNativeName();
266
-
267
-        return trim(strstr($name, ',', true) ?: $name);
268
-    }
269
-
270
-    /**
271
-     * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
272
-     *
273
-     * @return string
274
-     */
275
-    public function getIsoDescription()
276
-    {
277
-        $region = $this->getRegionName();
278
-        $variant = $this->getVariantName();
279
-
280
-        return $this->getIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
281
-    }
282
-
283
-    /**
284
-     * Get a string with short native name, region in parentheses if applicable, variant in parentheses if applicable.
285
-     *
286
-     * @return string
287
-     */
288
-    public function getNativeDescription()
289
-    {
290
-        $region = $this->getRegionName();
291
-        $variant = $this->getVariantName();
292
-
293
-        return $this->getNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
294
-    }
295
-
296
-    /**
297
-     * Get a string with long ISO name, region in parentheses if applicable, variant in parentheses if applicable.
298
-     *
299
-     * @return string
300
-     */
301
-    public function getFullIsoDescription()
302
-    {
303
-        $region = $this->getRegionName();
304
-        $variant = $this->getVariantName();
305
-
306
-        return $this->getFullIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
307
-    }
308
-
309
-    /**
310
-     * Get a string with long native name, region in parentheses if applicable, variant in parentheses if applicable.
311
-     *
312
-     * @return string
313
-     */
314
-    public function getFullNativeDescription()
315
-    {
316
-        $region = $this->getRegionName();
317
-        $variant = $this->getVariantName();
318
-
319
-        return $this->getFullNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
320
-    }
321
-
322
-    /**
323
-     * Returns the original locale ID.
324
-     *
325
-     * @return string
326
-     */
327
-    public function __toString()
328
-    {
329
-        return $this->getId();
330
-    }
331
-
332
-    /**
333
-     * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
334
-     *
335
-     * @return string
336
-     */
337
-    #[ReturnTypeWillChange]
338
-    public function jsonSerialize()
339
-    {
340
-        return $this->getIsoDescription();
341
-    }
19
+	/**
20
+	 * @var array
21
+	 */
22
+	protected static $languagesNames;
23
+
24
+	/**
25
+	 * @var array
26
+	 */
27
+	protected static $regionsNames;
28
+
29
+	/**
30
+	 * @var string
31
+	 */
32
+	protected $id;
33
+
34
+	/**
35
+	 * @var string
36
+	 */
37
+	protected $code;
38
+
39
+	/**
40
+	 * @var string|null
41
+	 */
42
+	protected $variant;
43
+
44
+	/**
45
+	 * @var string|null
46
+	 */
47
+	protected $region;
48
+
49
+	/**
50
+	 * @var array
51
+	 */
52
+	protected $names;
53
+
54
+	/**
55
+	 * @var string
56
+	 */
57
+	protected $isoName;
58
+
59
+	/**
60
+	 * @var string
61
+	 */
62
+	protected $nativeName;
63
+
64
+	public function __construct(string $id)
65
+	{
66
+		$this->id = str_replace('-', '_', $id);
67
+		$parts = explode('_', $this->id);
68
+		$this->code = $parts[0];
69
+
70
+		if (isset($parts[1])) {
71
+			if (!preg_match('/^[A-Z]+$/', $parts[1])) {
72
+				$this->variant = $parts[1];
73
+				$parts[1] = $parts[2] ?? null;
74
+			}
75
+			if ($parts[1]) {
76
+				$this->region = $parts[1];
77
+			}
78
+		}
79
+	}
80
+
81
+	/**
82
+	 * Get the list of the known languages.
83
+	 *
84
+	 * @return array
85
+	 */
86
+	public static function all()
87
+	{
88
+		if (!static::$languagesNames) {
89
+			static::$languagesNames = require __DIR__.'/List/languages.php';
90
+		}
91
+
92
+		return static::$languagesNames;
93
+	}
94
+
95
+	/**
96
+	 * Get the list of the known regions.
97
+	 *
98
+	 * @return array
99
+	 */
100
+	public static function regions()
101
+	{
102
+		if (!static::$regionsNames) {
103
+			static::$regionsNames = require __DIR__.'/List/regions.php';
104
+		}
105
+
106
+		return static::$regionsNames;
107
+	}
108
+
109
+	/**
110
+	 * Get both isoName and nativeName as an array.
111
+	 *
112
+	 * @return array
113
+	 */
114
+	public function getNames(): array
115
+	{
116
+		if (!$this->names) {
117
+			$this->names = static::all()[$this->code] ?? [
118
+				'isoName' => $this->code,
119
+				'nativeName' => $this->code,
120
+			];
121
+		}
122
+
123
+		return $this->names;
124
+	}
125
+
126
+	/**
127
+	 * Returns the original locale ID.
128
+	 *
129
+	 * @return string
130
+	 */
131
+	public function getId(): string
132
+	{
133
+		return $this->id;
134
+	}
135
+
136
+	/**
137
+	 * Returns the code of the locale "en"/"fr".
138
+	 *
139
+	 * @return string
140
+	 */
141
+	public function getCode(): string
142
+	{
143
+		return $this->code;
144
+	}
145
+
146
+	/**
147
+	 * Returns the variant code such as cyrl/latn.
148
+	 *
149
+	 * @return string|null
150
+	 */
151
+	public function getVariant(): ?string
152
+	{
153
+		return $this->variant;
154
+	}
155
+
156
+	/**
157
+	 * Returns the variant such as Cyrillic/Latin.
158
+	 *
159
+	 * @return string|null
160
+	 */
161
+	public function getVariantName(): ?string
162
+	{
163
+		if ($this->variant === 'Latn') {
164
+			return 'Latin';
165
+		}
166
+
167
+		if ($this->variant === 'Cyrl') {
168
+			return 'Cyrillic';
169
+		}
170
+
171
+		return $this->variant;
172
+	}
173
+
174
+	/**
175
+	 * Returns the region part of the locale.
176
+	 *
177
+	 * @return string|null
178
+	 */
179
+	public function getRegion(): ?string
180
+	{
181
+		return $this->region;
182
+	}
183
+
184
+	/**
185
+	 * Returns the region name for the current language.
186
+	 *
187
+	 * @return string|null
188
+	 */
189
+	public function getRegionName(): ?string
190
+	{
191
+		return $this->region ? (static::regions()[$this->region] ?? $this->region) : null;
192
+	}
193
+
194
+	/**
195
+	 * Returns the long ISO language name.
196
+	 *
197
+	 * @return string
198
+	 */
199
+	public function getFullIsoName(): string
200
+	{
201
+		if (!$this->isoName) {
202
+			$this->isoName = $this->getNames()['isoName'];
203
+		}
204
+
205
+		return $this->isoName;
206
+	}
207
+
208
+	/**
209
+	 * Set the ISO language name.
210
+	 *
211
+	 * @param string $isoName
212
+	 */
213
+	public function setIsoName(string $isoName): self
214
+	{
215
+		$this->isoName = $isoName;
216
+
217
+		return $this;
218
+	}
219
+
220
+	/**
221
+	 * Return the full name of the language in this language.
222
+	 *
223
+	 * @return string
224
+	 */
225
+	public function getFullNativeName(): string
226
+	{
227
+		if (!$this->nativeName) {
228
+			$this->nativeName = $this->getNames()['nativeName'];
229
+		}
230
+
231
+		return $this->nativeName;
232
+	}
233
+
234
+	/**
235
+	 * Set the name of the language in this language.
236
+	 *
237
+	 * @param string $nativeName
238
+	 */
239
+	public function setNativeName(string $nativeName): self
240
+	{
241
+		$this->nativeName = $nativeName;
242
+
243
+		return $this;
244
+	}
245
+
246
+	/**
247
+	 * Returns the short ISO language name.
248
+	 *
249
+	 * @return string
250
+	 */
251
+	public function getIsoName(): string
252
+	{
253
+		$name = $this->getFullIsoName();
254
+
255
+		return trim(strstr($name, ',', true) ?: $name);
256
+	}
257
+
258
+	/**
259
+	 * Get the short name of the language in this language.
260
+	 *
261
+	 * @return string
262
+	 */
263
+	public function getNativeName(): string
264
+	{
265
+		$name = $this->getFullNativeName();
266
+
267
+		return trim(strstr($name, ',', true) ?: $name);
268
+	}
269
+
270
+	/**
271
+	 * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
272
+	 *
273
+	 * @return string
274
+	 */
275
+	public function getIsoDescription()
276
+	{
277
+		$region = $this->getRegionName();
278
+		$variant = $this->getVariantName();
279
+
280
+		return $this->getIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
281
+	}
282
+
283
+	/**
284
+	 * Get a string with short native name, region in parentheses if applicable, variant in parentheses if applicable.
285
+	 *
286
+	 * @return string
287
+	 */
288
+	public function getNativeDescription()
289
+	{
290
+		$region = $this->getRegionName();
291
+		$variant = $this->getVariantName();
292
+
293
+		return $this->getNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
294
+	}
295
+
296
+	/**
297
+	 * Get a string with long ISO name, region in parentheses if applicable, variant in parentheses if applicable.
298
+	 *
299
+	 * @return string
300
+	 */
301
+	public function getFullIsoDescription()
302
+	{
303
+		$region = $this->getRegionName();
304
+		$variant = $this->getVariantName();
305
+
306
+		return $this->getFullIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
307
+	}
308
+
309
+	/**
310
+	 * Get a string with long native name, region in parentheses if applicable, variant in parentheses if applicable.
311
+	 *
312
+	 * @return string
313
+	 */
314
+	public function getFullNativeDescription()
315
+	{
316
+		$region = $this->getRegionName();
317
+		$variant = $this->getVariantName();
318
+
319
+		return $this->getFullNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
320
+	}
321
+
322
+	/**
323
+	 * Returns the original locale ID.
324
+	 *
325
+	 * @return string
326
+	 */
327
+	public function __toString()
328
+	{
329
+		return $this->getId();
330
+	}
331
+
332
+	/**
333
+	 * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
334
+	 *
335
+	 * @return string
336
+	 */
337
+	#[ReturnTypeWillChange]
338
+	public function jsonSerialize()
339
+	{
340
+		return $this->getIsoDescription();
341
+	}
342 342
 }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/src/Carbon/AbstractTranslator.php 2 patches
Indentation   +374 added lines, -374 removed lines patch added patch discarded remove patch
@@ -20,378 +20,378 @@
 block discarded – undo
20 20
 
21 21
 abstract class AbstractTranslator extends Translation\Translator
22 22
 {
23
-    /**
24
-     * Translator singletons for each language.
25
-     *
26
-     * @var array
27
-     */
28
-    protected static $singletons = [];
29
-
30
-    /**
31
-     * List of custom localized messages.
32
-     *
33
-     * @var array
34
-     */
35
-    protected $messages = [];
36
-
37
-    /**
38
-     * List of custom directories that contain translation files.
39
-     *
40
-     * @var string[]
41
-     */
42
-    protected $directories = [];
43
-
44
-    /**
45
-     * Set to true while constructing.
46
-     *
47
-     * @var bool
48
-     */
49
-    protected $initializing = false;
50
-
51
-    /**
52
-     * List of locales aliases.
53
-     *
54
-     * @var string[]
55
-     */
56
-    protected $aliases = [
57
-        'me' => 'sr_Latn_ME',
58
-        'scr' => 'sh',
59
-    ];
60
-
61
-    /**
62
-     * Return a singleton instance of Translator.
63
-     *
64
-     * @param string|null $locale optional initial locale ("en" - english by default)
65
-     *
66
-     * @return static
67
-     */
68
-    public static function get($locale = null)
69
-    {
70
-        $locale = $locale ?: 'en';
71
-        $key = static::class === Translator::class ? $locale : static::class.'|'.$locale;
72
-
73
-        if (!isset(static::$singletons[$key])) {
74
-            static::$singletons[$key] = new static($locale);
75
-        }
76
-
77
-        return static::$singletons[$key];
78
-    }
79
-
80
-    public function __construct($locale, MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
81
-    {
82
-        parent::setLocale($locale);
83
-        $this->initializing = true;
84
-        $this->directories = [__DIR__.'/Lang'];
85
-        $this->addLoader('array', new ArrayLoader());
86
-        parent::__construct($locale, $formatter, $cacheDir, $debug);
87
-        $this->initializing = false;
88
-    }
89
-
90
-    /**
91
-     * Returns the list of directories translation files are searched in.
92
-     *
93
-     * @return array
94
-     */
95
-    public function getDirectories(): array
96
-    {
97
-        return $this->directories;
98
-    }
99
-
100
-    /**
101
-     * Set list of directories translation files are searched in.
102
-     *
103
-     * @param array $directories new directories list
104
-     *
105
-     * @return $this
106
-     */
107
-    public function setDirectories(array $directories)
108
-    {
109
-        $this->directories = $directories;
110
-
111
-        return $this;
112
-    }
113
-
114
-    /**
115
-     * Add a directory to the list translation files are searched in.
116
-     *
117
-     * @param string $directory new directory
118
-     *
119
-     * @return $this
120
-     */
121
-    public function addDirectory(string $directory)
122
-    {
123
-        $this->directories[] = $directory;
124
-
125
-        return $this;
126
-    }
127
-
128
-    /**
129
-     * Remove a directory from the list translation files are searched in.
130
-     *
131
-     * @param string $directory directory path
132
-     *
133
-     * @return $this
134
-     */
135
-    public function removeDirectory(string $directory)
136
-    {
137
-        $search = rtrim(strtr($directory, '\\', '/'), '/');
138
-
139
-        return $this->setDirectories(array_filter($this->getDirectories(), function ($item) use ($search) {
140
-            return rtrim(strtr($item, '\\', '/'), '/') !== $search;
141
-        }));
142
-    }
143
-
144
-    /**
145
-     * Reset messages of a locale (all locale if no locale passed).
146
-     * Remove custom messages and reload initial messages from matching
147
-     * file in Lang directory.
148
-     *
149
-     * @param string|null $locale
150
-     *
151
-     * @return bool
152
-     */
153
-    public function resetMessages($locale = null)
154
-    {
155
-        if ($locale === null) {
156
-            $this->messages = [];
157
-
158
-            return true;
159
-        }
160
-
161
-        foreach ($this->getDirectories() as $directory) {
162
-            $data = @include sprintf('%s/%s.php', rtrim($directory, '\\/'), $locale);
163
-
164
-            if ($data !== false) {
165
-                $this->messages[$locale] = $data;
166
-                $this->addResource('array', $this->messages[$locale], $locale);
167
-
168
-                return true;
169
-            }
170
-        }
171
-
172
-        return false;
173
-    }
174
-
175
-    /**
176
-     * Returns the list of files matching a given locale prefix (or all if empty).
177
-     *
178
-     * @param string $prefix prefix required to filter result
179
-     *
180
-     * @return array
181
-     */
182
-    public function getLocalesFiles($prefix = '')
183
-    {
184
-        $files = [];
185
-
186
-        foreach ($this->getDirectories() as $directory) {
187
-            $directory = rtrim($directory, '\\/');
188
-
189
-            foreach (glob("$directory/$prefix*.php") as $file) {
190
-                $files[] = $file;
191
-            }
192
-        }
193
-
194
-        return array_unique($files);
195
-    }
196
-
197
-    /**
198
-     * Returns the list of internally available locales and already loaded custom locales.
199
-     * (It will ignore custom translator dynamic loading.)
200
-     *
201
-     * @param string $prefix prefix required to filter result
202
-     *
203
-     * @return array
204
-     */
205
-    public function getAvailableLocales($prefix = '')
206
-    {
207
-        $locales = [];
208
-        foreach ($this->getLocalesFiles($prefix) as $file) {
209
-            $locales[] = substr($file, strrpos($file, '/') + 1, -4);
210
-        }
211
-
212
-        return array_unique(array_merge($locales, array_keys($this->messages)));
213
-    }
214
-
215
-    protected function translate(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
216
-    {
217
-        if ($domain === null) {
218
-            $domain = 'messages';
219
-        }
220
-
221
-        $catalogue = $this->getCatalogue($locale);
222
-        $format = $this instanceof TranslatorStrongTypeInterface
223
-            ? $this->getFromCatalogue($catalogue, (string) $id, $domain)
224
-            : $this->getCatalogue($locale)->get((string) $id, $domain); // @codeCoverageIgnore
225
-
226
-        if ($format instanceof Closure) {
227
-            // @codeCoverageIgnoreStart
228
-            try {
229
-                $count = (new ReflectionFunction($format))->getNumberOfRequiredParameters();
230
-            } catch (ReflectionException $exception) {
231
-                $count = 0;
232
-            }
233
-            // @codeCoverageIgnoreEnd
234
-
235
-            return $format(
236
-                ...array_values($parameters),
237
-                ...array_fill(0, max(0, $count - \count($parameters)), null)
238
-            );
239
-        }
240
-
241
-        return parent::trans($id, $parameters, $domain, $locale);
242
-    }
243
-
244
-    /**
245
-     * Init messages language from matching file in Lang directory.
246
-     *
247
-     * @param string $locale
248
-     *
249
-     * @return bool
250
-     */
251
-    protected function loadMessagesFromFile($locale)
252
-    {
253
-        return isset($this->messages[$locale]) || $this->resetMessages($locale);
254
-    }
255
-
256
-    /**
257
-     * Set messages of a locale and take file first if present.
258
-     *
259
-     * @param string $locale
260
-     * @param array  $messages
261
-     *
262
-     * @return $this
263
-     */
264
-    public function setMessages($locale, $messages)
265
-    {
266
-        $this->loadMessagesFromFile($locale);
267
-        $this->addResource('array', $messages, $locale);
268
-        $this->messages[$locale] = array_merge(
269
-            $this->messages[$locale] ?? [],
270
-            $messages
271
-        );
272
-
273
-        return $this;
274
-    }
275
-
276
-    /**
277
-     * Set messages of the current locale and take file first if present.
278
-     *
279
-     * @param array $messages
280
-     *
281
-     * @return $this
282
-     */
283
-    public function setTranslations($messages)
284
-    {
285
-        return $this->setMessages($this->getLocale(), $messages);
286
-    }
287
-
288
-    /**
289
-     * Get messages of a locale, if none given, return all the
290
-     * languages.
291
-     *
292
-     * @param string|null $locale
293
-     *
294
-     * @return array
295
-     */
296
-    public function getMessages($locale = null)
297
-    {
298
-        return $locale === null ? $this->messages : $this->messages[$locale];
299
-    }
300
-
301
-    /**
302
-     * Set the current translator locale and indicate if the source locale file exists
303
-     *
304
-     * @param string $locale locale ex. en
305
-     *
306
-     * @return bool
307
-     */
308
-    public function setLocale($locale)
309
-    {
310
-        $locale = preg_replace_callback('/[-_]([a-z]{2,}|\d{2,})/', function ($matches) {
311
-            // _2-letters or YUE is a region, _3+-letters is a variant
312
-            $upper = strtoupper($matches[1]);
313
-
314
-            if ($upper === 'YUE' || $upper === 'ISO' || \strlen($upper) < 3) {
315
-                return "_$upper";
316
-            }
317
-
318
-            return '_'.ucfirst($matches[1]);
319
-        }, strtolower($locale));
320
-
321
-        $previousLocale = $this->getLocale();
322
-
323
-        if ($previousLocale === $locale && isset($this->messages[$locale])) {
324
-            return true;
325
-        }
326
-
327
-        unset(static::$singletons[$previousLocale]);
328
-
329
-        if ($locale === 'auto') {
330
-            $completeLocale = setlocale(LC_TIME, '0');
331
-            $locale = preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale);
332
-            $locales = $this->getAvailableLocales($locale);
333
-
334
-            $completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale);
335
-
336
-            $getScore = function ($language) use ($completeLocaleChunks) {
337
-                return self::compareChunkLists($completeLocaleChunks, preg_split('/[_.-]+/', $language));
338
-            };
339
-
340
-            usort($locales, function ($first, $second) use ($getScore) {
341
-                return $getScore($second) <=> $getScore($first);
342
-            });
343
-
344
-            $locale = $locales[0];
345
-        }
346
-
347
-        if (isset($this->aliases[$locale])) {
348
-            $locale = $this->aliases[$locale];
349
-        }
350
-
351
-        // If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
352
-        if (str_contains($locale, '_') &&
353
-            $this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
354
-        ) {
355
-            parent::setLocale($macroLocale);
356
-        }
357
-
358
-        if (!$this->loadMessagesFromFile($locale) && !$this->initializing) {
359
-            return false;
360
-        }
361
-
362
-        parent::setLocale($locale);
363
-
364
-        return true;
365
-    }
366
-
367
-    /**
368
-     * Show locale on var_dump().
369
-     *
370
-     * @return array
371
-     */
372
-    public function __debugInfo()
373
-    {
374
-        return [
375
-            'locale' => $this->getLocale(),
376
-        ];
377
-    }
378
-
379
-    private static function compareChunkLists($referenceChunks, $chunks)
380
-    {
381
-        $score = 0;
382
-
383
-        foreach ($referenceChunks as $index => $chunk) {
384
-            if (!isset($chunks[$index])) {
385
-                $score++;
386
-
387
-                continue;
388
-            }
389
-
390
-            if (strtolower($chunks[$index]) === strtolower($chunk)) {
391
-                $score += 10;
392
-            }
393
-        }
394
-
395
-        return $score;
396
-    }
23
+	/**
24
+	 * Translator singletons for each language.
25
+	 *
26
+	 * @var array
27
+	 */
28
+	protected static $singletons = [];
29
+
30
+	/**
31
+	 * List of custom localized messages.
32
+	 *
33
+	 * @var array
34
+	 */
35
+	protected $messages = [];
36
+
37
+	/**
38
+	 * List of custom directories that contain translation files.
39
+	 *
40
+	 * @var string[]
41
+	 */
42
+	protected $directories = [];
43
+
44
+	/**
45
+	 * Set to true while constructing.
46
+	 *
47
+	 * @var bool
48
+	 */
49
+	protected $initializing = false;
50
+
51
+	/**
52
+	 * List of locales aliases.
53
+	 *
54
+	 * @var string[]
55
+	 */
56
+	protected $aliases = [
57
+		'me' => 'sr_Latn_ME',
58
+		'scr' => 'sh',
59
+	];
60
+
61
+	/**
62
+	 * Return a singleton instance of Translator.
63
+	 *
64
+	 * @param string|null $locale optional initial locale ("en" - english by default)
65
+	 *
66
+	 * @return static
67
+	 */
68
+	public static function get($locale = null)
69
+	{
70
+		$locale = $locale ?: 'en';
71
+		$key = static::class === Translator::class ? $locale : static::class.'|'.$locale;
72
+
73
+		if (!isset(static::$singletons[$key])) {
74
+			static::$singletons[$key] = new static($locale);
75
+		}
76
+
77
+		return static::$singletons[$key];
78
+	}
79
+
80
+	public function __construct($locale, MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
81
+	{
82
+		parent::setLocale($locale);
83
+		$this->initializing = true;
84
+		$this->directories = [__DIR__.'/Lang'];
85
+		$this->addLoader('array', new ArrayLoader());
86
+		parent::__construct($locale, $formatter, $cacheDir, $debug);
87
+		$this->initializing = false;
88
+	}
89
+
90
+	/**
91
+	 * Returns the list of directories translation files are searched in.
92
+	 *
93
+	 * @return array
94
+	 */
95
+	public function getDirectories(): array
96
+	{
97
+		return $this->directories;
98
+	}
99
+
100
+	/**
101
+	 * Set list of directories translation files are searched in.
102
+	 *
103
+	 * @param array $directories new directories list
104
+	 *
105
+	 * @return $this
106
+	 */
107
+	public function setDirectories(array $directories)
108
+	{
109
+		$this->directories = $directories;
110
+
111
+		return $this;
112
+	}
113
+
114
+	/**
115
+	 * Add a directory to the list translation files are searched in.
116
+	 *
117
+	 * @param string $directory new directory
118
+	 *
119
+	 * @return $this
120
+	 */
121
+	public function addDirectory(string $directory)
122
+	{
123
+		$this->directories[] = $directory;
124
+
125
+		return $this;
126
+	}
127
+
128
+	/**
129
+	 * Remove a directory from the list translation files are searched in.
130
+	 *
131
+	 * @param string $directory directory path
132
+	 *
133
+	 * @return $this
134
+	 */
135
+	public function removeDirectory(string $directory)
136
+	{
137
+		$search = rtrim(strtr($directory, '\\', '/'), '/');
138
+
139
+		return $this->setDirectories(array_filter($this->getDirectories(), function ($item) use ($search) {
140
+			return rtrim(strtr($item, '\\', '/'), '/') !== $search;
141
+		}));
142
+	}
143
+
144
+	/**
145
+	 * Reset messages of a locale (all locale if no locale passed).
146
+	 * Remove custom messages and reload initial messages from matching
147
+	 * file in Lang directory.
148
+	 *
149
+	 * @param string|null $locale
150
+	 *
151
+	 * @return bool
152
+	 */
153
+	public function resetMessages($locale = null)
154
+	{
155
+		if ($locale === null) {
156
+			$this->messages = [];
157
+
158
+			return true;
159
+		}
160
+
161
+		foreach ($this->getDirectories() as $directory) {
162
+			$data = @include sprintf('%s/%s.php', rtrim($directory, '\\/'), $locale);
163
+
164
+			if ($data !== false) {
165
+				$this->messages[$locale] = $data;
166
+				$this->addResource('array', $this->messages[$locale], $locale);
167
+
168
+				return true;
169
+			}
170
+		}
171
+
172
+		return false;
173
+	}
174
+
175
+	/**
176
+	 * Returns the list of files matching a given locale prefix (or all if empty).
177
+	 *
178
+	 * @param string $prefix prefix required to filter result
179
+	 *
180
+	 * @return array
181
+	 */
182
+	public function getLocalesFiles($prefix = '')
183
+	{
184
+		$files = [];
185
+
186
+		foreach ($this->getDirectories() as $directory) {
187
+			$directory = rtrim($directory, '\\/');
188
+
189
+			foreach (glob("$directory/$prefix*.php") as $file) {
190
+				$files[] = $file;
191
+			}
192
+		}
193
+
194
+		return array_unique($files);
195
+	}
196
+
197
+	/**
198
+	 * Returns the list of internally available locales and already loaded custom locales.
199
+	 * (It will ignore custom translator dynamic loading.)
200
+	 *
201
+	 * @param string $prefix prefix required to filter result
202
+	 *
203
+	 * @return array
204
+	 */
205
+	public function getAvailableLocales($prefix = '')
206
+	{
207
+		$locales = [];
208
+		foreach ($this->getLocalesFiles($prefix) as $file) {
209
+			$locales[] = substr($file, strrpos($file, '/') + 1, -4);
210
+		}
211
+
212
+		return array_unique(array_merge($locales, array_keys($this->messages)));
213
+	}
214
+
215
+	protected function translate(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
216
+	{
217
+		if ($domain === null) {
218
+			$domain = 'messages';
219
+		}
220
+
221
+		$catalogue = $this->getCatalogue($locale);
222
+		$format = $this instanceof TranslatorStrongTypeInterface
223
+			? $this->getFromCatalogue($catalogue, (string) $id, $domain)
224
+			: $this->getCatalogue($locale)->get((string) $id, $domain); // @codeCoverageIgnore
225
+
226
+		if ($format instanceof Closure) {
227
+			// @codeCoverageIgnoreStart
228
+			try {
229
+				$count = (new ReflectionFunction($format))->getNumberOfRequiredParameters();
230
+			} catch (ReflectionException $exception) {
231
+				$count = 0;
232
+			}
233
+			// @codeCoverageIgnoreEnd
234
+
235
+			return $format(
236
+				...array_values($parameters),
237
+				...array_fill(0, max(0, $count - \count($parameters)), null)
238
+			);
239
+		}
240
+
241
+		return parent::trans($id, $parameters, $domain, $locale);
242
+	}
243
+
244
+	/**
245
+	 * Init messages language from matching file in Lang directory.
246
+	 *
247
+	 * @param string $locale
248
+	 *
249
+	 * @return bool
250
+	 */
251
+	protected function loadMessagesFromFile($locale)
252
+	{
253
+		return isset($this->messages[$locale]) || $this->resetMessages($locale);
254
+	}
255
+
256
+	/**
257
+	 * Set messages of a locale and take file first if present.
258
+	 *
259
+	 * @param string $locale
260
+	 * @param array  $messages
261
+	 *
262
+	 * @return $this
263
+	 */
264
+	public function setMessages($locale, $messages)
265
+	{
266
+		$this->loadMessagesFromFile($locale);
267
+		$this->addResource('array', $messages, $locale);
268
+		$this->messages[$locale] = array_merge(
269
+			$this->messages[$locale] ?? [],
270
+			$messages
271
+		);
272
+
273
+		return $this;
274
+	}
275
+
276
+	/**
277
+	 * Set messages of the current locale and take file first if present.
278
+	 *
279
+	 * @param array $messages
280
+	 *
281
+	 * @return $this
282
+	 */
283
+	public function setTranslations($messages)
284
+	{
285
+		return $this->setMessages($this->getLocale(), $messages);
286
+	}
287
+
288
+	/**
289
+	 * Get messages of a locale, if none given, return all the
290
+	 * languages.
291
+	 *
292
+	 * @param string|null $locale
293
+	 *
294
+	 * @return array
295
+	 */
296
+	public function getMessages($locale = null)
297
+	{
298
+		return $locale === null ? $this->messages : $this->messages[$locale];
299
+	}
300
+
301
+	/**
302
+	 * Set the current translator locale and indicate if the source locale file exists
303
+	 *
304
+	 * @param string $locale locale ex. en
305
+	 *
306
+	 * @return bool
307
+	 */
308
+	public function setLocale($locale)
309
+	{
310
+		$locale = preg_replace_callback('/[-_]([a-z]{2,}|\d{2,})/', function ($matches) {
311
+			// _2-letters or YUE is a region, _3+-letters is a variant
312
+			$upper = strtoupper($matches[1]);
313
+
314
+			if ($upper === 'YUE' || $upper === 'ISO' || \strlen($upper) < 3) {
315
+				return "_$upper";
316
+			}
317
+
318
+			return '_'.ucfirst($matches[1]);
319
+		}, strtolower($locale));
320
+
321
+		$previousLocale = $this->getLocale();
322
+
323
+		if ($previousLocale === $locale && isset($this->messages[$locale])) {
324
+			return true;
325
+		}
326
+
327
+		unset(static::$singletons[$previousLocale]);
328
+
329
+		if ($locale === 'auto') {
330
+			$completeLocale = setlocale(LC_TIME, '0');
331
+			$locale = preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale);
332
+			$locales = $this->getAvailableLocales($locale);
333
+
334
+			$completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale);
335
+
336
+			$getScore = function ($language) use ($completeLocaleChunks) {
337
+				return self::compareChunkLists($completeLocaleChunks, preg_split('/[_.-]+/', $language));
338
+			};
339
+
340
+			usort($locales, function ($first, $second) use ($getScore) {
341
+				return $getScore($second) <=> $getScore($first);
342
+			});
343
+
344
+			$locale = $locales[0];
345
+		}
346
+
347
+		if (isset($this->aliases[$locale])) {
348
+			$locale = $this->aliases[$locale];
349
+		}
350
+
351
+		// If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
352
+		if (str_contains($locale, '_') &&
353
+			$this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
354
+		) {
355
+			parent::setLocale($macroLocale);
356
+		}
357
+
358
+		if (!$this->loadMessagesFromFile($locale) && !$this->initializing) {
359
+			return false;
360
+		}
361
+
362
+		parent::setLocale($locale);
363
+
364
+		return true;
365
+	}
366
+
367
+	/**
368
+	 * Show locale on var_dump().
369
+	 *
370
+	 * @return array
371
+	 */
372
+	public function __debugInfo()
373
+	{
374
+		return [
375
+			'locale' => $this->getLocale(),
376
+		];
377
+	}
378
+
379
+	private static function compareChunkLists($referenceChunks, $chunks)
380
+	{
381
+		$score = 0;
382
+
383
+		foreach ($referenceChunks as $index => $chunk) {
384
+			if (!isset($chunks[$index])) {
385
+				$score++;
386
+
387
+				continue;
388
+			}
389
+
390
+			if (strtolower($chunks[$index]) === strtolower($chunk)) {
391
+				$score += 10;
392
+			}
393
+		}
394
+
395
+		return $score;
396
+	}
397 397
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
     {
137 137
         $search = rtrim(strtr($directory, '\\', '/'), '/');
138 138
 
139
-        return $this->setDirectories(array_filter($this->getDirectories(), function ($item) use ($search) {
139
+        return $this->setDirectories(array_filter($this->getDirectories(), function($item) use ($search) {
140 140
             return rtrim(strtr($item, '\\', '/'), '/') !== $search;
141 141
         }));
142 142
     }
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
      */
308 308
     public function setLocale($locale)
309 309
     {
310
-        $locale = preg_replace_callback('/[-_]([a-z]{2,}|\d{2,})/', function ($matches) {
310
+        $locale = preg_replace_callback('/[-_]([a-z]{2,}|\d{2,})/', function($matches) {
311 311
             // _2-letters or YUE is a region, _3+-letters is a variant
312 312
             $upper = strtoupper($matches[1]);
313 313
 
@@ -333,11 +333,11 @@  discard block
 block discarded – undo
333 333
 
334 334
             $completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale);
335 335
 
336
-            $getScore = function ($language) use ($completeLocaleChunks) {
336
+            $getScore = function($language) use ($completeLocaleChunks) {
337 337
                 return self::compareChunkLists($completeLocaleChunks, preg_split('/[_.-]+/', $language));
338 338
             };
339 339
 
340
-            usort($locales, function ($first, $second) use ($getScore) {
340
+            usort($locales, function($first, $second) use ($getScore) {
341 341
                 return $getScore($second) <=> $getScore($first);
342 342
             });
343 343
 
Please login to merge, or discard this patch.
htdocs/includes/webklex/php-imap/vendor/nesbot/carbon/src/Carbon/Carbon.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -509,15 +509,15 @@
 block discarded – undo
509 509
  */
510 510
 class Carbon extends DateTime implements CarbonInterface
511 511
 {
512
-    use Date;
512
+	use Date;
513 513
 
514
-    /**
515
-     * Returns true if the current class/instance is mutable.
516
-     *
517
-     * @return bool
518
-     */
519
-    public static function isMutable()
520
-    {
521
-        return true;
522
-    }
514
+	/**
515
+	 * Returns true if the current class/instance is mutable.
516
+	 *
517
+	 * @return bool
518
+	 */
519
+	public static function isMutable()
520
+	{
521
+		return true;
522
+	}
523 523
 }
Please login to merge, or discard this patch.