briannesbitt / Carbon
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\Traits;
12

13
use Carbon\Carbon;
14
use Carbon\CarbonImmutable;
15
use Carbon\CarbonInterface;
16
use Carbon\CarbonInterval;
17
use Carbon\CarbonPeriod;
18
use Carbon\Translator;
19
use Closure;
20
use DateInterval;
21
use DateTimeInterface;
22

23
/**
24
 * Trait Difference.
25
 *
26
 * Depends on the following methods:
27
 *
28
 * @method bool lessThan($date)
29
 * @method static copy()
30
 * @method static resolveCarbon($date = null)
31
 * @method static Translator translator()
32
 */
33
trait Difference
34
{
35
    /**
36
     * @codeCoverageIgnore
37
     *
38
     * @param CarbonInterval $diff
39
     */
40
    protected static function fixNegativeMicroseconds(CarbonInterval $diff)
41
    {
42
        if ($diff->s !== 0 || $diff->i !== 0 || $diff->h !== 0 || $diff->d !== 0 || $diff->m !== 0 || $diff->y !== 0) {
43
            $diff->f = (round($diff->f * 1000000) + 1000000) / 1000000;
44
            $diff->s--;
45

46
            if ($diff->s < 0) {
47
                $diff->s += 60;
48
                $diff->i--;
49

50
                if ($diff->i < 0) {
51
                    $diff->i += 60;
52
                    $diff->h--;
53

54
                    if ($diff->h < 0) {
55
                        $diff->h += 24;
56
                        $diff->d--;
57

58
                        if ($diff->d < 0) {
59
                            $diff->d += 30;
60
                            $diff->m--;
61

62
                            if ($diff->m < 0) {
63
                                $diff->m += 12;
64
                                $diff->y--;
65
                            }
66
                        }
67
                    }
68
                }
69
            }
70

71
            return;
72
        }
73

74
        $diff->f *= -1;
75
        $diff->invert();
76
    }
77

78
    /**
79
     * @param DateInterval $diff
80
     * @param bool         $absolute
81
     *
82
     * @return CarbonInterval
83
     */
84 2
    protected static function fixDiffInterval(DateInterval $diff, $absolute)
85
    {
86 2
        $diff = CarbonInterval::instance($diff);
87

88
        // Work-around for https://bugs.php.net/bug.php?id=77145
89
        // @codeCoverageIgnoreStart
90
        if ($diff->f > 0 && $diff->y === -1 && $diff->m === 11 && $diff->d >= 27 && $diff->h === 23 && $diff->i === 59 && $diff->s === 59) {
91
            $diff->y = 0;
92
            $diff->m = 0;
93
            $diff->d = 0;
94
            $diff->h = 0;
95
            $diff->i = 0;
96
            $diff->s = 0;
97
            $diff->f = (1000000 - round($diff->f * 1000000)) / 1000000;
98
            $diff->invert();
99
        } elseif ($diff->f < 0) {
100
            static::fixNegativeMicroseconds($diff);
101
        }
102
        // @codeCoverageIgnoreEnd
103

104 2
        if ($absolute && $diff->invert) {
105 2
            $diff->invert();
106
        }
107

108 2
        return $diff;
109
    }
110

111
    /**
112
     * Get the difference as a DateInterval instance.
113
     * Return relative interval (negative if
114
     *
115
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
116
     * @param bool                                                   $absolute Get the absolute of the difference
117
     *
118
     * @return DateInterval
119
     */
120 2
    public function diff($date = null, $absolute = false)
121
    {
122 2
        return parent::diff($this->resolveCarbon($date), (bool) $absolute);
123
    }
124

125
    /**
126
     * Get the difference as a CarbonInterval instance.
127
     * Return absolute interval (always positive) unless you pass false to the second argument.
128
     *
129
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
130
     * @param bool                                                   $absolute Get the absolute of the difference
131
     *
132
     * @return CarbonInterval
133
     */
134 2
    public function diffAsCarbonInterval($date = null, $absolute = true)
135
    {
136 2
        return static::fixDiffInterval($this->diff($this->resolveCarbon($date), $absolute), $absolute);
137
    }
138

139
    /**
140
     * Get the difference in years
141
     *
142
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
143
     * @param bool                                                   $absolute Get the absolute of the difference
144
     *
145
     * @return int
146
     */
147 2
    public function diffInYears($date = null, $absolute = true)
148
    {
149 2
        return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y');
150
    }
151

152
    /**
153
     * Get the difference in quarters rounded down.
154
     *
155
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
156
     * @param bool                                                   $absolute Get the absolute of the difference
157
     *
158
     * @return int
159
     */
160 2
    public function diffInQuarters($date = null, $absolute = true)
161
    {
162 2
        return (int) ($this->diffInMonths($date, $absolute) / static::MONTHS_PER_QUARTER);
163
    }
164

165
    /**
166
     * Get the difference in months rounded down.
167
     *
168
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
169
     * @param bool                                                   $absolute Get the absolute of the difference
170
     *
171
     * @return int
172
     */
173 2
    public function diffInMonths($date = null, $absolute = true)
174
    {
175 2
        $date = $this->resolveCarbon($date);
176

177 2
        return $this->diffInYears($date, $absolute) * static::MONTHS_PER_YEAR + (int) $this->diff($date, $absolute)->format('%r%m');
178
    }
179

180
    /**
181
     * Get the difference in weeks rounded down.
182
     *
183
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
184
     * @param bool                                                   $absolute Get the absolute of the difference
185
     *
186
     * @return int
187
     */
188 2
    public function diffInWeeks($date = null, $absolute = true)
189
    {
190 2
        return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK);
191
    }
