Vous êtes connecté en tant que anonymous Se Deconnecter
Browse code

Application modulaire fonctionnelle !

Emmanuel ROY authored on 12/08/2019 15:10:25
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1916 +0,0 @@
1
-<?php
2
-
3
-/**
4
- * This file is part of the Carbon package.
5
- *
6
- * (c) Brian Nesbitt <brian@nesbot.com>
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
-namespace Carbon;
12
-
13
-use BadMethodCallException;
14
-use Carbon\Traits\Options;
15
-use Closure;
16
-use DateInterval;
17
-use InvalidArgumentException;
18
-use ReflectionClass;
19
-use ReflectionMethod;
20
-
21
-/**
22
- * A simple API extension for DateInterval.
23
- * The implementation provides helpers to handle weeks but only days are saved.
24
- * Weeks are calculated based on the total days of the current instance.
25
- *
26
- * @property int $years Total years of the current interval.
27
- * @property int $months Total months of the current interval.
28
- * @property int $weeks Total weeks of the current interval calculated from the days.
29
- * @property int $dayz Total days of the current interval (weeks * 7 + days).
30
- * @property int $hours Total hours of the current interval.
31
- * @property int $minutes Total minutes of the current interval.
32
- * @property int $seconds Total seconds of the current interval.
33
- * @property int $microseconds Total microseconds of the current interval.
34
- * @property int $milliseconds Total microseconds of the current interval.
35
- * @property-read int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
36
- * @property-read int $daysExcludeWeeks alias of dayzExcludeWeeks
37
- * @property-read float $totalYears Number of years equivalent to the interval.
38
- * @property-read float $totalMonths Number of months equivalent to the interval.
39
- * @property-read float $totalWeeks Number of weeks equivalent to the interval.
40
- * @property-read float $totalDays Number of days equivalent to the interval.
41
- * @property-read float $totalDayz Alias for totalDays.
42
- * @property-read float $totalHours Number of hours equivalent to the interval.
43
- * @property-read float $totalMinutes Number of minutes equivalent to the interval.
44
- * @property-read float $totalSeconds Number of seconds equivalent to the interval.
45
- * @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval.
46
- * @property-read float $totalMicroseconds Number of microseconds equivalent to the interval.
47
- * @property-read string $locale locale of the current instance
48
- *
49
- * @method static CarbonInterval years($years = 1) Create instance specifying a number of years.
50
- * @method static CarbonInterval year($years = 1) Alias for years()
51
- * @method static CarbonInterval months($months = 1) Create instance specifying a number of months.
52
- * @method static CarbonInterval month($months = 1) Alias for months()
53
- * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks.
54
- * @method static CarbonInterval week($weeks = 1) Alias for weeks()
55
- * @method static CarbonInterval days($days = 1) Create instance specifying a number of days.
56
- * @method static CarbonInterval dayz($days = 1) Alias for days()
57
- * @method static CarbonInterval day($days = 1) Alias for days()
58
- * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours.
59
- * @method static CarbonInterval hour($hours = 1) Alias for hours()
60
- * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes.
61
- * @method static CarbonInterval minute($minutes = 1) Alias for minutes()
62
- * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds.
63
- * @method static CarbonInterval second($seconds = 1) Alias for seconds()
64
- * @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds.
65
- * @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds()
66
- * @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds.
67
- * @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds()
68
- * @method CarbonInterval years($years = 1) Set the years portion of the current interval.
69
- * @method CarbonInterval year($years = 1) Alias for years().
70
- * @method CarbonInterval months($months = 1) Set the months portion of the current interval.
71
- * @method CarbonInterval month($months = 1) Alias for months().
72
- * @method CarbonInterval weeks($weeks = 1) Set the weeks portion of the current interval.  Will overwrite dayz value.
73
- * @method CarbonInterval week($weeks = 1) Alias for weeks().
74
- * @method CarbonInterval days($days = 1) Set the days portion of the current interval.
75
- * @method CarbonInterval dayz($days = 1) Alias for days().
76
- * @method CarbonInterval day($days = 1) Alias for days().
77
- * @method CarbonInterval hours($hours = 1) Set the hours portion of the current interval.
78
- * @method CarbonInterval hour($hours = 1) Alias for hours().
79
- * @method CarbonInterval minutes($minutes = 1) Set the minutes portion of the current interval.
80
- * @method CarbonInterval minute($minutes = 1) Alias for minutes().
81
- * @method CarbonInterval seconds($seconds = 1) Set the seconds portion of the current interval.
82
- * @method CarbonInterval second($seconds = 1) Alias for seconds().
83
- * @method CarbonInterval milliseconds($seconds = 1) Set the seconds portion of the current interval.
84
- * @method CarbonInterval millisecond($seconds = 1) Alias for seconds().
85
- * @method CarbonInterval microseconds($seconds = 1) Set the seconds portion of the current interval.
86
- * @method CarbonInterval microsecond($seconds = 1) Alias for seconds().
87
- */
88
-class CarbonInterval extends DateInterval
89
-{
90
-    use Options;
91
-
92
-    /**
93
-     * Interval spec period designators
94
-     */
95
-    const PERIOD_PREFIX = 'P';
96
-    const PERIOD_YEARS = 'Y';
97
-    const PERIOD_MONTHS = 'M';
98
-    const PERIOD_DAYS = 'D';
99
-    const PERIOD_TIME_PREFIX = 'T';
100
-    const PERIOD_HOURS = 'H';
101
-    const PERIOD_MINUTES = 'M';
102
-    const PERIOD_SECONDS = 'S';
103
-
104
-    /**
105
-     * A translator to ... er ... translate stuff
106
-     *
107
-     * @var \Symfony\Component\Translation\TranslatorInterface
108
-     */
109
-    protected static $translator;
110
-
111
-    /**
112
-     * @var array|null
113
-     */
114
-    protected static $cascadeFactors;
115
-
116
-    /**
117
-     * @var array|null
118
-     */
119
-    private static $flipCascadeFactors;
120
-
121
-    /**
122
-     * The registered macros.
123
-     *
124
-     * @var array
125
-     */
126
-    protected static $macros = [];
127
-
128
-    /**
129
-     * Timezone handler for settings() method.
130
-     *
131
-     * @var mixed
132
-     */
133
-    protected $tzName;
134
-
135
-    /**
136
-     * Set the instance's timezone from a string or object and add/subtract the offset difference.
137
-     *
138
-     * @param \DateTimeZone|string $tzName
139
-     *
140
-     * @return static
141
-     */
142
-    public function shiftTimezone($tzName)
143
-    {
144
-        $this->tzName = $tzName;
145
-
146
-        return $this;
147
-    }
148
-
149
-    /**
150
-     * Mapping of units and factors for cascading.
151
-     *
152
-     * Should only be modified by changing the factors or referenced constants.
153
-     *
154
-     * @return array
155
-     */
156
-    public static function getCascadeFactors()
157
-    {
158
-        return static::$cascadeFactors ?: [
159
-            'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
160
-            'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
161
-            'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
162
-            'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
163
-            'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
164
-            'months' => [Carbon::DAYS_PER_WEEK * Carbon::WEEKS_PER_MONTH, 'dayz'],
165
-            'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
166
-        ];
167
-    }
168
-
169
-    private static function standardizeUnit($unit)
170
-    {
171
-        $unit = rtrim($unit, 'sz').'s';
172
-
173
-        return $unit === 'days' ? 'dayz' : $unit;
174
-    }
175
-
176
-    private static function getFlipCascadeFactors()
177
-    {
178
-        if (!self::$flipCascadeFactors) {
179
-            self::$flipCascadeFactors = [];
180
-            foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
181
-                self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
182
-            }
183
-        }
184
-
185
-        return self::$flipCascadeFactors;
186
-    }
187
-
188
-    /**
189
-     * Set default cascading factors for ->cascade() method.
190
-     *
191
-     * @param array $cascadeFactors
192
-     */
193
-    public static function setCascadeFactors(array $cascadeFactors)
194
-    {
195
-        self::$flipCascadeFactors = null;
196
-        static::$cascadeFactors = $cascadeFactors;
197
-    }
198
-
199
-    ///////////////////////////////////////////////////////////////////
200
-    //////////////////////////// CONSTRUCTORS /////////////////////////
201
-    ///////////////////////////////////////////////////////////////////
202
-
203
-    /**
204
-     * Create a new CarbonInterval instance.
205
-     *
206
-     * @param int $years
207
-     * @param int $months
208
-     * @param int $weeks
209
-     * @param int $days
210
-     * @param int $hours
211
-     * @param int $minutes
212
-     * @param int $seconds
213
-     * @param int $microseconds
214
-     *
215
-     * @throws \Exception
216
-     */
217
-    public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
218
-    {
219
-        $spec = $years;
220
-
221
-        if (!is_string($spec) || floatval($years) || preg_match('/^[0-9.]/', $years)) {
222
-            $spec = static::PERIOD_PREFIX;
223
-
224
-            $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
225
-            $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
226
-
227
-            $specDays = 0;
228
-            $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
229
-            $specDays += $days > 0 ? $days : 0;
230
-
231
-            $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
232
-
233
-            if ($hours > 0 || $minutes > 0 || $seconds > 0) {
234
-                $spec .= static::PERIOD_TIME_PREFIX;
235
-                $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
236
-                $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
237
-                $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
238
-            }
239
-
240
-            if ($spec === static::PERIOD_PREFIX) {
241
-                // Allow the zero interval.
242
-                $spec .= '0'.static::PERIOD_YEARS;
243
-            }
244
-        }
245
-
246
-        parent::__construct($spec);
247
-
248
-        if (!is_null($microseconds)) {
249
-            $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
250
-        }
251
-    }
252
-
253
-    /**
254
-     * Returns the factor for a given source-to-target couple.
255
-     *
256
-     * @param string $source
257
-     * @param string $target
258
-     *
259
-     * @return int|null
260
-     */
261
-    public static function getFactor($source, $target)
262
-    {
263
-        $source = self::standardizeUnit($source);
264
-        $target = self::standardizeUnit($target);
265
-        $factors = static::getFlipCascadeFactors();
266
-        if (isset($factors[$source])) {
267
-            [$to, $factor] = $factors[$source];
268
-            if ($to === $target) {
269
-                return $factor;
270
-            }
271
-        }
272
-
273
-        return null;
274
-    }
275
-
276
-    /**
277
-     * Returns current config for days per week.
278
-     *
279
-     * @return int
280
-     */
281
-    public static function getDaysPerWeek()
282
-    {
283
-        return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
284
-    }
285
-
286
-    /**
287
-     * Returns current config for hours per day.
288
-     *
289
-     * @return int
290
-     */
291
-    public static function getHoursPerDay()
292
-    {
293
-        return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
294
-    }
295
-
296
-    /**
297
-     * Returns current config for minutes per hour.
298
-     *
299
-     * @return int
300
-     */
301
-    public static function getMinutesPerHour()
302
-    {
303
-        return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
304
-    }
305
-
306
-    /**
307
-     * Returns current config for seconds per minute.
308
-     *
309
-     * @return int
310
-     */
311
-    public static function getSecondsPerMinute()
312
-    {
313
-        return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
314
-    }
315
-
316
-    /**
317
-     * Returns current config for microseconds per second.
318
-     *
319
-     * @return int
320
-     */
321
-    public static function getMillisecondsPerSecond()
322
-    {
323
-        return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
324
-    }
325
-
326
-    /**
327
-     * Returns current config for microseconds per second.
328
-     *
329
-     * @return int
330
-     */
331
-    public static function getMicrosecondsPerMillisecond()
332
-    {
333
-        return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
334
-    }
335
-
336
-    /**
337
-     * Create a new CarbonInterval instance from specific values.
338
-     * This is an alias for the constructor that allows better fluent
339
-     * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
340
-     * (new CarbonInterval(1))->fn().
341
-     *
342
-     * @param int $years
343
-     * @param int $months
344
-     * @param int $weeks
345
-     * @param int $days
346
-     * @param int $hours
347
-     * @param int $minutes
348
-     * @param int $seconds
349
-     * @param int $microseconds
350
-     *
351
-     * @return static
352
-     */
353
-    public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
354
-    {
355
-        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
356
-    }
357
-
358
-    /**
359
-     * Get a copy of the instance.
360
-     *
361
-     * @return static
362
-     */
363
-    public function copy()
364
-    {
365
-        $date = new static($this->spec());
366
-        $date->invert = $this->invert;
367
-        $date->f = $this->f;
368
-
369
-        return $date;
370
-    }
371
-
372
-    /**
373
-     * Get a copy of the instance.
374
-     *
375
-     * @return static
376
-     */
377
-    public function clone()
378
-    {
379
-        return $this->copy();
380
-    }
381
-
382
-    /**
383
-     * Provide static helpers to create instances.  Allows CarbonInterval::years(3).
384
-     *
385
-     * Note: This is done using the magic method to allow static and instance methods to
386
-     *       have the same names.
387
-     *
388
-     * @param string $method     magic method name called
389
-     * @param array  $parameters parameters list
390
-     *
391
-     * @return static|null
392
-     */
393
-    public static function __callStatic($method, $parameters)
394
-    {
395
-        $arg = count($parameters) === 0 ? 1 : $parameters[0];
396
-
397
-        switch (Carbon::singularUnit(rtrim($method, 'z'))) {
398
-            case 'year':
399
-                return new static($arg);
400
-
401
-            case 'month':
402
-                return new static(null, $arg);
403
-
404
-            case 'week':
405
-                return new static(null, null, $arg);
406
-
407
-            case 'day':
408
-                return new static(null, null, null, $arg);
409
-
410
-            case 'hour':
411
-                return new static(null, null, null, null, $arg);
412
-
413
-            case 'minute':
414
-                return new static(null, null, null, null, null, $arg);
415
-
416
-            case 'second':
417
-                return new static(null, null, null, null, null, null, $arg);
418
-
419
-            case 'millisecond':
420
-            case 'milli':
421
-                return new static(null, null, null, null, null, null, null, $arg * Carbon::MICROSECONDS_PER_MILLISECOND);
422
-
423
-            case 'microsecond':
424
-            case 'micro':
425
-                return new static(null, null, null, null, null, null, null, $arg);
426
-        }
427
-
428
-        if (static::hasMacro($method)) {
429
-            return (new static(0))->$method(...$parameters);
430
-        }
431
-
432
-        if (Carbon::isStrictModeEnabled()) {
433
-            throw new BadMethodCallException(sprintf("Unknown fluent constructor '%s'.", $method));
434
-        }
435
-
436
-        return null;
437
-    }
438
-
439
-    /**
440
-     * Creates a CarbonInterval from string.
441
-     *
442
-     * Format:
443
-     *
444
-     * Suffix | Unit    | Example | DateInterval expression
445
-     * -------|---------|---------|------------------------
446
-     * y      | years   |   1y    | P1Y
447
-     * mo     | months  |   3mo   | P3M
448
-     * w      | weeks   |   2w    | P2W
449
-     * d      | days    |  28d    | P28D
450
-     * h      | hours   |   4h    | PT4H
451
-     * m      | minutes |  12m    | PT12M
452
-     * s      | seconds |  59s    | PT59S
453
-     *
454
-     * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
455
-     *
456
-     * Special cases:
457
-     *  - An empty string will return a zero interval
458
-     *  - Fractions are allowed for weeks, days, hours and minutes and will be converted
459
-     *    and rounded to the next smaller value (caution: 0.5w = 4d)
460
-     *
461
-     * @param string $intervalDefinition
462
-     *
463
-     * @return static
464
-     */
465
-    public static function fromString($intervalDefinition)
466
-    {
467
-        if (empty($intervalDefinition)) {
468
-            return new static(0);
469
-        }
470
-
471
-        $years = 0;
472
-        $months = 0;
473
-        $weeks = 0;
474
-        $days = 0;
475
-        $hours = 0;
476
-        $minutes = 0;
477
-        $seconds = 0;
478
-        $milliseconds = 0;
479
-        $microseconds = 0;
480
-
481
-        $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
482
-        preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
483
-
484
-        while ([$part, $value, $unit] = array_shift($parts)) {
485
-            $intValue = intval($value);
486
-            $fraction = floatval($value) - $intValue;
487
-
488
-            // Fix calculation precision
489
-            switch (round($fraction, 6)) {
490
-                case 1:
491
-                    $fraction = 0;
492
-                    $intValue++;
493
-
494
-                    break;
495
-                case 0:
496
-                    $fraction = 0;
497
-
498
-                    break;
499
-            }
500
-
501
-            switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
502
-                case 'millennia':
503
-                case 'millennium':
504
-                    $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
505
-
506
-                    break;
507
-
508
-                case 'century':
509
-                case 'centuries':
510
-                    $years += $intValue * CarbonInterface::YEARS_PER_CENTURY;
511
-
512
-                    break;
513
-
514
-                case 'decade':
515
-                case 'decades':
516
-                    $years += $intValue * CarbonInterface::YEARS_PER_DECADE;
517
-
518
-                    break;
519
-
520
-                case 'year':
521
-                case 'years':
522
-                case 'y':
523
-                    $years += $intValue;
524
-
525
-                    break;
526
-
527
-                case 'quarter':
528
-                case 'quarters':
529
-                    $months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;
530
-
531
-                    break;
532
-
533
-                case 'month':
534
-                case 'months':
535
-                case 'mo':
536
-                    $months += $intValue;
537
-
538
-                    break;
539
-
540
-                case 'week':
541
-                case 'weeks':
542
-                case 'w':
543
-                    $weeks += $intValue;
544
-
545
-                    if ($fraction) {
546
-                        $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
547
-                    }
548
-
549
-                    break;
550
-
551
-                case 'day':
552
-                case 'days':
553
-                case 'd':
554
-                    $days += $intValue;
555
-
556
-                    if ($fraction) {
557
-                        $parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
558
-                    }
559
-
560
-                    break;
561
-
562
-                case 'hour':
563
-                case 'hours':
564
-                case 'h':
565
-                    $hours += $intValue;
566
-
567
-                    if ($fraction) {
568
-                        $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
569
-                    }
570
-
571
-                    break;
572
-
573
-                case 'minute':
574
-                case 'minutes':
575
-                case 'm':
576
-                    $minutes += $intValue;
577
-
578
-                    if ($fraction) {
579
-                        $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
580
-                    }
581
-
582
-                    break;
583
-
584
-                case 'second':
585
-                case 'seconds':
586
-                case 's':
587
-                    $seconds += $intValue;
588
-
589
-                    if ($fraction) {
590
-                        $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
591
-                    }
592
-
593
-                    break;
594
-
595
-                case 'millisecond':
596
-                case 'milliseconds':
597
-                case 'milli':
598
-                case 'ms':
599
-                    $milliseconds += $intValue;
600
-
601
-                    if ($fraction) {
602
-                        $microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
603
-                    }
604
-
605
-                    break;
606
-
607
-                case 'microsecond':
608
-                case 'microseconds':
609
-                case 'micro':
610
-                case 'µs':
611
-                    $microseconds += $intValue;
612
-
613
-                    break;
614
-
615
-                default:
616
-                    throw new InvalidArgumentException(
617
-                        sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
618
-                    );
619
-            }
620
-        }
621
-
622
-        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
623
-    }
624
-
625
-    /**
626
-     * Creates a CarbonInterval from string using a different locale.
627
-     *
628
-     * @param string $interval
629
-     * @param string $locale
630
-     *
631
-     * @return static
632
-     */
633
-    public static function parseFromLocale($interval, $locale)
634
-    {
635
-        return static::fromString(Carbon::translateTimeString($interval, $locale, 'en'));
636
-    }
637
-
638
-    /**
639
-     * Create a CarbonInterval instance from a DateInterval one.  Can not instance
640
-     * DateInterval objects created from DateTime::diff() as you can't externally
641
-     * set the $days field.
642
-     *
643
-     * @param DateInterval $interval
644
-     *
645
-     * @return static
646
-     */
647
-    public static function instance(DateInterval $interval)
648
-    {
649
-        $microseconds = $interval->f;
650
-        $instance = new static(static::getDateIntervalSpec($interval));
651
-        if ($microseconds) {
652
-            $instance->f = $microseconds;
653
-        }
654
-        $instance->invert = $interval->invert;
655
-        foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
656
-            if ($interval->$unit < 0) {
657
-                $instance->$unit *= -1;
658
-            }
659
-        }
660
-
661
-        return $instance;
662
-    }
663
-
664
-    /**
665
-     * Make a CarbonInterval instance from given variable if possible.
666
-     *
667
-     * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
668
-     * and recurrences). Throw an exception for invalid format, but otherwise return null.
669
-     *
670
-     * @param mixed $var
671
-     *
672
-     * @return static|null
673
-     */
674
-    public static function make($var)
675
-    {
676
-        if ($var instanceof DateInterval) {
677
-            return static::instance($var);
678
-        }
679
-
680
-        if (!is_string($var)) {
681
-            return null;
682
-        }
683
-
684
-        $var = trim($var);
685
-
686
-        if (preg_match('/^P[T0-9]/', $var)) {
687
-            return new static($var);
688
-        }
689
-
690
-        if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $var)) {
691
-            return static::fromString($var);
692
-        }
693
-
694
-        /** @var static $interval */
695
-        $interval = static::createFromDateString($var);
696
-
697
-        return !$interval || $interval->isEmpty() ? null : $interval;
698
-    }
699
-
700
-    protected function resolveInterval($interval)
701
-    {
702
-        if (!($interval instanceof self)) {
703
-            return self::make($interval);
704
-        }
705
-
706
-        return $interval;
707
-    }
708
-
709
-    /**
710
-     * Sets up a DateInterval from the relative parts of the string.
711
-     *
712
-     * @param string $time
713
-     *
714
-     * @return static
715
-     *
716
-     * @link http://php.net/manual/en/dateinterval.createfromdatestring.php
717
-     */
718
-    public static function createFromDateString($time)
719
-    {
720
-        $interval = @parent::createFromDateString(strtr($time, [
721
-            ',' => ' ',
722
-            ' and ' => ' ',
723
-        ]));
724
-
725
-        if ($interval instanceof DateInterval) {
726
-            $interval = static::instance($interval);
727
-        }
728
-
729
-        return $interval;
730
-    }
731
-
732
-    ///////////////////////////////////////////////////////////////////
733
-    ///////////////////////// GETTERS AND SETTERS /////////////////////
734
-    ///////////////////////////////////////////////////////////////////
735
-
736
-    /**
737
-     * Get a part of the CarbonInterval object.
738
-     *
739
-     * @param string $name
740
-     *
741
-     * @throws \InvalidArgumentException
742
-     *
743
-     * @return int|float|string
744
-     */
745
-    public function __get($name)
746
-    {
747
-        if (substr($name, 0, 5) === 'total') {
748
-            return $this->total(substr($name, 5));
749
-        }
750
-
751
-        switch ($name) {
752
-            case 'years':
753
-                return $this->y;
754
-
755
-            case 'months':
756
-                return $this->m;
757
-
758
-            case 'dayz':
759
-                return $this->d;
760
-
761
-            case 'hours':
762
-                return $this->h;
763
-
764
-            case 'minutes':
765
-                return $this->i;
766
-
767
-            case 'seconds':
768
-                return $this->s;
769
-
770
-            case 'milli':
771
-            case 'milliseconds':
772
-                return (int) floor(round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
773
-
774
-            case 'micro':
775
-            case 'microseconds':
776
-                return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
777
-
778
-            case 'weeks':
779
-                return (int) floor($this->d / static::getDaysPerWeek());
780
-
781
-            case 'daysExcludeWeeks':
782
-            case 'dayzExcludeWeeks':
783
-                return $this->d % static::getDaysPerWeek();
784
-
785
-            case 'locale':
786
-                return $this->getLocalTranslator()->getLocale();
787
-
788
-            default:
789
-                throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
790
-        }
791
-    }
792
-
793
-    /**
794
-     * Set a part of the CarbonInterval object.
795
-     *
796
-     * @param string $name
797
-     * @param int    $value
798
-     *
799
-     * @throws \InvalidArgumentException
800
-     */
801
-    public function __set($name, $value)
802
-    {
803
-        switch (Carbon::singularUnit(rtrim($name, 'z'))) {
804
-            case 'year':
805
-                $this->y = $value;
806
-
807
-                break;
808
-
809
-            case 'month':
810
-                $this->m = $value;
811
-
812
-                break;
813
-
814
-            case 'week':
815
-                $this->d = $value * static::getDaysPerWeek();
816
-
817
-                break;
818
-
819
-            case 'day':
820
-                $this->d = $value;
821
-
822
-                break;
823
-
824
-            case 'hour':
825
-                $this->h = $value;
826
-
827
-                break;
828
-
829
-            case 'minute':
830
-                $this->i = $value;
831
-
832
-                break;
833
-
834
-            case 'second':
835
-                $this->s = $value;
836
-
837
-                break;
838
-
839
-            case 'milli':
840
-            case 'millisecond':
841
-                $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
842
-
843
-                break;
844
-
845
-            case 'micro':
846
-            case 'microsecond':
847
-                $this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
848
-
849
-                break;
850
-
851
-            default:
852
-                if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
853
-                    throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
854
-                }
855
-
856
-                $this->$name = $value;
857
-        }
858
-    }
859
-
860
-    /**
861
-     * Allow setting of weeks and days to be cumulative.
862
-     *
863
-     * @param int $weeks Number of weeks to set
864
-     * @param int $days  Number of days to set
865
-     *
866
-     * @return static
867
-     */
868
-    public function weeksAndDays($weeks, $days)
869
-    {
870
-        $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
871
-
872
-        return $this;
873
-    }
874
-
875
-    /**
876
-     * Returns true if the interval is empty for each unit.
877
-     *
878
-     * @return bool
879
-     */
880
-    public function isEmpty()
881
-    {
882
-        return $this->years === 0 &&
883
-            $this->months === 0 &&
884
-            $this->dayz === 0 &&
885
-            !$this->days &&
886
-            $this->hours === 0 &&
887
-            $this->minutes === 0 &&
888
-            $this->seconds === 0 &&
889
-            $this->microseconds === 0;
890
-    }
891
-
892
-    /**
893
-     * Register a custom macro.
894
-     *
895
-     * @example
896
-     * ```
897
-     * CarbonInterval::macro('twice', function () {
898
-     *   return $this->times(2);
899
-     * });
900
-     * echo CarbonInterval::hours(2)->twice();
901
-     * ```
902
-     *
903
-     * @param string          $name
904
-     * @param object|callable $macro
905
-     *
906
-     * @return void
907
-     */
908
-    public static function macro($name, $macro)
909
-    {
910
-        static::$macros[$name] = $macro;
911
-    }
912
-
913
-    /**
914
-     * Register macros from a mixin object.
915
-     *
916
-     * @example
917
-     * ```
918
-     * CarbonInterval::mixin(new class {
919
-     *   public function daysToHours() {
920
-     *     return function () {
921
-     *       $this->hours += $this->days;
922
-     *       $this->days = 0;
923
-     *
924
-     *       return $this;
925
-     *     };
926
-     *   }
927
-     *   public function hoursToDays() {
928
-     *     return function () {
929
-     *       $this->days += $this->hours;
930
-     *       $this->hours = 0;
931
-     *
932
-     *       return $this;
933
-     *     };
934
-     *   }
935
-     * });
936
-     * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
937
-     * echo CarbonInterval::days(5)->daysToHours() . "\n";
938
-     * ```
939
-     *
940
-     * @param object $mixin
941
-     *
942
-     * @throws \ReflectionException
943
-     *
944
-     * @return void
945
-     */
946
-    public static function mixin($mixin)
947
-    {
948
-        $reflection = new ReflectionClass($mixin);
949
-
950
-        $methods = $reflection->getMethods(
951
-            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
952
-        );
953
-
954
-        foreach ($methods as $method) {
955
-            $method->setAccessible(true);
956
-
957
-            static::macro($method->name, $method->invoke($mixin));
958
-        }
959
-    }
960
-
961
-    /**
962
-     * Check if macro is registered.
963
-     *
964
-     * @param string $name
965
-     *
966
-     * @return bool
967
-     */
968
-    public static function hasMacro($name)
969
-    {
970
-        return isset(static::$macros[$name]);
971
-    }
972
-
973
-    /**
974
-     * Call given macro.
975
-     *
976
-     * @param string $name
977
-     * @param array  $parameters
978
-     *
979
-     * @return mixed
980
-     */
981
-    protected function callMacro($name, $parameters)
982
-    {
983
-        $macro = static::$macros[$name];
984
-
985
-        if ($macro instanceof Closure) {
986
-            return call_user_func_array($macro->bindTo($this, static::class), $parameters);
987
-        }
988
-
989
-        return call_user_func_array($macro, $parameters);
990
-    }
991
-
992
-    /**
993
-     * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
994
-     *
995
-     * Note: This is done using the magic method to allow static and instance methods to
996
-     *       have the same names.
997
-     *
998
-     * @param string $method     magic method name called
999
-     * @param array  $parameters parameters list
1000
-     *
1001
-     * @return static
1002
-     */
1003
-    public function __call($method, $parameters)
1004
-    {
1005
-        if (static::hasMacro($method)) {
1006
-            return $this->callMacro($method, $parameters);
1007
-        }
1008
-
1009
-        $arg = count($parameters) === 0 ? 1 : $parameters[0];
1010
-
1011
-        switch (Carbon::singularUnit(rtrim($method, 'z'))) {
1012
-            case 'year':
1013
-                $this->years = $arg;
1014
-
1015
-                break;
1016
-
1017
-            case 'month':
1018
-                $this->months = $arg;
1019
-
1020
-                break;
1021
-
1022
-            case 'week':
1023
-                $this->dayz = $arg * static::getDaysPerWeek();
1024
-
1025
-                break;
1026
-
1027
-            case 'day':
1028
-                $this->dayz = $arg;
1029
-
1030
-                break;
1031
-
1032
-            case 'hour':
1033
-                $this->hours = $arg;
1034
-
1035
-                break;
1036
-
1037
-            case 'minute':
1038
-                $this->minutes = $arg;
1039
-
1040
-                break;
1041
-
1042
-            case 'second':
1043
-                $this->seconds = $arg;
1044
-
1045
-                break;
1046
-
1047
-            case 'milli':
1048
-            case 'millisecond':
1049
-                $this->milliseconds = $arg;
1050
-
1051
-                break;
1052
-
1053
-            case 'micro':
1054
-            case 'microsecond':
1055
-                $this->microseconds = $arg;
1056
-
1057
-                break;
1058
-
1059
-            default:
1060
-                if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
1061
-                    throw new BadMethodCallException(sprintf("Unknown fluent setter '%s'", $method));
1062
-                }
1063
-        }
1064
-
1065
-        return $this;
1066
-    }
1067
-
1068
-    /**
1069
-     * @SuppressWarnings(PHPMD.ElseExpression)
1070
-     *
1071
-     * @param mixed $syntax
1072
-     * @param mixed $short
1073
-     * @param mixed $parts
1074
-     * @param mixed $options
1075
-     *
1076
-     * @return array
1077
-     */
1078
-    protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
1079
-    {
1080
-        $join = ' ';
1081
-        $aUnit = false;
1082
-        if (is_array($syntax)) {
1083
-            extract($syntax);
1084
-        } else {
1085
-            if (is_int($short)) {
1086
-                $parts = $short;
1087
-                $short = false;
1088
-            }
1089
-            if (is_bool($syntax)) {
1090
-                $short = $syntax;
1091
-                $syntax = CarbonInterface::DIFF_ABSOLUTE;
1092
-            }
1093
-        }
1094
-        if (is_null($syntax)) {
1095
-            $syntax = CarbonInterface::DIFF_ABSOLUTE;
1096
-        }
1097
-        if ($parts === -1) {
1098
-            $parts = INF;
1099
-        }
1100
-        if (is_null($options)) {
1101
-            $options = static::getHumanDiffOptions();
1102
-        }
1103
-        if ($join === true) {
1104
-            $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
1105
-            $join = [
1106
-                $default,
1107
-                $this->getTranslationMessage('list.1') ?? $default,
1108
-            ];
1109
-        }
1110
-        if (is_array($join)) {
1111
-            [$default, $last] = $join;
1112
-
1113
-            $join = function ($list) use ($default, $last) {
1114
-                if (count($list) < 2) {
1115
-                    return implode('', $list);
1116
-                }
1117
-
1118
-                $end = array_pop($list);
1119
-
1120
-                return implode($default, $list).$last.$end;
1121
-            };
1122
-        }
1123
-        if (is_string($join)) {
1124
-            $glue = $join;
1125
-            $join = function ($list) use ($glue) {
1126
-                return implode($glue, $list);
1127
-            };
1128
-        }
1129
-
1130
-        return [$syntax, $short, $parts, $options, $join, $aUnit];
1131
-    }
1132
-
1133
-    /**
1134
-     * Get the current interval in a human readable format in the current locale.
1135
-     *
1136
-     * @example
1137
-     * ```
1138
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
1139
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
1140
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
1141
-     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
1142
-     * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
1143
-     * ```
1144
-     *
1145
-     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
1146
-     *                           - 'syntax' entry (see below)
1147
-     *                           - 'short' entry (see below)
1148
-     *                           - 'parts' entry (see below)
1149
-     *                           - 'options' entry (see below)
1150
-     *                           - 'aUnit' entry, prefer "an hour" over "1 hour" if true
1151
-     *                           - 'join' entry determines how to join multiple parts of the string
1152
-     *                           `  - if $join is a string, it's used as a joiner glue
1153
-     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
1154
-     *                           `  - if $join is an array, the first item will be the default glue, and the second item
1155
-     *                           `    will be used instead of the glue for the last item
1156
-     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
1157
-     *                           `  - if $join is missing, a space will be used as glue
1158
-     *                           if int passed, it add modifiers:
1159
-     *                           Possible values:
1160
-     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
1161
-     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
1162
-     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
1163
-     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
1164
-     * @param bool      $short   displays short format of time units
1165
-     * @param int       $parts   maximum number of parts to display (default value: -1: no limits)
1166
-     * @param int       $options human diff options
1167
-     *
1168
-     * @return string
1169
-     */
1170
-    public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
1171
-    {
1172
-        [$syntax, $short, $parts, $options, $join, $aUnit] = $this->getForHumansParameters($syntax, $short, $parts, $options);
1173
-
1174
-        $interval = [];
1175
-        $syntax = (int) ($syntax === null ? CarbonInterface::DIFF_ABSOLUTE : $syntax);
1176
-        $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
1177
-        $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
1178
-        $count = 1;
1179
-        $unit = $short ? 's' : 'second';
1180
-
1181
-        /** @var \Symfony\Component\Translation\Translator $translator */
1182
-        $translator = $this->getLocalTranslator();
1183
-
1184
-        $diffIntervalArray = [
1185
-            ['value' => $this->years,            'unit' => 'year',   'unitShort' => 'y'],
1186
-            ['value' => $this->months,           'unit' => 'month',  'unitShort' => 'm'],
1187
-            ['value' => $this->weeks,            'unit' => 'week',   'unitShort' => 'w'],
1188
-            ['value' => $this->daysExcludeWeeks, 'unit' => 'day',    'unitShort' => 'd'],
1189
-            ['value' => $this->hours,            'unit' => 'hour',   'unitShort' => 'h'],
1190
-            ['value' => $this->minutes,          'unit' => 'minute', 'unitShort' => 'min'],
1191
-            ['value' => $this->seconds,          'unit' => 'second', 'unitShort' => 's'],
1192
-        ];
1193
-
1194
-        $transChoice = function ($short, $unitData) use ($translator, $aUnit) {
1195
-            $count = $unitData['value'];
1196
-
1197
-            if ($short) {
1198
-                $result = $this->translate($unitData['unitShort'], [], $count, $translator);
1199
-
1200
-                if ($result !== $unitData['unitShort']) {
1201
-                    return $result;
1202
-                }
1203
-            } elseif ($aUnit) {
1204
-                $key = 'a_'.$unitData['unit'];
1205
-                $result = $this->translate($key, [], $count, $translator);
1206
-
1207
-                if ($result !== $key) {
1208
-                    return $result;
1209
-                }
1210
-            }
1211
-
1212
-            return $this->translate($unitData['unit'], [], $count, $translator);
1213
-        };
1214
-
1215
-        foreach ($diffIntervalArray as $diffIntervalData) {
1216
-            if ($diffIntervalData['value'] > 0) {
1217
-                $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
1218
-                $count = $diffIntervalData['value'];
1219
-                $interval[] = $transChoice($short, $diffIntervalData);
1220
-            } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && count($interval) > 0) {
1221
-                break;
1222
-            }
1223
-
1224
-            // break the loop after we get the required number of parts in array
1225
-            if (count($interval) >= $parts) {
1226
-                break;
1227
-            }
1228
-        }
1229
-
1230
-        if (count($interval) === 0) {
1231
-            if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
1232
-                $key = 'diff_now';
1233
-                $translation = $this->translate($key, [], null, $translator);
1234
-                if ($translation !== $key) {
1235
-                    return $translation;
1236
-                }
1237
-            }
1238
-            $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
1239
-            $unit = $short ? 's' : 'second';
1240
-            $interval[] = $this->translate($unit, [], $count, $translator);
1241
-        }
1242
-
1243
-        // join the interval parts by a space
1244
-        $time = $join($interval);
1245
-
1246
-        unset($diffIntervalArray, $interval);
1247
-
1248
-        if ($absolute) {
1249
-            return $time;
1250
-        }
1251
-
1252
-        $isFuture = $this->invert === 1;
1253
-
1254
-        $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
1255
-
1256
-        if ($parts === 1) {
1257
-            if ($relativeToNow && $unit === 'day') {
1258
-                if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
1259
-                    $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
1260
-                    $translation = $this->translate($key, [], null, $translator);
1261
-                    if ($translation !== $key) {
1262
-                        return $translation;
1263
-                    }
1264
-                }
1265
-                if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
1266
-                    $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
1267
-                    $translation = $this->translate($key, [], null, $translator);
1268
-                    if ($translation !== $key) {
1269
-                        return $translation;
1270
-                    }
1271
-                }
1272
-            }
1273
-            // Some languages have special pluralization for past and future tense.
1274
-            $key = $unit.'_'.$transId;
1275
-            if ($key !== $this->translate($key, [], null, $translator)) {
1276
-                $time = $this->translate($key, [], $count, $translator);
1277
-            }
1278
-        }
1279
-
1280
-        return $this->translate($transId, [':time' => $time], null, $translator);
1281
-    }
1282
-
1283
-    /**
1284
-     * Format the instance as a string using the forHumans() function.
1285
-     *
1286
-     * @return string
1287
-     */
1288
-    public function __toString()
1289
-    {
1290
-        return $this->forHumans();
1291
-    }
1292
-
1293
-    /**
1294
-     * Convert the interval to a CarbonPeriod.
1295
-     *
1296
-     * @return CarbonPeriod
1297
-     */
1298
-    public function toPeriod(...$params)
1299
-    {
1300
-        return CarbonPeriod::create($this, ...$params);
1301
-    }
1302
-
1303
-    /**
1304
-     * Invert the interval.
1305
-     *
1306
-     * @return $this
1307
-     */
1308
-    public function invert()
1309
-    {
1310
-        $this->invert = $this->invert ? 0 : 1;
1311
-
1312
-        return $this;
1313
-    }
1314
-
1315
-    protected function solveNegativeInterval()
1316
-    {
1317
-        if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
1318
-            $this->years *= -1;
1319
-            $this->months *= -1;
1320
-            $this->dayz *= -1;
1321
-            $this->hours *= -1;
1322
-            $this->minutes *= -1;
1323
-            $this->seconds *= -1;
1324
-            $this->microseconds *= -1;
1325
-            $this->invert();
1326
-        }
1327
-
1328
-        return $this;
1329
-    }
1330
-
1331
-    /**
1332
-     * Add the passed interval to the current instance.
1333
-     *
1334
-     * @param string|DateInterval $unit
1335
-     * @param int                 $value
1336
-     *
1337
-     * @return static
1338
-     */
1339
-    public function add($unit, $value = 1)
1340
-    {
1341
-        if (is_numeric($unit)) {
1342
-            [$value, $unit] = [$unit, $value];
1343
-        }
1344
-
1345
-        if (is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
1346
-            $unit = "$value $unit";
1347
-            $value = 1;
1348
-        }
1349
-
1350
-        $interval = static::make($unit);
1351
-
1352
-        if (!$interval) {
1353
-            throw new InvalidArgumentException('This type of data cannot be added/subtracted.');
1354
-        }
1355
-
1356
-        if ($value !== 1) {
1357
-            $interval->times($value);
1358
-        }
1359
-        $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
1360
-        $this->years += $interval->y * $sign;
1361
-        $this->months += $interval->m * $sign;
1362
-        $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
1363
-        $this->hours += $interval->h * $sign;
1364
-        $this->minutes += $interval->i * $sign;
1365
-        $this->seconds += $interval->s * $sign;
1366
-        $this->microseconds += $interval->microseconds * $sign;
1367
-
1368
-        $this->solveNegativeInterval();
1369
-
1370
-        return $this;
1371
-    }
1372
-
1373
-    /**
1374
-     * Subtract the passed interval to the current instance.
1375
-     *
1376
-     * @param string|DateInterval $unit
1377
-     * @param int                 $value
1378
-     *
1379
-     * @return static
1380
-     */
1381
-    public function sub($unit, $value = 1)
1382
-    {
1383
-        if (is_numeric($unit)) {
1384
-            [$value, $unit] = [$unit, $value];
1385
-        }
1386
-
1387
-        return $this->add($unit, -floatval($value));
1388
-    }
1389
-
1390
-    /**
1391
-     * Subtract the passed interval to the current instance.
1392
-     *
1393
-     * @param string|DateInterval $unit
1394
-     * @param int                 $value
1395
-     *
1396
-     * @return static
1397
-     */
1398
-    public function subtract($unit, $value = 1)
1399
-    {
1400
-        return $this->sub($unit, $value);
1401
-    }
1402
-
1403
-    /**
1404
-     * Multiply current instance given number of times. times() is naive, it multiplies each unit
1405
-     * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
1406
-     * separately for each unit.
1407
-     *
1408
-     * Use times() when you want a fast and approximated calculation that does not cascade units.
1409
-     *
1410
-     * For a precise and cascaded calculation,
1411
-     *
1412
-     * @see multiply()
1413
-     *
1414
-     * @param float|int $factor
1415
-     *
1416
-     * @return $this
1417
-     */
1418
-    public function times($factor)
1419
-    {
1420
-        if ($factor < 0) {
1421
-            $this->invert = $this->invert ? 0 : 1;
1422
-            $factor = -$factor;
1423
-        }
1424
-
1425
-        $this->years = (int) round($this->years * $factor);
1426
-        $this->months = (int) round($this->months * $factor);
1427
-        $this->dayz = (int) round($this->dayz * $factor);
1428
-        $this->hours = (int) round($this->hours * $factor);
1429
-        $this->minutes = (int) round($this->minutes * $factor);
1430
-        $this->seconds = (int) round($this->seconds * $factor);
1431
-        $this->microseconds = (int) round($this->microseconds * $factor);
1432
-
1433
-        return $this;
1434
-    }
1435
-
1436
-    /**
1437
-     * Divide current instance by a given divider. shares() is naive, it divides each unit separately
1438
-     * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
1439
-     * and 7 minutes.
1440
-     *
1441
-     * Use shares() when you want a fast and approximated calculation that does not cascade units.
1442
-     *
1443
-     * For a precise and cascaded calculation,
1444
-     *
1445
-     * @see divide()
1446
-     *
1447
-     * @param float|int $divider
1448
-     *
1449
-     * @return $this
1450
-     */
1451
-    public function shares($divider)
1452
-    {
1453
-        return $this->times(1 / $divider);
1454
-    }
1455
-
1456
-    /**
1457
-     * Multiply and cascade current instance by a given factor.
1458
-     *
1459
-     * @param float|int $factor
1460
-     *
1461
-     * @return $this
1462
-     */
1463
-    public function multiply($factor)
1464
-    {
1465
-        if ($factor < 0) {
1466
-            $this->invert = $this->invert ? 0 : 1;
1467
-            $factor = -$factor;
1468
-        }
1469
-
1470
-        $yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision
1471
-
1472
-        if ($yearPart) {
1473
-            $this->years -= $yearPart / $factor;
1474
-        }
1475
-
1476
-        $newInterval = static::__callStatic('years', [$yearPart])->microseconds($this->totalMicroseconds * $factor)->cascade();
1477
-
1478
-        $this->years = $newInterval->years;
1479
-        $this->months = $newInterval->months;
1480
-        $this->dayz = $newInterval->dayz;
1481
-        $this->hours = $newInterval->hours;
1482
-        $this->minutes = $newInterval->minutes;
1483
-        $this->seconds = $newInterval->seconds;
1484
-        $this->microseconds = $newInterval->microseconds;
1485
-
1486
-        return $this;
1487
-    }
1488
-
1489
-    /**
1490
-     * Divide and cascade current instance by a given divider.
1491
-     *
1492
-     * @param float|int $divider
1493
-     *
1494
-     * @return $this
1495
-     */
1496
-    public function divide($divider)
1497
-    {
1498
-        return $this->multiply(1 / $divider);
1499
-    }
1500
-
1501
-    /**
1502
-     * Get the interval_spec string of a date interval.
1503
-     *
1504
-     * @param DateInterval $interval
1505
-     *
1506
-     * @return string
1507
-     */
1508
-    public static function getDateIntervalSpec(DateInterval $interval)
1509
-    {
1510
-        $date = array_filter([
1511
-            static::PERIOD_YEARS => abs($interval->y),
1512
-            static::PERIOD_MONTHS => abs($interval->m),
1513
-            static::PERIOD_DAYS => abs($interval->d),
1514
-        ]);
1515
-
1516
-        $time = array_filter([
1517
-            static::PERIOD_HOURS => abs($interval->h),
1518
-            static::PERIOD_MINUTES => abs($interval->i),
1519
-            static::PERIOD_SECONDS => abs($interval->s),
1520
-        ]);
1521
-
1522
-        $specString = static::PERIOD_PREFIX;
1523
-
1524
-        foreach ($date as $key => $value) {
1525
-            $specString .= $value.$key;
1526
-        }
1527
-
1528
-        if (count($time) > 0) {
1529
-            $specString .= static::PERIOD_TIME_PREFIX;
1530
-            foreach ($time as $key => $value) {
1531
-                $specString .= $value.$key;
1532
-            }
1533
-        }
1534
-
1535
-        return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
1536
-    }
1537
-
1538
-    /**
1539
-     * Get the interval_spec string.
1540
-     *
1541
-     * @return string
1542
-     */
1543
-    public function spec()
1544
-    {
1545
-        return static::getDateIntervalSpec($this);
1546
-    }
1547
-
1548
-    /**
1549
-     * Comparing 2 date intervals.
1550
-     *
1551
-     * @param DateInterval $first
1552
-     * @param DateInterval $second
1553
-     *
1554
-     * @return int
1555
-     */
1556
-    public static function compareDateIntervals(DateInterval $first, DateInterval $second)
1557
-    {
1558
-        $current = Carbon::now();
1559
-        $passed = $current->copy()->add($second);
1560
-        $current->add($first);
1561
-
1562
-        if ($current < $passed) {
1563
-            return -1;
1564
-        }
1565
-        if ($current > $passed) {
1566
-            return 1;
1567
-        }
1568
-
1569
-        return 0;
1570
-    }
1571
-
1572
-    /**
1573
-     * Comparing with passed interval.
1574
-     *
1575
-     * @param DateInterval $interval
1576
-     *
1577
-     * @return int
1578
-     */
1579
-    public function compare(DateInterval $interval)
1580
-    {
1581
-        return static::compareDateIntervals($this, $interval);
1582
-    }
1583
-
1584
-    /**
1585
-     * Convert overflowed values into bigger units.
1586
-     *
1587
-     * @return $this
1588
-     */
1589
-    public function cascade()
1590
-    {
1591
-        foreach (static::getFlipCascadeFactors() as $source => [$target, $factor]) {
1592
-            if ($source === 'dayz' && $target === 'weeks') {
1593
-                continue;
1594
-            }
1595
-
1596
-            $value = $this->$source;
1597
-            $this->$source = $modulo = ($factor + ($value % $factor)) % $factor;
1598
-            $this->$target += ($value - $modulo) / $factor;
1599
-            if ($this->$source > 0 && $this->$target < 0) {
1600
-                $this->$source -= $factor;
1601
-                $this->$target++;
1602
-            }
1603
-        }
1604
-
1605
-        return $this->solveNegativeInterval();
1606
-    }
1607
-
1608
-    /**
1609
-     * Get amount of given unit equivalent to the interval.
1610
-     *
1611
-     * @param string $unit
1612
-     *
1613
-     * @throws \InvalidArgumentException
1614
-     *
1615
-     * @return float
1616
-     */
1617
-    public function total($unit)
1618
-    {
1619
-        $realUnit = $unit = strtolower($unit);
1620
-
1621
-        if (in_array($unit, ['days', 'weeks'])) {
1622
-            $realUnit = 'dayz';
1623
-        } elseif (!in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
1624
-            throw new InvalidArgumentException("Unknown unit '$unit'.");
1625
-        }
1626
-
1627
-        $result = 0;
1628
-        $cumulativeFactor = 0;
1629
-        $unitFound = false;
1630
-        $factors = static::getFlipCascadeFactors();
1631
-
1632
-        foreach ($factors as $source => [$target, $factor]) {
1633
-            if ($source === $realUnit) {
1634
-                $unitFound = true;
1635
-                $value = $this->$source;
1636
-                if ($source === 'microseconds' && isset($factors['milliseconds'])) {
1637
-                    $value %= Carbon::MICROSECONDS_PER_MILLISECOND;
1638
-                }
1639
-                $result += $value;
1640
-                $cumulativeFactor = 1;
1641
-            }
1642
-
1643
-            if ($factor === false) {
1644
-                if ($unitFound) {
1645
-                    break;
1646
-                }
1647
-
1648
-                $result = 0;
1649
-                $cumulativeFactor = 0;
1650
-
1651
-                continue;
1652
-            }
1653
-
1654
-            if ($target === $realUnit) {
1655
-                $unitFound = true;
1656
-            }
1657
-
1658
-            if ($cumulativeFactor) {
1659
-                $cumulativeFactor *= $factor;
1660
-                $result += $this->$target * $cumulativeFactor;
1661
-
1662
-                continue;
1663
-            }
1664
-
1665
-            $value = $this->$source;
1666
-
1667
-            if ($source === 'microseconds' && isset($factors['milliseconds'])) {
1668
-                $value %= Carbon::MICROSECONDS_PER_MILLISECOND;
1669
-            }
1670
-
1671
-            $result = ($result + $value) / $factor;
1672
-        }
1673
-
1674
-        if (isset($target) && !$cumulativeFactor) {
1675
-            $result += $this->$target;
1676
-        }
1677
-
1678
-        if (!$unitFound) {
1679
-            throw new \InvalidArgumentException("Unit $unit have no configuration to get total from other units.");
1680
-        }
1681
-
1682
-        if ($unit === 'weeks') {
1683
-            return $result / static::getDaysPerWeek();
1684
-        }
1685
-
1686
-        return $result;
1687
-    }
1688
-
1689
-    /**
1690
-     * Determines if the instance is equal to another
1691
-     *
1692
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1693
-     *
1694
-     * @see equalTo()
1695
-     *
1696
-     * @return bool
1697
-     */
1698
-    public function eq($interval): bool
1699
-    {
1700
-        return $this->equalTo($interval);
1701
-    }
1702
-
1703
-    /**
1704
-     * Determines if the instance is equal to another
1705
-     *
1706
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1707
-     *
1708
-     * @return bool
1709
-     */
1710
-    public function equalTo($interval): bool
1711
-    {
1712
-        $interval = $this->resolveInterval($interval);
1713
-
1714
-        return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds;
1715
-    }
1716
-
1717
-    /**
1718
-     * Determines if the instance is not equal to another
1719
-     *
1720
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1721
-     *
1722
-     * @see notEqualTo()
1723
-     *
1724
-     * @return bool
1725
-     */
1726
-    public function ne($interval): bool
1727
-    {
1728
-        return $this->notEqualTo($interval);
1729
-    }
1730
-
1731
-    /**
1732
-     * Determines if the instance is not equal to another
1733
-     *
1734
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1735
-     *
1736
-     * @return bool
1737
-     */
1738
-    public function notEqualTo($interval): bool
1739
-    {
1740
-        return !$this->eq($interval);
1741
-    }
1742
-
1743
-    /**
1744
-     * Determines if the instance is greater (longer) than another
1745
-     *
1746
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1747
-     *
1748
-     * @see greaterThan()
1749
-     *
1750
-     * @return bool
1751
-     */
1752
-    public function gt($interval): bool
1753
-    {
1754
-        return $this->greaterThan($interval);
1755
-    }
1756
-
1757
-    /**
1758
-     * Determines if the instance is greater (longer) than another
1759
-     *
1760
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1761
-     *
1762
-     * @return bool
1763
-     */
1764
-    public function greaterThan($interval): bool
1765
-    {
1766
-        $interval = $this->resolveInterval($interval);
1767
-
1768
-        return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
1769
-    }
1770
-
1771
-    /**
1772
-     * Determines if the instance is greater (longer) than or equal to another
1773
-     *
1774
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1775
-     *
1776
-     * @see greaterThanOrEqualTo()
1777
-     *
1778
-     * @return bool
1779
-     */
1780
-    public function gte($interval): bool
1781
-    {
1782
-        return $this->greaterThanOrEqualTo($interval);
1783
-    }
1784
-
1785
-    /**
1786
-     * Determines if the instance is greater (longer) than or equal to another
1787
-     *
1788
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1789
-     *
1790
-     * @return bool
1791
-     */
1792
-    public function greaterThanOrEqualTo($interval): bool
1793
-    {
1794
-        return $this->greaterThan($interval) || $this->equalTo($interval);
1795
-    }
1796
-
1797
-    /**
1798
-     * Determines if the instance is less (shorter) than another
1799
-     *
1800
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1801
-     *
1802
-     * @see lessThan()
1803
-     *
1804
-     * @return bool
1805
-     */
1806
-    public function lt($interval): bool
1807
-    {
1808
-        return $this->lessThan($interval);
1809
-    }
1810
-
1811
-    /**
1812
-     * Determines if the instance is less (shorter) than another
1813
-     *
1814
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1815
-     *
1816
-     * @return bool
1817
-     */
1818
-    public function lessThan($interval): bool
1819
-    {
1820
-        $interval = $this->resolveInterval($interval);
1821
-
1822
-        return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
1823
-    }
1824
-
1825
-    /**
1826
-     * Determines if the instance is less (shorter) than or equal to another
1827
-     *
1828
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1829
-     *
1830
-     * @see lessThanOrEqualTo()
1831
-     *
1832
-     * @return bool
1833
-     */
1834
-    public function lte($interval): bool
1835
-    {
1836
-        return $this->lessThanOrEqualTo($interval);
1837
-    }
1838
-
1839
-    /**
1840
-     * Determines if the instance is less (shorter) than or equal to another
1841
-     *
1842
-     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1843
-     *
1844
-     * @return bool
1845
-     */
1846
-    public function lessThanOrEqualTo($interval): bool
1847
-    {
1848
-        return $this->lessThan($interval) || $this->equalTo($interval);
1849
-    }
1850
-
1851
-    /**
1852
-     * Determines if the instance is between two others.
1853
-     *
1854
-     * @example
1855
-     * ```
1856
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
1857
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
1858
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
1859
-     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
1860
-     * ```
1861
-     *
1862
-     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval1
1863
-     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval2
1864
-     * @param bool                                       $equal     Indicates if an equal to comparison should be done
1865
-     *
1866
-     * @return bool
1867
-     */
1868
-    public function between($interval1, $interval2, $equal = true): bool
1869
-    {
1870
-        return $equal
1871
-            ? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
1872
-            : $this->greaterThan($interval1) && $this->lessThan($interval2);
1873
-    }
1874
-
1875
-    /**
1876
-     * Determines if the instance is between two others, bounds excluded.
1877
-     *
1878
-     * @example
1879
-     * ```
1880
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
1881
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
1882
-     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
1883
-     * ```
1884
-     *
1885
-     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval1
1886
-     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval2
1887
-     *
1888
-     * @return bool
1889
-     */
1890
-    public function betweenExcluded($interval1, $interval2): bool
1891
-    {
1892
-        return $this->between($interval1, $interval2, false);
1893
-    }
1894
-
1895
-    /**
1896
-     * Determines if the instance is between two others
1897
-     *
1898
-     * @example
1899
-     * ```
1900
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
1901
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
1902
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
1903
-     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
1904
-     * ```
1905
-     *
1906
-     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval1
1907
-     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval2
1908
-     * @param bool                                       $equal     Indicates if an equal to comparison should be done
1909
-     *
1910
-     * @return bool
1911
-     */
1912
-    public function isBetween($interval1, $interval2, $equal = true): bool
1913
-    {
1914
-        return $this->between($interval1, $interval2, $equal);
1915
-    }
1916
-}
Browse code

