Skip to content

Commit

Permalink
Optimize diffInDays
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekatarnls committed Aug 5, 2024
1 parent 0ea08e9 commit 0e42f93
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 23 deletions.
40 changes: 17 additions & 23 deletions src/Carbon/Traits/Difference.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ public function diffInMonths($date = null, bool $absolute = false, bool $utc = f
{
$start = $this;
$end = $this->resolveCarbon($date);
$compareUsingUtc = $utc || ($end->timezoneName !== $start->timezoneName);

if ($compareUsingUtc) {
// Compare using UTC
if ($utc || ($end->timezoneName !== $start->timezoneName)) {
$start = $start->avoidMutation()->utc();
$end = $end->avoidMutation()->utc();
}
Expand Down Expand Up @@ -255,32 +255,26 @@ public function diffInDays($date = null, bool $absolute = false, bool $utc = fal
{
$date = $this->resolveCarbon($date);
$current = $this;
$compareUsingUtc = $utc || ($date->timezoneName !== $current->timezoneName);

if ($compareUsingUtc) {
// Compare using UTC
if ($utc || ($date->timezoneName !== $current->timezoneName)) {
$date = $date->avoidMutation()->utc();
$current = $current->avoidMutation()->utc();
}

$interval = $current->diffAsDateInterval($date, $absolute);

if (!$compareUsingUtc) {
$minutes = $interval->i + ($interval->s + $interval->f) / static::SECONDS_PER_MINUTE;
// 24 hours means there is a DST bug
$hours = ($interval->h === 24 && $interval->days !== false ? 0 : $interval->h) + $minutes / static::MINUTES_PER_HOUR;

return $this->getIntervalDayDiff($interval)
+ ($interval->invert ? -$hours : $hours) / static::HOURS_PER_DAY;
}

$hoursDiff = $current->diffInHours($date, $absolute);

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

return $this->getIntervalDayDiff($interval)
+ fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
$negative = ($date < $current);
[$start, $end] = $negative ? [$date, $current] : [$current, $date];
$interval = $start->diffAsDateInterval($end);
$daysA = $this->getIntervalDayDiff($interval);
$floorEnd = $start->avoidMutation()->addDays($daysA);
$daysB = $daysA + ($floorEnd <= $end ? 1 : -1);
$ceilEnd = $start->avoidMutation()->addDays($daysB);
$microsecondsBetween = $floorEnd->diffInMicroseconds($ceilEnd);
$microsecondsToEnd = $floorEnd->diffInMicroseconds($end);

return ($negative && !$absolute ? -1 : 1)
* ($daysA * ($microsecondsBetween - $microsecondsToEnd) + $daysB * $microsecondsToEnd)
/ $microsecondsBetween;
}

/**
Expand Down
11 changes: 11 additions & 0 deletions tests/Carbon/DiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2198,6 +2198,17 @@ public function testBigGapInDays()
$end = Carbon::parse('2027-05-02 01:24:22.848816', 'America/Toronto');

$this->assertSame(-1281.0, $start->diffInDays($end));

$start = Carbon::parse('2030-11-03 01:24:22.848811', 'America/Toronto');
$end = Carbon::parse('2027-05-02 01:24:22.848816', 'America/Toronto');

$this->assertVeryClose(-1280.999999999942, $start->diffInDays($end));

$start = Carbon::parse('2024-11-03 00:24:22.848816', 'America/Toronto');
$end = Carbon::parse('2024-11-03 23:24:22.848816', 'America/Toronto');

// November 3rd is a 25-hours day in Toronto because of the DST
$this->assertVeryClose(24 / 25, $start->diffInDays($end));
}

public function testAFormat()
Expand Down

0 comments on commit 0e42f93

Please sign in to comment.