192

193
    /**
194
     * Get the difference in days rounded down.
195
     *
196
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
197
     * @param bool                                                   $absolute Get the absolute of the difference
198
     *
199
     * @return int
200
     */
201 2
    public function diffInDays($date = null, $absolute = true)
202
    {
203 2
        return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%a');
204
    }
205

206
    /**
207
     * Get the difference in days using a filter closure rounded down.
208
     *
209
     * @param Closure                                                $callback
210
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
211
     * @param bool                                                   $absolute Get the absolute of the difference
212
     *
213
     * @return int
214
     */
215 2
    public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true)
216
    {
217 2
        return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute);
218
    }
219

220
    /**
221
     * Get the difference in hours using a filter closure rounded down.
222
     *
223
     * @param Closure                                                $callback
224
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
225
     * @param bool                                                   $absolute Get the absolute of the difference
226
     *
227
     * @return int
228
     */
229 2
    public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true)
230
    {
231 2
        return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute);
232
    }
233

234
    /**
235
     * Get the difference by the given interval using a filter closure.
236
     *
237
     * @param CarbonInterval                                         $ci       An interval to traverse by
238
     * @param Closure                                                $callback
239
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
240
     * @param bool                                                   $absolute Get the absolute of the difference
241
     *
242
     * @return int
243
     */
244 2
    public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true)
245
    {
246 2
        $start = $this;
247 2
        $end = $this->resolveCarbon($date);
248 2
        $inverse = false;
249

250 2
        if ($end < $start) {
251 2
            $start = $end;
252 2
            $end = $this;
253 2
            $inverse = true;
254
        }
255

256 2
        $options = CarbonPeriod::EXCLUDE_END_DATE | ($this->isMutable() ? 0 : CarbonPeriod::IMMUTABLE);
257 2
        $diff = $ci->toPeriod($start, $end, $options)->filter($callback)->count();
258

259 2
        return $inverse && !$absolute ? -$diff : $diff;
260
    }
261

262
    /**
263
     * Get the difference in weekdays rounded down.
264
     *
265
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
266
     * @param bool                                                   $absolute Get the absolute of the difference
267
     *
268
     * @return int
269
     */
270 2
    public function diffInWeekdays($date = null, $absolute = true)
271
    {
272
        return $this->diffInDaysFiltered(function (CarbonInterface $date) {
273 2
            return $date->isWeekday();
274 2
        }, $date, $absolute);
275
    }
276

277
    /**
278
     * Get the difference in weekend days using a filter rounded down.
279
     *
280
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
281
     * @param bool                                                   $absolute Get the absolute of the difference
282
     *
283
     * @return int
284
     */
285 2
    public function diffInWeekendDays($date = null, $absolute = true)
286
    {
287
        return $this->diffInDaysFiltered(function (CarbonInterface $date) {
288 2
            return $date->isWeekend();
289 2
        }, $date, $absolute);
290
    }
291

292
    /**
293
     * Get the difference in hours rounded down.
294
     *
295
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
296
     * @param bool                                                   $absolute Get the absolute of the difference
297
     *
298
     * @return int
299
     */
300 2
    public function diffInHours($date = null, $absolute = true)
301
    {
302 2
        return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
303
    }
304

305
    /**
306
     * Get the difference in hours rounded down using timestamps.
307
     *
308
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
309
     * @param bool                                                   $absolute Get the absolute of the difference
310
     *
311
     * @return int
312
     */