initial commit

Emmanuel ROY authored on 09/08/2019 08:39:02
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1916 @@
1
+<?php
2
+
3
+/**
4
+ * This file is part of the Carbon package.
5
+ *
6
+ * (c) Brian Nesbitt <brian@nesbot.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+namespace Carbon;
12
+
13
+use BadMethodCallException;
14
+use Carbon\Traits\Options;
15
+use Closure;
16
+use DateInterval;
17
+use InvalidArgumentException;
18
+use ReflectionClass;
19
+use ReflectionMethod;
20
+
21
+/**
22
+ * A simple API extension for DateInterval.
23
+ * The implementation provides helpers to handle weeks but only days are saved.
24
+ * Weeks are calculated based on the total days of the current instance.
25
+ *
26
+ * @property int $years Total years of the current interval.
27
+ * @property int $months Total months of the current interval.
28
+ * @property int $weeks Total weeks of the current interval calculated from the days.
29
+ * @property int $dayz Total days of the current interval (weeks * 7 + days).
30
+ * @property int $hours Total hours of the current interval.
31
+ * @property int $minutes Total minutes of the current interval.
32
+ * @property int $seconds Total seconds of the current interval.
33
+ * @property int $microseconds Total microseconds of the current interval.
34
+ * @property int $milliseconds Total microseconds of the current interval.
35
+ * @property-read int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
36
+ * @property-read int $daysExcludeWeeks alias of dayzExcludeWeeks
37
+ * @property-read float $totalYears Number of years equivalent to the interval.
38
+ * @property-read float $totalMonths Number of months equivalent to the interval.
39
+ * @property-read float $totalWeeks Number of weeks equivalent to the interval.
40
+ * @property-read float $totalDays Number of days equivalent to the interval.
41
+ * @property-read float $totalDayz Alias for totalDays.
42
+ * @property-read float $totalHours Number of hours equivalent to the interval.
43
+ * @property-read float $totalMinutes Number of minutes equivalent to the interval.
44
+ * @property-read float $totalSeconds Number of seconds equivalent to the interval.
45
+ * @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval.
46
+ * @property-read float $totalMicroseconds Number of microseconds equivalent to the interval.
47
+ * @property-read string $locale locale of the current instance
48
+ *
49
+ * @method static CarbonInterval years($years = 1) Create instance specifying a number of years.
50
+ * @method static CarbonInterval year($years = 1) Alias for years()
51
+ * @method static CarbonInterval months($months = 1) Create instance specifying a number of months.
52
+ * @method static CarbonInterval month($months = 1) Alias for months()
53
+ * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks.
54
+ * @method static CarbonInterval week($weeks = 1) Alias for weeks()
55
+ * @method static CarbonInterval days($days = 1) Create instance specifying a number of days.
56
+ * @method static CarbonInterval dayz($days = 1) Alias for days()
57
+ * @method static CarbonInterval day($days = 1) Alias for days()
58
+ * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours.
59
+ * @method static CarbonInterval hour($hours = 1) Alias for hours()
60
+ * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes.
61
+ * @method static CarbonInterval minute($minutes = 1) Alias for minutes()
62
+ * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds.
63
+ * @method static CarbonInterval second($seconds = 1) Alias for seconds()
64
+ * @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds.
65
+ * @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds()
66
+ * @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds.
67
+ * @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds()
68
+ * @method CarbonInterval years($years = 1) Set the years portion of the current interval.
69
+ * @method CarbonInterval year($years = 1) Alias for years().
70
+ * @method CarbonInterval months($months = 1) Set the months portion of the current interval.
71
+ * @method CarbonInterval month($months = 1) Alias for months().
72
+ * @method CarbonInterval weeks($weeks = 1) Set the weeks portion of the current interval.  Will overwrite dayz value.
73
+ * @method CarbonInterval week($weeks = 1) Alias for weeks().
74
+ * @method CarbonInterval days($days = 1) Set the days portion of the current interval.
75
+ * @method CarbonInterval dayz($days = 1) Alias for days().
76
+ * @method CarbonInterval day($days = 1) Alias for days().
77
+ * @method CarbonInterval hours($hours = 1) Set the hours portion of the current interval.
78
+ * @method CarbonInterval hour($hours = 1) Alias for hours().
79
+ * @method CarbonInterval minutes($minutes = 1) Set the minutes portion of the current interval.
80
+ * @method CarbonInterval minute($minutes = 1) Alias for minutes().
81
+ * @method CarbonInterval seconds($seconds = 1) Set the seconds portion of the current interval.
82
+ * @method CarbonInterval second($seconds = 1) Alias for seconds().
83
+ * @method CarbonInterval milliseconds($seconds = 1) Set the seconds portion of the current interval.
84
+ * @method CarbonInterval millisecond($seconds = 1) Alias for seconds().
85
+ * @method CarbonInterval microseconds($seconds = 1) Set the seconds portion of the current interval.
86
+ * @method CarbonInterval microsecond($seconds = 1) Alias for seconds().
87
+ */
88
+class CarbonInterval extends DateInterval
89
+{
90
+    use Options;
91
+
92
+    /**
93
+     * Interval spec period designators
94
+     */
95
+    const PERIOD_PREFIX = 'P';
96
+    const PERIOD_YEARS = 'Y';
97
+    const PERIOD_MONTHS = 'M';
98
+    const PERIOD_DAYS = 'D';
99
+    const PERIOD_TIME_PREFIX = 'T';
100
+    const PERIOD_HOURS = 'H';
101
+    const PERIOD_MINUTES = 'M';
102
+    const PERIOD_SECONDS = 'S';
103
+
104
+    /**
105
+     * A translator to ... er ... translate stuff
106
+     *
107
+     * @var \Symfony\Component\Translation\TranslatorInterface
108
+     */
109
+    protected static $translator;
110
+
111
+    /**
112
+     * @var array|null
113
+     */
114
+    protected static $cascadeFactors;
115
+
116
+    /**
117
+     * @var array|null
118
+     */
119
+    private static $flipCascadeFactors;
120
+
121
+    /**
122
+     * The registered macros.
123
+     *
124
+     * @var array
125
+     */
126
+    protected static $macros = [];
127
+
128
+    /**
129
+     * Timezone handler for settings() method.
130
+     *
131
+     * @var mixed
132
+     */
133
+    protected $tzName;
134
+
135
+    /**
136
+     * Set the instance's timezone from a string or object and add/subtract the offset difference.
137
+     *
138
+     * @param \DateTimeZone|string $tzName
139
+     *
140
+     * @return static
141
+     */
142
+    public function shiftTimezone($tzName)
143
+    {
144
+        $this->tzName = $tzName;
145
+
146
+        return $this;
147
+    }
148
+
149
+    /**
150
+     * Mapping of units and factors for cascading.
151
+     *
152
+     * Should only be modified by changing the factors or referenced constants.
153
+     *
154
+     * @return array
155
+     */
156
+    public static function getCascadeFactors()
157
+    {
158
+        return static::$cascadeFactors ?: [
159
+            'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
160
+            'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
161
+            'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
162
+            'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
163
+            'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
164
+            'months' => [Carbon::DAYS_PER_WEEK * Carbon::WEEKS_PER_MONTH, 'dayz'],
165
+            'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
166
+        ];
167
+    }
168
+
169
+    private static function standardizeUnit($unit)
170
+    {
171
+        $unit = rtrim($unit, 'sz').'s';
172
+
173
+        return $unit === 'days' ? 'dayz' : $unit;
174
+    }
175
+
176
+    private static function getFlipCascadeFactors()
177
+    {
178
+        if (!self::$flipCascadeFactors) {
179
+            self::$flipCascadeFactors = [];
180
+            foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
181
+                self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
182
+            }
183
+        }
184
+
185
+        return self::$flipCascadeFactors;
186
+    }
187
+
188
+    /**
189
+     * Set default cascading factors for ->cascade() method.
190
+     *
191
+     * @param array $cascadeFactors
192
+     */
193
+    public static function setCascadeFactors(array $cascadeFactors)
194
+    {
195
+        self::$flipCascadeFactors = null;
196
+        static::$cascadeFactors = $cascadeFactors;
197
+    }
198
+
199
+    ///////////////////////////////////////////////////////////////////
200
+    //////////////////////////// CONSTRUCTORS /////////////////////////
201
+    ///////////////////////////////////////////////////////////////////
202
+
203
+    /**
204
+     * Create a new CarbonInterval instance.
205
+     *
206
+     * @param int $years
207
+     * @param int $months
208
+     * @param int $weeks
209
+     * @param int $days
210
+     * @param int $hours
211
+     * @param int $minutes
212
+     * @param int $seconds
213
+     * @param int $microseconds
214
+     *
215
+     * @throws \Exception
216
+     */
217
+    public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
218
+    {
219
+        $spec = $years;
220
+
221
+        if (!is_string($spec) || floatval($years) || preg_match('/^[0-9.]/', $years)) {
222
+            $spec = static::PERIOD_PREFIX;
223
+
224
+            $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
225
+            $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
226
+
227
+            $specDays = 0;
228
+            $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
229
+            $specDays += $days > 0 ? $days : 0;
230
+
231
+            $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
232
+
233
+            if ($hours > 0 || $minutes > 0 || $seconds > 0) {
234
+                $spec .= static::PERIOD_TIME_PREFIX;
235
+                $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
236
+                $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
237
+                $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
238
+            }
239
+
240
+            if ($spec === static::PERIOD_PREFIX) {
241
+                // Allow the zero interval.
242
+                $spec .= '0'.static::PERIOD_YEARS;
243
+            }
244
+        }
245
+
246
+        parent::__construct($spec);
247
+
248
+        if (!is_null($microseconds)) {
249
+            $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
250
+        }
251
+    }
252
+
253
+    /**
254
+     * Returns the factor for a given source-to-target couple.
255
+     *
256
+     * @param string $source
257
+     * @param string $target
258
+     *
259
+     * @return int|null
260
+     */
261
+    public static function getFactor($source, $target)
262
+    {
263
+        $source = self::standardizeUnit($source);
264
+        $target = self::standardizeUnit($target);
265
+        $factors = static::getFlipCascadeFactors();
266
+        if (isset($factors[$source])) {
267
+            [$to, $factor] = $factors[$source];
268
+            if ($to === $target) {
269
+                return $factor;
270
+            }
271
+        }
272
+
273
+        return null;
274
+    }
275
+
276
+    /**
277
+     * Returns current config for days per week.
278
+     *
279
+     * @return int
280
+     */
281
+    public static function getDaysPerWeek()
282
+    {
283
+        return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
284
+    }
285
+
286
+    /**
287
+     * Returns current config for hours per day.
288
+     *
289
+     * @return int
290
+     */
291
+    public static function getHoursPerDay()
292
+    {
293
+        return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
294
+    }
295
+
296
+    /**
297
+     * Returns current config for minutes per hour.
298
+     *
299
+     * @return int
300
+     */
301
+    public static function getMinutesPerHour()
302
+    {
303
+        return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
304
+    }
305
+
306
+    /**
307
+     * Returns current config for seconds per minute.
308
+     *
309
+     * @return int
310
+     */
311
+    public static function getSecondsPerMinute()
312
+    {
313
+        return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
314
+    }
315
+
316
+    /**
317
+     * Returns current config for microseconds per second.
318
+     *
319
+     * @return int
320
+     */
321
+    public static function getMillisecondsPerSecond()
322
+    {
323
+        return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
324
+    }
325
+
326
+    /**
327
+     * Returns current config for microseconds per second.
328
+     *
329
+     * @return int
330
+     */
331
+    public static function getMicrosecondsPerMillisecond()
332
+    {
333
+        return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
334
+    }
335
+
336
+    /**
337
+     * Create a new CarbonInterval instance from specific values.
338
+     * This is an alias for the constructor that allows better fluent
339
+     * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
340
+     * (new CarbonInterval(1))->fn().
341
+     *
342
+     * @param int $years
343
+     * @param int $months
344
+     * @param int $weeks
345
+     * @param int $days
346
+     * @param int $hours
347
+     * @param int $minutes
348
+     * @param int $seconds
349
+     * @param int $microseconds
350
+     *
351
+     * @return static
352
+     */
353
+    public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
354
+    {
355
+        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
356
+    }
357
+
358
+    /**
359
+     * Get a copy of the instance.
360
+     *
361
+     * @return static
362
+     */
363
+    public function copy()
364
+    {
365
+        $date = new static($this->spec());
366
+        $date->invert = $this->invert;
367
+        $date->f = $this->f;
368
+
369
+        return $date;
370
+    }
371
+
372
+    /**
373
+     * Get a copy of the instance.
374
+     *
375
+     * @return static
376
+     */
377
+    public function clone()
378
+    {
379
+        return $this->copy();
380
+    }
381
+
382
+    /**
383
+     * Provide static helpers to create instances.  Allows CarbonInterval::years(3).
384
+     *
385
+     * Note: This is done using the magic method to allow static and instance methods to
386
+     *       have the same names.
387
+     *
388
+     * @param string $method     magic method name called
389
+     * @param array  $parameters parameters list
390
+     *
391
+     * @return static|null
392
+     */
393
+    public static function __callStatic($method, $parameters)
394
+    {
395
+        $arg = count($parameters) === 0 ? 1 : $parameters[0];
396
+
397
+        switch (Carbon::singularUnit(rtrim($method, 'z'))) {
398
+            case 'year':
399
+                return new static($arg);
400
+
401
+            case 'month':
402
+                return new static(null, $arg);
403
+
404
+            case 'week':
405
+                return new static(null, null, $arg);
406
+
407
+            case 'day':
408
+                return new static(null, null, null, $arg);
409
+
410
+            case 'hour':
411
+                return new static(null, null, null, null, $arg);
412
+
413
+            case 'minute':
414
+                return new static(null, null, null, null, null, $arg);
415
+
416
+            case 'second':
417
+                return new static(null, null, null, null, null, null, $arg);
418
+
419
+            case 'millisecond':
420
+            case 'milli':
421
+                return new static(null, null, null, null, null, null, null, $arg * Carbon::MICROSECONDS_PER_MILLISECOND);
422
+
423
+            case 'microsecond':
424
+            case 'micro':
425
+                return new static(null, null, null, null, null, null, null, $arg);
426
+        }
427
+
428
+        if (static::hasMacro($method)) {
429
+            return (new static(0))->$method(...$parameters);
430
+        }
431
+
432
+        if (Carbon::isStrictModeEnabled()) {
433
+            throw new BadMethodCallException(sprintf("Unknown fluent constructor '%s'.", $method));
434
+        }
435
+
436
+        return null;
437
+    }
438
+
439
+    /**
440
+     * Creates a CarbonInterval from string.
441
+     *
442
+     * Format:
443
+     *
444
+     * Suffix | Unit    | Example | DateInterval expression
445
+     * -------|---------|---------|------------------------
446
+     * y      | years   |   1y    | P1Y
447
+     * mo     | months  |   3mo   | P3M
448
+     * w      | weeks   |   2w    | P2W
449
+     * d      | days    |  28d    | P28D
450
+     * h      | hours   |   4h    | PT4H
451
+     * m      | minutes |  12m    | PT12M
452
+     * s      | seconds |  59s    | PT59S
453
+     *
454
+     * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
455
+     *
456
+     * Special cases:
457
+     *  - An empty string will return a zero interval
458
+     *  - Fractions are allowed for weeks, days, hours and minutes and will be converted
459
+     *    and rounded to the next smaller value (caution: 0.5w = 4d)
460
+     *
461
+     * @param string $intervalDefinition
462
+     *
463
+     * @return static
464
+     */
465
+    public static function fromString($intervalDefinition)
466
+    {
467
+        if (empty($intervalDefinition)) {
468
+            return new static(0);
469
+        }
470
+
471
+        $years = 0;
472
+        $months = 0;
473
+        $weeks = 0;
474
+        $days = 0;
475
+        $hours = 0;
476
+        $minutes = 0;
477
+        $seconds = 0;
478
+        $milliseconds = 0;
479
+        $microseconds = 0;
480
+
481
+        $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
482
+        preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
483
+
484
+        while ([$part, $value, $unit] = array_shift($parts)) {
485
+            $intValue = intval($value);
486
+            $fraction = floatval($value) - $intValue;
487
+
488
+            // Fix calculation precision
489
+            switch (round($fraction, 6)) {
490
+                case 1:
491
+                    $fraction = 0;
492
+                    $intValue++;
493
+
494
+                    break;
495
+                case 0:
496
+                    $fraction = 0;
497
+
498
+                    break;
499
+            }
500
+
501
+            switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
502
+                case 'millennia':
503
+                case 'millennium':
504
+                    $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
505
+
506
+                    break;
507
+
508
+                case 'century':
509
+                case 'centuries':
510
+                    $years += $intValue * CarbonInterface::YEARS_PER_CENTURY;
511
+
512
+                    break;
513
+
514
+                case 'decade':
515
+                case 'decades':
516
+                    $years += $intValue * CarbonInterface::YEARS_PER_DECADE;
517
+
518
+                    break;
519
+
520
+                case 'year':
521
+                case 'years':
522
+                case 'y':
523
+                    $years += $intValue;
524
+
525
+                    break;
526
+
527
+                case 'quarter':
528
+                case 'quarters':
529
+                    $months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;
530
+
531
+                    break;
532
+
533
+                case 'month':
534
+                case 'months':
535
+                case 'mo':
536
+                    $months += $intValue;
537
+
538
+                    break;
539
+
540
+                case 'week':
541
+                case 'weeks':
542
+                case 'w':
543
+                    $weeks += $intValue;
544
+
545
+                    if ($fraction) {
546
+                        $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
547
+                    }
548
+
549
+                    break;
550
+
551
+                case 'day':
552
+                case 'days':
553
+                case 'd':
554
+                    $days += $intValue;
555
+
556
+                    if ($fraction) {
557
+                        $parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
558
+                    }
559
+
560
+                    break;
561
+
562
+                case 'hour':
563
+                case 'hours':
564
+                case 'h':
565
+                    $hours += $intValue;
566
+
567
+                    if ($fraction) {
568
+                        $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
569
+                    }
570
+
571
+                    break;
572
+
573
+                case 'minute':
574
+                case 'minutes':
575
+                case 'm':
576
+                    $minutes += $intValue;
577
+
578
+                    if ($fraction) {
579
+                        $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
580
+                    }
581
+
582
+                    break;
583
+
584
+                case 'second':
585
+                case 'seconds':
586
+                case 's':
587
+                    $seconds += $intValue;
588
+
589
+                    if ($fraction) {
590
+                        $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
591
+                    }
592
+
593
+                    break;
594
+
595
+                case 'millisecond':
596
+                case 'milliseconds':
597
+                case 'milli':
598
+                case 'ms':
599
+                    $milliseconds += $intValue;
600
+
601
+                    if ($fraction) {
602
+                        $microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
603
+                    }
604
+
605
+                    break;
606
+
607
+                case 'microsecond':
608
+                case 'microseconds':
609
+                case 'micro':
610
+                case 'µs':
611
+                    $microseconds += $intValue;
612
+
613
+                    break;
614
+
615
+                default:
616
+                    throw new InvalidArgumentException(
617
+                        sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
618
+                    );
619
+            }
620
+        }
621
+
622
+        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
623
+    }
624
+
625
+    /**
626
+     * Creates a CarbonInterval from string using a different locale.
627
+     *
628
+     * @param string $interval
629
+     * @param string $locale
630
+     *
631
+     * @return static
632
+     */
633
+    public static function parseFromLocale($interval, $locale)
634
+    {
635
+        return static::fromString(Carbon::translateTimeString($interval, $locale, 'en'));
636
+    }
637
+
638
+    /**
639
+     * Create a CarbonInterval instance from a DateInterval one.  Can not instance
640
+     * DateInterval objects created from DateTime::diff() as you can't externally
641
+     * set the $days field.
642
+     *
643
+     * @param DateInterval $interval
644
+     *
645
+     * @return static
646
+     */
647
+    public static function instance(DateInterval $interval)
648
+    {
649
+        $microseconds = $interval->f;
650
+        $instance = new static(static::getDateIntervalSpec($interval));
651
+        if ($microseconds) {
652
+            $instance->f = $microseconds;
653
+        }
654
+        $instance->invert = $interval->invert;
655
+        foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
656
+            if ($interval->$unit < 0) {
657
+                $instance->$unit *= -1;
658
+            }
659
+        }
660
+
661
+        return $instance;
662
+    }
663
+
664
+    /**
665
+     * Make a CarbonInterval instance from given variable if possible.
666
+     *
667
+     * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
668
+     * and recurrences). Throw an exception for invalid format, but otherwise return null.
669
+     *
670
+     * @param mixed $var
671
+     *
672
+     * @return static|null
673
+     */
674
+    public static function make($var)
675
+    {
676
+        if ($var instanceof DateInterval) {
677
+            return static::instance($var);
678
+        }
679
+
680
+        if (!is_string($var)) {
681
+            return null;
682
+        }
683
+
684
+        $var = trim($var);
685
+
686
+        if (preg_match('/^P[T0-9]/', $var)) {
687
+            return new static($var);
688
+        }
689
+
690
+        if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $var)) {
691
+            return static::fromString($var);
692
+        }
693
+
694
+        /** @var static $interval */
695
+        $interval = static::createFromDateString($var);
696
+
697
+        return !$interval || $interval->isEmpty() ? null : $interval;
698
+    }
699
+
700
+    protected function resolveInterval($interval)
701
+    {
702
+        if (!($interval instanceof self)) {
703
+            return self::make($interval);
704
+        }
705
+
706
+        return $interval;
707
+    }
708
+
709
+    /**
710
+     * Sets up a DateInterval from the relative parts of the string.
711
+     *
712
+     * @param string $time
713
+     *
714
+     * @return static
715
+     *
716
+     * @link http://php.net/manual/en/dateinterval.createfromdatestring.php
717
+     */
718
+    public static function createFromDateString($time)
719
+    {
720
+        $interval = @parent::createFromDateString(strtr($time, [
721
+            ',' => ' ',
722
+            ' and ' => ' ',
723
+        ]));
724
+
725
+        if ($interval instanceof DateInterval) {
726
+            $interval = static::instance($interval);
727
+        }
728
+
729
+        return $interval;
730
+    }
731
+
732
+    ///////////////////////////////////////////////////////////////////
733
+    ///////////////////////// GETTERS AND SETTERS /////////////////////
734
+    ///////////////////////////////////////////////////////////////////
735
+
736
+    /**
737
+     * Get a part of the CarbonInterval object.
738
+     *
739
+     * @param string $name
740
+     *
741
+     * @throws \InvalidArgumentException
742
+     *
743
+     * @return int|float|string
744
+     */
745
+    public function __get($name)
746
+    {
747
+        if (substr($name, 0, 5) === 'total') {
748
+            return $this->total(substr($name, 5));
749
+        }
750
+
751
+        switch ($name) {
752
+            case 'years':
753
+                return $this->y;
754
+
755
+            case 'months':
756
+                return $this->m;
757
+
758
+            case 'dayz':
759
+                return $this->d;
760
+
761
+            case 'hours':
762
+                return $this->h;
763
+
764
+            case 'minutes':
765
+                return $this->i;
766
+
767
+            case 'seconds':
768
+                return $this->s;
769
+
770
+            case 'milli':
771
+            case 'milliseconds':
772
+                return (int) floor(round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
773
+
774
+            case 'micro':
775
+            case 'microseconds':
776
+                return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
777
+
778
+            case 'weeks':
779
+                return (int) floor($this->d / static::getDaysPerWeek());
780
+
781
+            case 'daysExcludeWeeks':
782
+            case 'dayzExcludeWeeks':
783
+                return $this->d % static::getDaysPerWeek();
784
+
785
+            case 'locale':
786
+                return $this->getLocalTranslator()->getLocale();
787
+
788
+            default:
789
+                throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
790
+        }
791
+    }
792
+
793
+    /**
794
+     * Set a part of the CarbonInterval object.
795
+     *
796
+     * @param string $name
797
+     * @param int    $value
798
+     *
799
+     * @throws \InvalidArgumentException
800
+     */
801
+    public function __set($name, $value)
802
+    {
803
+        switch (Carbon::singularUnit(rtrim($name, 'z'))) {
804
+            case 'year':
805
+                $this->y = $value;
806
+
807
+                break;
808
+
809
+            case 'month':
810
+                $this->m = $value;
811
+
812
+                break;
813
+
814
+            case 'week':
815
+                $this->d = $value * static::getDaysPerWeek();
816
+
817
+                break;
818
+
819
+            case 'day':
820
+                $this->d = $value;
821
+
822
+                break;
823
+
824
+            case 'hour':
825
+                $this->h = $value;
826
+
827
+                break;
828
+
829
+            case 'minute':
830
+                $this->i = $value;
831
+
832
+                break;
833
+
834
+            case 'second':
835
+                $this->s = $value;
836
+
837
+                break;
838
+
839
+            case 'milli':
840
+            case 'millisecond':
841
+                $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
842
+
843
+                break;
844
+
845
+            case 'micro':
846
+            case 'microsecond':
847
+                $this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
848
+
849
+                break;
850
+
851
+            default:
852
+                if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
853
+                    throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
854
+                }
855
+
856
+                $this->$name = $value;
857
+        }
858
+    }
859
+
860
+    /**
861
+     * Allow setting of weeks and days to be cumulative.
862
+     *
863
+     * @param int $weeks Number of weeks to set
864
+     * @param int $days  Number of days to set
865
+     *
866
+     * @return static
867
+     */
868
+    public function weeksAndDays($weeks, $days)
869
+    {
870
+        $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
871
+
872
+        return $this;
873
+    }
874
+
875
+    /**
876
+     * Returns true if the interval is empty for each unit.
877
+     *
878
+     * @return bool
879
+     */
880
+    public function isEmpty()
881
+    {
882
+        return $this->years === 0 &&
883
+            $this->months === 0 &&
884
+            $this->dayz === 0 &&
885
+            !$this->days &&
886
+            $this->hours === 0 &&
887
+            $this->minutes === 0 &&
888
+            $this->seconds === 0 &&
889
+            $this->microseconds === 0;
890
+    }
891
+
892
+    /**
893
+     * Register a custom macro.
894
+     *
895
+     * @example
896
+     * ```
897
+     * CarbonInterval::macro('twice', function () {
898
+     *   return $this->times(2);
899
+     * });
900
+     * echo CarbonInterval::hours(2)->twice();
901
+     * ```
902
+     *
903
+     * @param string          $name
904
+     * @param object|callable $macro
905
+     *
906
+     * @return void
907
+     */
908
+    public static function macro($name, $macro)
909
+    {
910
+        static::$macros[$name] = $macro;
911
+    }
912
+
913
+    /**
914
+     * Register macros from a mixin object.
915
+     *
916
+     * @example
917
+     * ```
918
+     * CarbonInterval::mixin(new class {
919
+     *   public function daysToHours() {
920
+     *     return function () {
921
+     *       $this->hours += $this->days;
922
+     *       $this->days = 0;
923
+     *
924
+     *       return $this;
925
+     *     };
926
+     *   }
927
+     *   public function hoursToDays() {
928
+     *     return function () {
929
+     *       $this->days += $this->hours;
930
+     *       $this->hours = 0;
931
+     *
932
+     *       return $this;
933
+     *     };
934
+     *   }
935
+     * });
936
+     * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
937
+     * echo CarbonInterval::days(5)->daysToHours() . "\n";
938
+     * ```
939
+     *
940
+     * @param object $mixin
941
+     *
942
+     * @throws \ReflectionException
943
+     *
944
+     * @return void
945
+     */
946
+    public static function mixin($mixin)
947
+    {
948
+        $reflection = new ReflectionClass($mixin);
949
+
950
+        $methods = $reflection->getMethods(
951
+            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
952
+        );
953
+
954
+        foreach ($methods as $method) {
955
+            $method->setAccessible(true);
956
+
957
+            static::macro($method->name, $method->invoke($mixin));
958
+        }
959
+    }
960
+
961
+    /**
962
+     * Check if macro is registered.
963
+     *
964
+     * @param string $name
965
+     *
966
+     * @return bool
967
+     */
968
+    public static function hasMacro($name)
969
+    {
970
+        return isset(static::$macros[$name]);
971
+    }
972
+
973
+    /**
974
+     * Call given macro.
975
+     *
976
+     * @param string $name
977
+     * @param array  $parameters
978
+     *
979
+     * @return mixed
980
+     */
981
+    protected function callMacro($name, $parameters)
982
+    {
983
+        $macro = static::$macros[$name];
984
+
985
+        if ($macro instanceof Closure) {
986
+            return call_user_func_array($macro->bindTo($this, static::class), $parameters);
987
+        }
988
+
989
+        return call_user_func_array($macro, $parameters);
990
+    }
991
+
992
+    /**
993
+     * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
994
+     *
995
+     * Note: This is done using the magic method to allow static and instance methods to
996
+     *       have the same names.
997
+     *
998
+     * @param string $method     magic method name called
999
+     * @param array  $parameters parameters list
1000
+     *
1001
+     * @return static
1002
+     */
1003
+    public function __call($method, $parameters)
1004
+    {
1005
+        if (static::hasMacro($method)) {
1006
+            return $this->callMacro($method, $parameters);
1007
+        }
1008
+
1009
+        $arg = count($parameters) === 0 ? 1 : $parameters[0];
1010
+
1011
+        switch (Carbon::singularUnit(rtrim($method, 'z'))) {
1012
+            case 'year':
1013
+                $this->years = $arg;
1014
+
1015
+                break;
1016
+
1017
+            case 'month':
1018
+                $this->months = $arg;
1019
+
1020
+                break;
1021
+
1022
+            case 'week':
1023
+                $this->dayz = $arg * static::getDaysPerWeek();
1024
+
1025
+                break;
1026
+
1027
+            case 'day':
1028
+                $this->dayz = $arg;
1029
+
1030
+                break;
1031
+
1032
+            case 'hour':
1033
+                $this->hours = $arg;
1034
+
1035
+                break;
1036
+
1037
+            case 'minute':
1038
+                $this->minutes = $arg;
1039
+
1040
+                break;
1041
+
1042
+            case 'second':
1043
+                $this->seconds = $arg;
1044
+
1045
+                break;
1046
+
1047
+            case 'milli':
1048
+            case 'millisecond':
1049
+                $this->milliseconds = $arg;
1050
+
1051
+                break;
1052
+
1053
+            case 'micro':
1054
+            case 'microsecond':
1055
+                $this->microseconds = $arg;
1056
+
1057
+                break;
1058
+
1059
+            default:
1060
+                if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
1061
+                    throw new BadMethodCallException(sprintf("Unknown fluent setter '%s'", $method));
1062
+                }
1063
+        }
1064
+
1065
+        return $this;
1066
+    }
1067
+
1068
+    /**
1069
+     * @SuppressWarnings(PHPMD.ElseExpression)
1070
+     *
1071
+     * @param mixed $syntax
1072
+     * @param mixed $short
1073
+     * @param mixed $parts
1074
+     * @param mixed $options
1075
+     *
1076
+     * @return array
1077
+     */
1078
+    protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
1079
+    {
1080
+        $join = ' ';
1081
+        $aUnit = false;
1082
+        if (is_array($syntax)) {
1083
+            extract($syntax);
1084
+        } else {
1085
+            if (is_int($short)) {
1086
+                $parts = $short;
1087
+                $short = false;
1088
+            }
1089
+            if (is_bool($syntax)) {
1090
+                $short = $syntax;
1091
+                $syntax = CarbonInterface::DIFF_ABSOLUTE;
1092
+            }
1093
+        }
1094
+        if (is_null($syntax)) {
1095
+            $syntax = CarbonInterface::DIFF_ABSOLUTE;
1096
+        }
1097
+        if ($parts === -1) {
1098
+            $parts = INF;
1099
+        }
1100
+        if (is_null($options)) {
1101
+            $options = static::getHumanDiffOptions();
1102
+        }
1103
+        if ($join === true) {
1104
+            $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
1105
+            $join = [
1106
+                $default,
1107
+                $this->getTranslationMessage('list.1') ?? $default,
1108
+            ];
1109
+        }
1110
+        if (is_array($join)) {
1111
+            [$default, $last] = $join;
1112
+
1113
+            $join = function ($list) use ($default, $last) {
1114
+                if (count($list) < 2) {
1115
+                    return implode('', $list);
1116
+                }
1117
+
1118
+                $end = array_pop($list);
1119
+
1120
+                return implode($default, $list).$last.$end;
1121
+            };
1122
+        }
1123
+        if (is_string($join)) {
1124
+            $glue = $join;
1125
+            $join = function ($list) use ($glue) {
1126
+                return implode($glue, $list);
1127
+            };
1128
+        }
1129
+
1130
+        return [$syntax, $short, $parts, $options, $join, $aUnit];
1131
+    }
1132
+
1133
+    /**
1134
+     * Get the current interval in a human readable format in the current locale.
1135
+     *
1136
+     * @example
1137
+     * ```
1138
+     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
1139
+     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
1140
+     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
1141
+     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
1142
+     * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
1143
+     * ```
1144
+     *
1145
+     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
1146
+     *                           - 'syntax' entry (see below)
1147
+     *                           - 'short' entry (see below)
1148
+     *                           - 'parts' entry (see below)
1149
+     *                           - 'options' entry (see below)
1150
+     *                           - 'aUnit' entry, prefer "an hour" over "1 hour" if true
1151
+     *                           - 'join' entry determines how to join multiple parts of the string
1152
+     *                           `  - if $join is a string, it's used as a joiner glue
1153
+     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
1154
+     *                           `  - if $join is an array, the first item will be the default glue, and the second item
1155
+     *                           `    will be used instead of the glue for the last item
1156
+     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
1157
+     *                           `  - if $join is missing, a space will be used as glue
1158
+     *                           if int passed, it add modifiers:
1159
+     *                           Possible values:
1160
+     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
1161
+     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
1162
+     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
1163
+     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
1164
+     * @param bool      $short   displays short format of time units
1165
+     * @param int       $parts   maximum number of parts to display (default value: -1: no limits)
1166
+     * @param int       $options human diff options
1167
+     *
1168
+     * @return string
1169
+     */
1170
+    public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
1171
+    {
1172
+        [$syntax, $short, $parts, $options, $join, $aUnit] = $this->getForHumansParameters($syntax, $short, $parts, $options);
1173
+
1174
+        $interval = [];
1175
+        $syntax = (int) ($syntax === null ? CarbonInterface::DIFF_ABSOLUTE : $syntax);
1176
+        $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
1177
+        $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
1178
+        $count = 1;
1179
+        $unit = $short ? 's' : 'second';
1180
+
1181
+        /** @var \Symfony\Component\Translation\Translator $translator */
1182
+        $translator = $this->getLocalTranslator();
1183
+
1184
+        $diffIntervalArray = [
1185
+            ['value' => $this->years,            'unit' => 'year',   'unitShort' => 'y'],
1186
+            ['value' => $this->months,           'unit' => 'month',  'unitShort' => 'm'],
1187
+            ['value' => $this->weeks,            'unit' => 'week',   'unitShort' => 'w'],
1188
+            ['value' => $this->daysExcludeWeeks, 'unit' => 'day',    'unitShort' => 'd'],
1189
+            ['value' => $this->hours,            'unit' => 'hour',   'unitShort' => 'h'],
1190
+            ['value' => $this->minutes,          'unit' => 'minute', 'unitShort' => 'min'],
1191
+            ['value' => $this->seconds,          'unit' => 'second', 'unitShort' => 's'],
1192
+        ];
1193
+
1194
+        $transChoice = function ($short, $unitData) use ($translator, $aUnit) {
1195
+            $count = $unitData['value'];
1196
+
1197
+            if ($short) {
1198
+                $result = $this->translate($unitData['unitShort'], [], $count, $translator);
1199
+
1200
+                if ($result !== $unitData['unitShort']) {
1201
+                    return $result;
1202
+                }
1203
+            } elseif ($aUnit) {
1204
+                $key = 'a_'.$unitData['unit'];
1205
+                $result = $this->translate($key, [], $count, $translator);
1206
+
1207
+                if ($result !== $key) {
1208
+                    return $result;
1209
+                }
1210
+            }
1211
+
1212
+            return $this->translate($unitData['unit'], [], $count, $translator);
1213
+        };
1214
+
1215
+        foreach ($diffIntervalArray as $diffIntervalData) {
1216
+            if ($diffIntervalData['value'] > 0) {
1217
+                $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
1218
+                $count = $diffIntervalData['value'];
1219
+                $interval[] = $transChoice($short, $diffIntervalData);
1220
+            } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && count($interval) > 0) {
1221
+                break;
1222
+            }
1223
+
1224
+            // break the loop after we get the required number of parts in array
1225
+            if (count($interval) >= $parts) {
1226
+                break;
1227
+            }
1228
+        }
1229
+
1230
+        if (count($interval) === 0) {
1231
+            if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
1232
+                $key = 'diff_now';
1233
+                $translation = $this->translate($key, [], null, $translator);
1234
+                if ($translation !== $key) {
1235
+                    return $translation;
1236
+                }
1237
+            }
1238
+            $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
1239
+            $unit = $short ? 's' : 'second';
1240
+            $interval[] = $this->translate($unit, [], $count, $translator);
1241
+        }
1242
+
1243
+        // join the interval parts by a space
1244
+        $time = $join($interval);
1245
+
1246
+        unset($diffIntervalArray, $interval);
1247
+
1248
+        if ($absolute) {
1249
+            return $time;
1250
+        }
1251
+
1252
+        $isFuture = $this->invert === 1;
1253
+
1254
+        $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
1255
+
1256
+        if ($parts === 1) {
1257
+            if ($relativeToNow && $unit === 'day') {
1258
+                if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
1259
+                    $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
1260
+                    $translation = $this->translate($key, [], null, $translator);
1261
+                    if ($translation !== $key) {
1262
+                        return $translation;
1263
+                    }
1264
+                }
1265
+                if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
1266
+                    $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
1267
+                    $translation = $this->translate($key, [], null, $translator);
1268
+                    if ($translation !== $key) {
1269
+                        return $translation;
1270
+                    }
1271
+                }
1272
+            }
1273
+            // Some languages have special pluralization for past and future tense.
1274
+            $key = $unit.'_'.$transId;
1275
+            if ($key !== $this->translate($key, [], null, $translator)) {
1276
+                $time = $this->translate($key, [], $count, $translator);
1277
+            }
1278
+        }
1279
+
1280
+        return $this->translate($transId, [':time' => $time], null, $translator);
1281
+    }
1282
+
1283
+    /**
1284
+     * Format the instance as a string using the forHumans() function.
1285
+     *
1286
+     * @return string
1287
+     */
1288
+    public function __toString()
1289
+    {
1290
+        return $this->forHumans();
1291
+    }
1292
+
1293
+    /**
1294
+     * Convert the interval to a CarbonPeriod.
1295
+     *
1296
+     * @return CarbonPeriod
1297
+     */
1298
+    public function toPeriod(...$params)
1299
+    {
1300
+        return CarbonPeriod::create($this, ...$params);
1301
+    }
1302
+
1303
+    /**
1304
+     * Invert the interval.
1305
+     *
1306
+     * @return $this
1307
+     */
1308
+    public function invert()
1309
+    {
1310
+        $this->invert = $this->invert ? 0 : 1;
1311
+
1312
+        return $this;
1313
+    }
1314
+
1315
+    protected function solveNegativeInterval()
1316
+    {
1317
+        if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
1318
+            $this->years *= -1;
1319
+            $this->months *= -1;
1320
+            $this->dayz *= -1;
1321
+            $this->hours *= -1;
1322
+            $this->minutes *= -1;
1323
+            $this->seconds *= -1;
1324
+            $this->microseconds *= -1;
1325
+            $this->invert();
1326
+        }
1327
+
1328
+        return $this;
1329
+    }
1330
+
1331
+    /**
1332
+     * Add the passed interval to the current instance.
1333
+     *
1334
+     * @param string|DateInterval $unit
1335
+     * @param int                 $value
1336
+     *
1337
+     * @return static
1338
+     */
1339
+    public function add($unit, $value = 1)
1340
+    {
1341
+        if (is_numeric($unit)) {
1342
+            [$value, $unit] = [$unit, $value];
1343
+        }
1344
+
1345
+        if (is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
1346
+            $unit = "$value $unit";
1347
+            $value = 1;
1348
+        }
1349
+
1350
+        $interval = static::make($unit);
1351
+
1352
+        if (!$interval) {
1353
+            throw new InvalidArgumentException('This type of data cannot be added/subtracted.');
1354
+        }
1355
+
1356
+        if ($value !== 1) {
1357
+            $interval->times($value);
1358
+        }
1359
+        $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
1360
+        $this->years += $interval->y * $sign;
1361
+        $this->months += $interval->m * $sign;
1362
+        $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
1363
+        $this->hours += $interval->h * $sign;
1364
+        $this->minutes += $interval->i * $sign;
1365
+        $this->seconds += $interval->s * $sign;
1366
+        $this->microseconds += $interval->microseconds * $sign;
1367
+
1368
+        $this->solveNegativeInterval();
1369
+
1370
+        return $this;
1371
+    }
1372
+
1373
+    /**
1374
+     * Subtract the passed interval to the current instance.
1375
+     *
1376
+     * @param string|DateInterval $unit
1377
+     * @param int                 $value
1378
+     *
1379
+     * @return static
1380
+     */
1381
+    public function sub($unit, $value = 1)
1382
+    {
1383
+        if (is_numeric($unit)) {
1384
+            [$value, $unit] = [$unit, $value];
1385
+        }
1386
+
1387
+        return $this->add($unit, -floatval($value));
1388
+    }
1389
+
1390
+    /**
1391
+     * Subtract the passed interval to the current instance.
1392
+     *
1393
+     * @param string|DateInterval $unit
1394
+     * @param int                 $value
1395
+     *
1396
+     * @return static
1397
+     */
1398
+    public function subtract($unit, $value = 1)
1399
+    {
1400
+        return $this->sub($unit, $value);
1401
+    }
1402
+
1403
+    /**
1404
+     * Multiply current instance given number of times. times() is naive, it multiplies each unit
1405
+     * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
1406
+     * separately for each unit.
1407
+     *
1408
+     * Use times() when you want a fast and approximated calculation that does not cascade units.
1409
+     *
1410
+     * For a precise and cascaded calculation,
1411
+     *
1412
+     * @see multiply()
1413
+     *
1414
+     * @param float|int $factor
1415
+     *
1416
+     * @return $this
1417
+     */
1418
+    public function times($factor)
1419
+    {
1420
+        if ($factor < 0) {
1421
+            $this->invert = $this->invert ? 0 : 1;
1422
+            $factor = -$factor;
1423
+        }
1424
+
1425
+        $this->years = (int) round($this->years * $factor);
1426
+        $this->months = (int) round($this->months * $factor);
1427
+        $this->dayz = (int) round($this->dayz * $factor);
1428
+        $this->hours = (int) round($this->hours * $factor);
1429
+        $this->minutes = (int) round($this->minutes * $factor);
1430
+        $this->seconds = (int) round($this->seconds * $factor);
1431
+        $this->microseconds = (int) round($this->microseconds * $factor);
1432
+
1433
+        return $this;
1434
+    }
1435
+
1436
+    /**
1437
+     * Divide current instance by a given divider. shares() is naive, it divides each unit separately
1438
+     * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
1439
+     * and 7 minutes.
1440
+     *
1441
+     * Use shares() when you want a fast and approximated calculation that does not cascade units.
1442
+     *
1443
+     * For a precise and cascaded calculation,
1444
+     *
1445
+     * @see divide()
1446
+     *
1447
+     * @param float|int $divider
1448
+     *
1449
+     * @return $this
1450
+     */
1451
+    public function shares($divider)
1452
+    {
1453
+        return $this->times(1 / $divider);
1454
+    }
1455
+
1456
+    /**
1457
+     * Multiply and cascade current instance by a given factor.
1458
+     *
1459
+     * @param float|int $factor
1460
+     *
1461
+     * @return $this
1462
+     */
1463
+    public function multiply($factor)
1464
+    {
1465
+        if ($factor < 0) {
1466
+            $this->invert = $this->invert ? 0 : 1;
1467
+            $factor = -$factor;
1468
+        }
1469
+
1470
+        $yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision
1471
+
1472
+        if ($yearPart) {
1473
+            $this->years -= $yearPart / $factor;
1474
+        }
1475
+
1476
+        $newInterval = static::__callStatic('years', [$yearPart])->microseconds($this->totalMicroseconds * $factor)->cascade();
1477
+
1478
+        $this->years = $newInterval->years;
1479
+        $this->months = $newInterval->months;
1480
+        $this->dayz = $newInterval->dayz;
1481
+        $this->hours = $newInterval->hours;
1482
+        $this->minutes = $newInterval->minutes;
1483
+        $this->seconds = $newInterval->seconds;
1484
+        $this->microseconds = $newInterval->microseconds;
1485
+
1486
+        return $this;
1487
+    }
1488
+
1489
+    /**
1490
+     * Divide and cascade current instance by a given divider.
1491
+     *
1492
+     * @param float|int $divider
1493
+     *
1494
+     * @return $this
1495
+     */
1496
+    public function divide($divider)
1497
+    {
1498
+        return $this->multiply(1 / $divider);
1499
+    }
1500
+
1501
+    /**
1502
+     * Get the interval_spec string of a date interval.
1503
+     *
1504
+     * @param DateInterval $interval
1505
+     *
1506
+     * @return string
1507
+     */
1508
+    public static function getDateIntervalSpec(DateInterval $interval)
1509
+    {
1510
+        $date = array_filter([
1511
+            static::PERIOD_YEARS => abs($interval->y),
1512
+            static::PERIOD_MONTHS => abs($interval->m),
1513
+            static::PERIOD_DAYS => abs($interval->d),
1514
+        ]);
1515
+
1516
+        $time = array_filter([
1517
+            static::PERIOD_HOURS => abs($interval->h),
1518
+            static::PERIOD_MINUTES => abs($interval->i),
1519
+            static::PERIOD_SECONDS => abs($interval->s),
1520
+        ]);
1521
+
1522
+        $specString = static::PERIOD_PREFIX;
1523
+
1524
+        foreach ($date as $key => $value) {
1525
+            $specString .= $value.$key;
1526
+        }
1527
+
1528
+        if (count($time) > 0) {
1529
+            $specString .= static::PERIOD_TIME_PREFIX;
1530
+            foreach ($time as $key => $value) {
1531
+                $specString .= $value.$key;
1532
+            }
1533
+        }
1534
+
1535
+        return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
1536
+    }
1537
+
1538
+    /**
1539
+     * Get the interval_spec string.
1540
+     *
1541
+     * @return string
1542
+     */
1543
+    public function spec()
1544
+    {
1545
+        return static::getDateIntervalSpec($this);
1546
+    }
1547
+
1548
+    /**
1549
+     * Comparing 2 date intervals.
1550
+     *
1551
+     * @param DateInterval $first
1552
+     * @param DateInterval $second
1553
+     *
1554
+     * @return int
1555
+     */
1556
+    public static function compareDateIntervals(DateInterval $first, DateInterval $second)
1557
+    {
1558
+        $current = Carbon::now();
1559
+        $passed = $current->copy()->add($second);
1560
+        $current->add($first);
1561
+
1562
+        if ($current < $passed) {
1563
+            return -1;
1564
+        }
1565
+        if ($current > $passed) {
1566
+            return 1;
1567
+        }
1568
+
1569
+        return 0;
1570
+    }
1571
+
1572
+    /**
1573
+     * Comparing with passed interval.
1574
+     *
1575
+     * @param DateInterval $interval
1576
+     *
1577
+     * @return int
1578
+     */
1579
+    public function compare(DateInterval $interval)
1580
+    {
1581
+        return static::compareDateIntervals($this, $interval);
1582
+    }
1583
+
1584
+    /**
1585
+     * Convert overflowed values into bigger units.
1586
+     *
1587
+     * @return $this
1588
+     */
1589
+    public function cascade()
1590
+    {
1591
+        foreach (static::getFlipCascadeFactors() as $source => [$target, $factor]) {
1592
+            if ($source === 'dayz' && $target === 'weeks') {
1593
+                continue;
1594
+            }
1595
+
1596
+            $value = $this->$source;
1597
+            $this->$source = $modulo = ($factor + ($value % $factor)) % $factor;
1598
+            $this->$target += ($value - $modulo) / $factor;
1599
+            if ($this->$source > 0 && $this->$target < 0) {
1600
+                $this->$source -= $factor;
1601
+                $this->$target++;
1602
+            }
1603
+        }
1604
+
1605
+        return $this->solveNegativeInterval();
1606
+    }
1607
+
1608
+    /**
1609
+     * Get amount of given unit equivalent to the interval.
1610
+     *
1611
+     * @param string $unit
1612
+     *
1613
+     * @throws \InvalidArgumentException
1614
+     *
1615
+     * @return float
1616
+     */
1617
+    public function total($unit)
1618
+    {
1619
+        $realUnit = $unit = strtolower($unit);
1620
+
1621
+        if (in_array($unit, ['days', 'weeks'])) {
1622
+            $realUnit = 'dayz';
1623
+        } elseif (!in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
1624
+            throw new InvalidArgumentException("Unknown unit '$unit'.");
1625
+        }
1626
+
1627
+        $result = 0;
1628
+        $cumulativeFactor = 0;
1629
+        $unitFound = false;
1630
+        $factors = static::getFlipCascadeFactors();
1631
+
1632
+        foreach ($factors as $source => [$target, $factor]) {
1633
+            if ($source === $realUnit) {
1634
+                $unitFound = true;
1635
+                $value = $this->$source;
1636
+                if ($source === 'microseconds' && isset($factors['milliseconds'])) {
1637
+                    $value %= Carbon::MICROSECONDS_PER_MILLISECOND;
1638
+                }
1639
+                $result += $value;
1640
+                $cumulativeFactor = 1;
1641
+            }
1642
+
1643
+            if ($factor === false) {
1644
+                if ($unitFound) {
1645
+                    break;
1646
+                }
1647
+
1648
+                $result = 0;
1649
+                $cumulativeFactor = 0;
1650
+
1651
+                continue;
1652
+            }
1653
+
1654
+            if ($target === $realUnit) {
1655
+                $unitFound = true;
1656
+            }
1657
+
1658
+            if ($cumulativeFactor) {
1659
+                $cumulativeFactor *= $factor;
1660
+                $result += $this->$target * $cumulativeFactor;
1661
+
1662
+                continue;
1663
+            }
1664
+
1665
+            $value = $this->$source;
1666
+
1667
+            if ($source === 'microseconds' && isset($factors['milliseconds'])) {
1668
+                $value %= Carbon::MICROSECONDS_PER_MILLISECOND;
1669
+            }
1670
+
1671
+            $result = ($result + $value) / $factor;
1672
+        }
1673
+
1674
+        if (isset($target) && !$cumulativeFactor) {
1675
+            $result += $this->$target;
1676
+        }
1677
+
1678
+        if (!$unitFound) {
1679
+            throw new \InvalidArgumentException("Unit $unit have no configuration to get total from other units.");
1680
+        }
1681
+
1682
+        if ($unit === 'weeks') {
1683
+            return $result / static::getDaysPerWeek();
1684
+        }
1685
+
1686
+        return $result;
1687
+    }
1688
+
1689
+    /**
1690
+     * Determines if the instance is equal to another
1691
+     *
1692
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1693
+     *
1694
+     * @see equalTo()
1695
+     *
1696
+     * @return bool
1697
+     */
1698
+    public function eq($interval): bool
1699
+    {
1700
+        return $this->equalTo($interval);
1701
+    }
1702
+
1703
+    /**
1704
+     * Determines if the instance is equal to another
1705
+     *
1706
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1707
+     *
1708
+     * @return bool
1709
+     */
1710
+    public function equalTo($interval): bool
1711
+    {
1712
+        $interval = $this->resolveInterval($interval);
1713
+
1714
+        return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds;
1715
+    }
1716
+
1717
+    /**
1718
+     * Determines if the instance is not equal to another
1719
+     *
1720
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1721
+     *
1722
+     * @see notEqualTo()
1723
+     *
1724
+     * @return bool
1725
+     */
1726
+    public function ne($interval): bool
1727
+    {
1728
+        return $this->notEqualTo($interval);
1729
+    }
1730
+
1731
+    /**
1732
+     * Determines if the instance is not equal to another
1733
+     *
1734
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1735
+     *
1736
+     * @return bool
1737
+     */
1738
+    public function notEqualTo($interval): bool
1739
+    {
1740
+        return !$this->eq($interval);
1741
+    }
1742
+
1743
+    /**
1744
+     * Determines if the instance is greater (longer) than another
1745
+     *
1746
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1747
+     *
1748
+     * @see greaterThan()
1749
+     *
1750
+     * @return bool
1751
+     */
1752
+    public function gt($interval): bool
1753
+    {
1754
+        return $this->greaterThan($interval);
1755
+    }
1756
+
1757
+    /**
1758
+     * Determines if the instance is greater (longer) than another
1759
+     *
1760
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1761
+     *
1762
+     * @return bool
1763
+     */
1764
+    public function greaterThan($interval): bool
1765
+    {
1766
+        $interval = $this->resolveInterval($interval);
1767
+
1768
+        return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
1769
+    }
1770
+
1771
+    /**
1772
+     * Determines if the instance is greater (longer) than or equal to another
1773
+     *
1774
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1775
+     *
1776
+     * @see greaterThanOrEqualTo()
1777
+     *
1778
+     * @return bool
1779
+     */
1780
+    public function gte($interval): bool
1781
+    {
1782
+        return $this->greaterThanOrEqualTo($interval);
1783
+    }
1784
+
1785
+    /**
1786
+     * Determines if the instance is greater (longer) than or equal to another
1787
+     *
1788
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1789
+     *
1790
+     * @return bool
1791
+     */
1792
+    public function greaterThanOrEqualTo($interval): bool
1793
+    {
1794
+        return $this->greaterThan($interval) || $this->equalTo($interval);
1795
+    }
1796
+
1797
+    /**
1798
+     * Determines if the instance is less (shorter) than another
1799
+     *
1800
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1801
+     *
1802
+     * @see lessThan()
1803
+     *
1804
+     * @return bool
1805
+     */
1806
+    public function lt($interval): bool
1807
+    {
1808
+        return $this->lessThan($interval);
1809
+    }
1810
+
1811
+    /**
1812
+     * Determines if the instance is less (shorter) than another
1813
+     *
1814
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1815
+     *
1816
+     * @return bool
1817
+     */
1818
+    public function lessThan($interval): bool
1819
+    {
1820
+        $interval = $this->resolveInterval($interval);
1821
+
1822
+        return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
1823
+    }
1824
+
1825
+    /**
1826
+     * Determines if the instance is less (shorter) than or equal to another
1827
+     *
1828
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1829
+     *
1830
+     * @see lessThanOrEqualTo()
1831
+     *
1832
+     * @return bool
1833
+     */
1834
+    public function lte($interval): bool
1835
+    {
1836
+        return $this->lessThanOrEqualTo($interval);
1837
+    }
1838
+
1839
+    /**
1840
+     * Determines if the instance is less (shorter) than or equal to another
1841
+     *
1842
+     * @param \Carbon\CarbonInterval|DateInterval|mixed $interval
1843
+     *
1844
+     * @return bool
1845
+     */
1846
+    public function lessThanOrEqualTo($interval): bool
1847
+    {
1848
+        return $this->lessThan($interval) || $this->equalTo($interval);
1849
+    }
1850
+
1851
+    /**
1852
+     * Determines if the instance is between two others.
1853
+     *
1854
+     * @example
1855
+     * ```
1856
+     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
1857
+     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
1858
+     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
1859
+     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
1860
+     * ```
1861
+     *
1862
+     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval1
1863
+     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval2
1864
+     * @param bool                                       $equal     Indicates if an equal to comparison should be done
1865
+     *
1866
+     * @return bool
1867
+     */
1868
+    public function between($interval1, $interval2, $equal = true): bool
1869
+    {
1870
+        return $equal
1871
+            ? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
1872
+            : $this->greaterThan($interval1) && $this->lessThan($interval2);
1873
+    }
1874
+
1875
+    /**
1876
+     * Determines if the instance is between two others, bounds excluded.
1877
+     *
1878
+     * @example
1879
+     * ```
1880
+     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
1881
+     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
1882
+     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
1883
+     * ```
1884
+     *
1885
+     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval1
1886
+     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval2
1887
+     *
1888
+     * @return bool
1889
+     */
1890
+    public function betweenExcluded($interval1, $interval2): bool
1891
+    {
1892
+        return $this->between($interval1, $interval2, false);
1893
+    }
1894
+
1895
+    /**
1896
+     * Determines if the instance is between two others
1897
+     *
1898
+     * @example
1899
+     * ```
1900
+     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
1901
+     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
1902
+     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
1903
+     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
1904
+     * ```
1905
+     *
1906
+     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval1
1907
+     * @param \Carbon\CarbonInterval|\DateInterval|mixed $interval2
1908
+     * @param bool                                       $equal     Indicates if an equal to comparison should be done
1909
+     *
1910
+     * @return bool
1911
+     */
1912
+    public function isBetween($interval1, $interval2, $equal = true): bool
1913
+    {
1914
+        return $this->between($interval1, $interval2, $equal);
1915
+    }
1916
+}