313 2
    public function diffInRealHours($date = null, $absolute = true)
314
    {
315 2
        return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
316
    }
317

318
    /**
319
     * Get the difference in minutes rounded down.
320
     *
321
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
322
     * @param bool                                                   $absolute Get the absolute of the difference
323
     *
324
     * @return int
325
     */
326 2
    public function diffInMinutes($date = null, $absolute = true)
327
    {
328 2
        return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
329
    }
330

331
    /**
332
     * Get the difference in minutes rounded down using timestamps.
333
     *
334
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
335
     * @param bool                                                   $absolute Get the absolute of the difference
336
     *
337
     * @return int
338
     */
339 2
    public function diffInRealMinutes($date = null, $absolute = true)
340
    {
341 2
        return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
342
    }
343

344
    /**
345
     * Get the difference in seconds rounded down.
346
     *
347
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
348
     * @param bool                                                   $absolute Get the absolute of the difference
349
     *
350
     * @return int
351
     */
352 2
    public function diffInSeconds($date = null, $absolute = true)
353
    {
354 2
        $diff = $this->diff($date);
355

356 2
        if ($diff->days === 0) {
357 2
            $diff = static::fixDiffInterval($diff, $absolute);
358
        }
359

360 2
        $value = (((($diff->m || $diff->y ? $diff->days : $diff->d) * static::HOURS_PER_DAY) +
361 2
            $diff->h) * static::MINUTES_PER_HOUR +
362 2
            $diff->i) * static::SECONDS_PER_MINUTE +
363 2
            $diff->s;
364

365 2
        return $absolute || !$diff->invert ? $value : -$value;
366
    }
367

368
    /**
369
     * Get the difference in microseconds.
370
     *
371
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
372
     * @param bool                                                   $absolute Get the absolute of the difference
373
     *
374
     * @return int
375
     */
376 2
    public function diffInMicroseconds($date = null, $absolute = true)
377
    {
378 2
        $diff = $this->diff($date);
379 2
        $value = (int) round(((((($diff->m || $diff->y ? $diff->days : $diff->d) * static::HOURS_PER_DAY) +
380 2
            $diff->h) * static::MINUTES_PER_HOUR +
381 2
            $diff->i) * static::SECONDS_PER_MINUTE +
382 2
            ($diff->f + $diff->s)) * static::MICROSECONDS_PER_SECOND);
383

384 2
        return $absolute || !$diff->invert ? $value : -$value;
385
    }
386

387
    /**
388
     * Get the difference in milliseconds rounded down.
389
     *
390
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
391
     * @param bool                                                   $absolute Get the absolute of the difference
392
     *
393
     * @return int
394
     */
395 2
    public function diffInMilliseconds($date = null, $absolute = true)
396
    {
397 2
        return (int) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
398
    }
399

400
    /**
401
     * Get the difference in seconds using timestamps.
402
     *
403
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
404
     * @param bool                                                   $absolute Get the absolute of the difference
405
     *
406
     * @return int
407
     */
408 2
    public function diffInRealSeconds($date = null, $absolute = true)
409
    {
410
        /** @var CarbonInterface $date */
411 2
        $date = $this->resolveCarbon($date);
412 2
        $value = $date->getTimestamp() - $this->getTimestamp();
413

414 2
        return $absolute ? abs($value) : $value;
415
    }
416

417
    /**
418
     * Get the difference in microseconds using timestamps.
419
     *
420
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
421
     * @param bool                                                   $absolute Get the absolute of the difference
422
     *
423
     * @return int
424
     */
425 2
    public function diffInRealMicroseconds($date = null, $absolute = true)
426
    {
427
        /** @var CarbonInterface $date */
428 2
        $date = $this->resolveCarbon($date);
429 2
        $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND +
430 2
            $date->micro - $this->micro;
431

432 2
        return $absolute ? abs($value) : $value;
433
    }
434

435
    /**
436
     * Get the difference in milliseconds rounded down using timestamps.
437
     *
438
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
439
     * @param bool                                                   $absolute Get the absolute of the difference
440
     *
441
     * @return int
442
     */
443 2
    public function diffInRealMilliseconds($date = null, $absolute = true)
444
    {
445 2
        return (int) ($this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
446
    }
447

448
    /**
449
     * Get the difference in seconds as float (microsecond-precision).
450
     *
451
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
452
     * @param bool                                                   $absolute Get the absolute of the difference
453
     *
454
     * @return float
455
     */
456 2
    public function floatDiffInSeconds($date = null, $absolute = true)
457
    {
458 2
        return $this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND;
459
    }
460

461
    /**
462
     * Get the difference in minutes as float (microsecond-precision).
463
     *
464
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
465
     * @param bool                                                   $absolute Get the absolute of the difference
466
     *
467
     * @return float
468
     */
469 2
    public function floatDiffInMinutes($date = null, $absolute = true)
470
    {
471 2
        return $this->floatDiffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
472
    }
473

474
    /**
475
     * Get the difference in hours as float (microsecond-precision).
476
     *
477
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
478
     * @param bool                                                   $absolute Get the absolute of the difference
479
     *
480
     * @return float
481
     */
482 2
    public function floatDiffInHours($date = null, $absolute = true)
483
    {
484 2
        return $this->floatDiffInMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
485
    }
486

487
    /**
488
     * Get the difference in days as float (microsecond-precision).
489
     *
490
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
491
     * @param bool                                                   $absolute Get the absolute of the difference
492
     *
493
     * @return float
494
     */
495 2
    public function floatDiffInDays($date = null, $absolute = true)
496
    {
497 2
        $hoursDiff = $this->floatDiffInHours($date, $absolute);
498 2
        $interval = $this->diff($date, $absolute);
499

500 2
        if ($interval->y === 0 && $interval->m === 0 && $interval->d === 0) {
501 2
            return $hoursDiff / static::HOURS_PER_DAY;
502
        }
503

504 2
        $daysDiff = (int) $interval->format('%r%a');
505

506 2
        return $daysDiff + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
507
    }
508

509
    /**
510
     * Get the difference in weeks as float (microsecond-precision).
511
     *
512
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
513
     * @param bool                                                   $absolute Get the absolute of the difference
514
     *
515
     * @return float
516
     */
517 2
    public function floatDiffInWeeks($date = null, $absolute = true)
518
    {
519 2
        return $this->floatDiffInDays($date, $absolute) / static::DAYS_PER_WEEK;
520
    }
521

522
    /**
523
     * Get the difference in months as float (microsecond-precision).
524
     *
525
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
526
     * @param bool                                                   $absolute Get the absolute of the difference
527
     *
528
     * @return float
529
     */
530 2
    public function floatDiffInMonths($date = null, $absolute = true)
531
    {
532 2
        $start = $this;
533 2
        $end = $this->resolveCarbon($date);
534 2
        $ascending = ($start <= $end);
535 2
        $sign = $absolute || $ascending ? 1 : -1;
536 2
        if (!$ascending) {
537 2
            [$start, $end] = [$end, $start];
538
        }
539 2
        $monthsDiff = $start->diffInMonths($end);
540
        /** @var Carbon|CarbonImmutable $floorEnd */
541 2
        $floorEnd = $start->copy()->addMonths($monthsDiff);
542

543 2
        if ($floorEnd >= $end) {
544 2
            return $sign * $monthsDiff;
545
        }
546

547
        /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
548 2
        $startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
549

550 2
        if ($startOfMonthAfterFloorEnd > $end) {
551 2
            return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInMonth);
552
        }
553

554 2
        return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInDays($end) / $end->daysInMonth);
555
    }
556

557
    /**
558
     * Get the difference in year as float (microsecond-precision).
559
     *
560
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
561
     * @param bool                                                   $absolute Get the absolute of the difference
562
     *
563
     * @return float
564
     */
565 2
    public function floatDiffInYears($date = null, $absolute = true)
566
    {
567 2
        $start = $this;
568 2
        $end = $this->resolveCarbon($date);
569 2
        $ascending = ($start <= $end);
570 2
        $sign = $absolute || $ascending ? 1 : -1;
571 2
        if (!$ascending) {
572 2
            [$start, $end] = [$end, $start];
573
        }
574 2
        $yearsDiff = $start->diffInYears($end);
575
        /** @var Carbon|CarbonImmutable $floorEnd */
576 2
        $floorEnd = $start->copy()->addYears($yearsDiff);
577

578 2
        if ($floorEnd >= $end) {
579 2
            return $sign * $yearsDiff;
580
        }
581

582
        /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
583 2
        $startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
584

585 2
        if ($startOfYearAfterFloorEnd > $end) {
586 2
            return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInYear);
587
        }
588

589 2
        return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInDays($end) / $end->daysInYear);
590
    }
591

592
    /**
593
     * Get the difference in seconds as float (microsecond-precision) using timestamps.
594
     *
595
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
596
     * @param bool                                                   $absolute Get the absolute of the difference
597
     *
598
     * @return float
599
     */
600 2
    public function floatDiffInRealSeconds($date = null, $absolute = true)
601
    {
602 2
        return $this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND;
603
    }
604

605
    /**
606
     * Get the difference in minutes as float (microsecond-precision) using timestamps.
607
     *
608
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
609
     * @param bool                                                   $absolute Get the absolute of the difference
610
     *
611
     * @return float
612
     */
613 2
    public function floatDiffInRealMinutes($date = null, $absolute = true)
614
    {
615 2
        return $this->floatDiffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
616
    }
617

618
    /**
619
     * Get the difference in hours as float (microsecond-precision) using timestamps.
620
     *
621
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
622
     * @param bool                                                   $absolute Get the absolute of the difference
623
     *
624
     * @return float
625
     */
626 2
    public function floatDiffInRealHours($date = null, $absolute = true)
627
    {
628 2
        return $this->floatDiffInRealMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
629
    }
630

631
    /**
632
     * Get the difference in days as float (microsecond-precision).
633
     *
634
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
635
     * @param bool                                                   $absolute Get the absolute of the difference
636
     *
637
     * @return float
638
     */
639 2
    public function floatDiffInRealDays($date = null, $absolute = true)
640
    {
641 2
        $hoursDiff = $this->floatDiffInRealHours($date, $absolute);
642

643 2
        return ($hoursDiff < 0 ? -1 : 1) * $this->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
644
    }
645

646
    /**
647
     * Get the difference in weeks as float (microsecond-precision).
648
     *
649
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
650
     * @param bool                                                   $absolute Get the absolute of the difference
651
     *
652
     * @return float
653
     */
654 2
    public function floatDiffInRealWeeks($date = null, $absolute = true)
655
    {
656 2
        return $this->floatDiffInRealDays($date, $absolute) / static::DAYS_PER_WEEK;
657
    }
658

659
    /**
660
     * Get the difference in months as float (microsecond-precision) using timestamps.
661
     *
662
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
663
     * @param bool                                                   $absolute Get the absolute of the difference
664
     *
665
     * @return float
666
     */
667 2
    public function floatDiffInRealMonths($date = null, $absolute = true)
668
    {
669 2
        $start = $this;
670 2
        $end = $this->resolveCarbon($date);
671 2
        $ascending = ($start <= $end);
672 2
        $sign = $absolute || $ascending ? 1 : -1;
673 2
        if (!$ascending) {
674 2
            [$start, $end] = [$end, $start];
675
        }
676 2
        $monthsDiff = $start->diffInMonths($end);
677
        /** @var Carbon|CarbonImmutable $floorEnd */
678 2
        $floorEnd = $start->copy()->addMonths($monthsDiff);
679

680 2
        if ($floorEnd >= $end) {
681 2
            return $sign * $monthsDiff;
682
        }
683

684
        /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
685 2
        $startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
686

687 2
        if ($startOfMonthAfterFloorEnd > $end) {
688 2
            return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInMonth);
689
        }
690

691 2
        return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInMonth);
692
    }
693

694
    /**
695
     * Get the difference in year as float (microsecond-precision) using timestamps.
696
     *
697
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
698
     * @param bool                                                   $absolute Get the absolute of the difference
699
     *
700
     * @return float
701
     */
702 2
    public function floatDiffInRealYears($date = null, $absolute = true)
703
    {
704 2
        $start = $this;
705 2
        $end = $this->resolveCarbon($date);
706 2
        $ascending = ($start <= $end);
707 2
        $sign = $absolute || $ascending ? 1 : -1;
708 2
        if (!$ascending) {
709 2
            [$start, $end] = [$end, $start];
710
        }
711 2
        $yearsDiff = $start->diffInYears($end);
712
        /** @var Carbon|CarbonImmutable $floorEnd */
713 2
        $floorEnd = $start->copy()->addYears($yearsDiff);
714

715 2
        if ($floorEnd >= $end) {
716 2
            return $sign * $yearsDiff;
717
        }
718

719
        /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
720 2
        $startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
721

722 2
        if ($startOfYearAfterFloorEnd > $end) {
723 2
            return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInYear);
724
        }
725

726 2
        return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInYear);
727
    }
728

729
    /**
730
     * The number of seconds since midnight.
731
     *
732
     * @return int
733
     */
734 2
    public function secondsSinceMidnight()
735
    {
736 2
        return $this->diffInSeconds($this->copy()->startOfDay());
737
    }
738

739
    /**
740
     * The number of seconds until 23:59:59.
741
     *
742
     * @return int
743
     */
744 2
    public function secondsUntilEndOfDay()
745
    {
746 2
        return $this->diffInSeconds($this->copy()->endOfDay());
747
    }
748

749
    /**
750
     * Get the difference in a human readable format in the current locale from current instance to an other
751
     * instance given (or now if null given).
752
     *
753
     * @example
754
     * ```
755
     * echo Carbon::tomorrow()->diffForHumans() . "\n";
756
     * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
757
     * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
758
     * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
759
     * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
760
     * ```
761
     *
762
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
763
     *                                                             if null passed, now will be used as comparison reference;
764
     *                                                             if any other type, it will be converted to date and used as reference.
765
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
766
     *                                                             - 'syntax' entry (see below)
767
     *                                                             - 'short' entry (see below)
768
     *                                                             - 'parts' entry (see below)
769
     *                                                             - 'options' entry (see below)
770
     *                                                             - 'join' entry determines how to join multiple parts of the string
771
     *                                                             `  - if $join is a string, it's used as a joiner glue
772
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
773
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
774
     *                                                             `    will be used instead of the glue for the last item
775
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
776
     *                                                             `  - if $join is missing, a space will be used as glue
777
     *                                                             - 'other' entry (see above)
778
     *                                                             if int passed, it add modifiers:
779
     *                                                             Possible values:
780
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
781
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
782
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
783
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
784
     * @param bool                                        $short   displays short format of time units
785
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
786
     * @param int                                         $options human diff options
787
     *
788
     * @return string
789
     */
790 2
    public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
791
    {
792
        /* @var CarbonInterface $this */
793 2
        if (\is_array($other)) {
794 2
            $other['syntax'] = \array_key_exists('syntax', $other) ? $other['syntax'] : $syntax;
795 2
            $syntax = $other;
796 2
            $other = $syntax['other'] ?? null;
797
        }
798

799 2
        $intSyntax = &$syntax;
800 2
        if (\is_array($syntax)) {
801 2
            $syntax['syntax'] = $syntax['syntax'] ?? null;
802 2
            $intSyntax = &$syntax['syntax'];
803
        }
804 2
        $intSyntax = (int) ($intSyntax === null ? static::DIFF_RELATIVE_AUTO : $intSyntax);
805 2
        $intSyntax = $intSyntax === static::DIFF_RELATIVE_AUTO && $other === null ? static::DIFF_RELATIVE_TO_NOW : $intSyntax;
806

807 2
        $parts = min(7, max(1, (int) $parts));
808

809 2
        return $this->diffAsCarbonInterval($other, false)
810 2
            ->setLocalTranslator($this->getLocalTranslator())
811 2
            ->forHumans($syntax, (bool) $short, $parts, $options ?? $this->localHumanDiffOptions ?? static::getHumanDiffOptions());
812
    }
813

814
    /**
815
     * @alias diffForHumans
816
     *
817
     * Get the difference in a human readable format in the current locale from current instance to an other
818
     * instance given (or now if null given).
819
     *
820
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
821
     *                                                             if null passed, now will be used as comparison reference;
822
     *                                                             if any other type, it will be converted to date and used as reference.
823
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
824
     *                                                             - 'syntax' entry (see below)
825
     *                                                             - 'short' entry (see below)
826
     *                                                             - 'parts' entry (see below)
827
     *                                                             - 'options' entry (see below)
828
     *                                                             - 'join' entry determines how to join multiple parts of the string
829
     *                                                             `  - if $join is a string, it's used as a joiner glue
830
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
831
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
832
     *                                                             `    will be used instead of the glue for the last item
833
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
834
     *                                                             `  - if $join is missing, a space will be used as glue
835
     *                                                             - 'other' entry (see above)
836
     *                                                             if int passed, it add modifiers:
837
     *                                                             Possible values:
838
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
839
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
840
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
841
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
842
     * @param bool                                        $short   displays short format of time units
843
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
844
     * @param int                                         $options human diff options
845
     *
846
     * @return string
847
     */
848 2
    public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
849
    {
850 2
        return $this->diffForHumans($other, $syntax, $short, $parts, $options);
851
    }
852

853
    /**
854
     * @alias diffForHumans
855
     *
856
     * Get the difference in a human readable format in the current locale from current instance to an other
857
     * instance given (or now if null given).
858
     */
859 2
    public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
860
    {
861 2
        return $this->diffForHumans($other, $syntax, $short, $parts, $options);
862
    }
863

864
    /**
865
     * Get the difference in a human readable format in the current locale from an other
866
     * instance given (or now if null given) to current instance.
867
     *
868
     * When comparing a value in the past to default now:
869
     * 1 hour from now
870
     * 5 months from now
871
     *
872
     * When comparing a value in the future to default now:
873
     * 1 hour ago
874
     * 5 months ago
875
     *
876
     * When comparing a value in the past to another value:
877
     * 1 hour after
878
     * 5 months after
879
     *
880
     * When comparing a value in the future to another value:
881
     * 1 hour before
882
     * 5 months before
883
     *
884
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
885
     *                                                             if null passed, now will be used as comparison reference;
886
     *                                                             if any other type, it will be converted to date and used as reference.
887
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
888
     *                                                             - 'syntax' entry (see below)
889
     *                                                             - 'short' entry (see below)
890
     *                                                             - 'parts' entry (see below)
891
     *                                                             - 'options' entry (see below)
892
     *                                                             - 'join' entry determines how to join multiple parts of the string
893
     *                                                             `  - if $join is a string, it's used as a joiner glue
894
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
895
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
896
     *                                                             `    will be used instead of the glue for the last item
897
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
898
     *                                                             `  - if $join is missing, a space will be used as glue
899
     *                                                             - 'other' entry (see above)
900
     *                                                             if int passed, it add modifiers:
901
     *                                                             Possible values:
902
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
903
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
904
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
905
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
906
     * @param bool                                        $short   displays short format of time units
907
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
908
     * @param int                                         $options human diff options
909
     *
910
     * @return string
911
     */
912 2
    public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
913
    {
914 2
        if (!$syntax && !$other) {
915 2
            $syntax = CarbonInterface::DIFF_RELATIVE_TO_NOW;
916
        }
917

918 2
        return $this->resolveCarbon($other)->diffForHumans($this, $syntax, $short, $parts, $options);
919
    }
920

921
    /**
922
     * @alias to
923
     *
924
     * Get the difference in a human readable format in the current locale from an other
925
     * instance given (or now if null given) to current instance.
926
     *
927
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
928
     *                                                             if null passed, now will be used as comparison reference;
929
     *                                                             if any other type, it will be converted to date and used as reference.
930
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
931
     *                                                             - 'syntax' entry (see below)
932
     *                                                             - 'short' entry (see below)
933
     *                                                             - 'parts' entry (see below)
934
     *                                                             - 'options' entry (see below)
935
     *                                                             - 'join' entry determines how to join multiple parts of the string
936
     *                                                             `  - if $join is a string, it's used as a joiner glue
937
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
938
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
939
     *                                                             `    will be used instead of the glue for the last item
940
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
941
     *                                                             `  - if $join is missing, a space will be used as glue
942
     *                                                             - 'other' entry (see above)
943
     *                                                             if int passed, it add modifiers:
944
     *                                                             Possible values:
945
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
946
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
947
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
948
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
949
     * @param bool                                        $short   displays short format of time units
950
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
951
     * @param int                                         $options human diff options
952
     *
953
     * @return string
954
     */
955 2
    public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
956
    {
957 2
        return $this->to($other, $syntax, $short, $parts, $options);
958
    }
959

960
    /**
961
     * Get the difference in a human readable format in the current locale from current
962
     * instance to now.
963
     *
964
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
965
     *                           - 'syntax' entry (see below)
966
     *                           - 'short' entry (see below)
967
     *                           - 'parts' entry (see below)
968
     *                           - 'options' entry (see below)
969
     *                           - 'join' entry determines how to join multiple parts of the string
970
     *                           `  - if $join is a string, it's used as a joiner glue
971
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
972
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
973
     *                           `    will be used instead of the glue for the last item
974
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
975
     *                           `  - if $join is missing, a space will be used as glue
976
     *                           if int passed, it add modifiers:
977
     *                           Possible values:
978
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
979
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
980
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
981
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
982
     * @param bool      $short   displays short format of time units
983
     * @param int       $parts   maximum number of parts to display (default value: 1: single unit)
984
     * @param int       $options human diff options
985
     *
986
     * @return string
987
     */
988 2
    public function fromNow($syntax = null, $short = false, $parts = 1, $options = null)
989
    {
990 2
        $other = null;
991

992 2
        if ($syntax instanceof DateTimeInterface) {
993 2
            [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null);
994
        }
995

996 2
        return $this->from($other, $syntax, $short, $parts, $options);
997
    }
998

999
    /**
1000
     * Get the difference in a human readable format in the current locale from an other
1001
     * instance given to now
1002
     *
1003
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
1004
     *                           - 'syntax' entry (see below)
1005
     *                           - 'short' entry (see below)
1006
     *                           - 'parts' entry (see below)
1007
     *                           - 'options' entry (see below)
1008
     *                           - 'join' entry determines how to join multiple parts of the string
1009
     *                           `  - if $join is a string, it's used as a joiner glue
1010
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
1011
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
1012
     *                           `    will be used instead of the glue for the last item
1013
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
1014
     *                           `  - if $join is missing, a space will be used as glue
1015
     *                           if int passed, it add modifiers:
1016
     *                           Possible values:
1017
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
1018
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
1019
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
1020
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
1021
     * @param bool      $short   displays short format of time units
1022
     * @param int       $parts   maximum number of parts to display (default value: 1: single part)
1023
     * @param int       $options human diff options
1024
     *
1025
     * @return string
1026
     */
1027 2
    public function toNow($syntax = null, $short = false, $parts = 1, $options = null)
1028
    {
1029 2
        return $this->to(null, $syntax, $short, $parts, $options);
1030
    }
1031

1032
    /**
1033
     * Get the difference in a human readable format in the current locale from an other
1034
     * instance given to now
1035
     *
1036
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
1037
     *                           - 'syntax' entry (see below)
1038
     *                           - 'short' entry (see below)
1039
     *                           - 'parts' entry (see below)
1040
     *                           - 'options' entry (see below)
1041
     *                           - 'join' entry determines how to join multiple parts of the string
1042
     *                           `  - if $join is a string, it's used as a joiner glue
1043
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
1044
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
1045
     *                           `    will be used instead of the glue for the last item
1046
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
1047
     *                           `  - if $join is missing, a space will be used as glue
1048
     *                           if int passed, it add modifiers:
1049
     *                           Possible values:
1050
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
1051
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
1052
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
1053
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
1054
     * @param bool      $short   displays short format of time units
1055
     * @param int       $parts   maximum number of parts to display (default value: 1: single part)
1056
     * @param int       $options human diff options
1057
     *
1058
     * @return string
1059
     */
1060 2
    public function ago($syntax = null, $short = false, $parts = 1, $options = null)
1061
    {
1062 2
        $other = null;
1063

1064 2
        if ($syntax instanceof DateTimeInterface) {
1065 2
            [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null);
1066
        }
1067

1068 2
        return $this->from($other, $syntax, $short, $parts, $options);
1069
    }
1070

1071
    /**
1072
     * Get the difference in a human readable format in the current locale from current instance to an other
1073
     * instance given (or now if null given).
1074
     *
1075
     * @return string
1076
     */
1077 2
    public function timespan($other = null, $timezone = null)
1078
    {
1079 2
        if (!$other instanceof DateTimeInterface) {
1080 2
            $other = static::parse($other, $timezone);
1081
        }
1082

1083 2
        return $this->diffForHumans($other, [
1084 2
            'join' => ', ',
1085
            'syntax' => CarbonInterface::DIFF_ABSOLUTE,
1086
            'options' => CarbonInterface::NO_ZERO_DIFF,
1087
            'parts' => -1,
1088
        ]);
1089
    }
1090

1091
    /**
1092
     * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days,
1093
     * or a calendar date (e.g. "10/29/2017") otherwise.
1094
     *
1095
     * Language, date and time formats will change according to the current locale.
1096
     *
1097
     * @param Carbon|\DateTimeInterface|string|null $referenceTime
1098
     * @param array                                 $formats
1099
     *
1100
     * @return string
1101
     */
1102 2
    public function calendar($referenceTime = null, array $formats = [])
1103
    {
1104
        /** @var CarbonInterface $current */
1105 2
        $current = $this->copy()->startOfDay();
1106
        /** @var CarbonInterface $other */
1107 2
        $other = $this->resolveCarbon($referenceTime)->copy()->setTimezone($this->getTimezone())->startOfDay();
1108 2
        $diff = $other->diffInDays($current, false);
1109 2
        $format = $diff < -6 ? 'sameElse' : (
1110 2
            $diff < -1 ? 'lastWeek' : (
1111 2
                $diff < 0 ? 'lastDay' : (
1112 2
                    $diff < 1 ? 'sameDay' : (
1113 2
                        $diff < 2 ? 'nextDay' : (
1114 2
                            $diff < 7 ? 'nextWeek' : 'sameElse'
1115
                        )
1116
                    )
1117
                )
1118
            )
1119
        );
1120 2
        $format = array_merge($this->getCalendarFormats(), $formats)[$format];
1121 2
        if ($format instanceof Closure) {
1122 2
            $format = $format($current, $other) ?? '';
1123
        }
1124

1125 2
        return $this->isoFormat(\strval($format));
1126
    }
1127
}

Read our documentation on viewing source code .

Loading