Skip to content

Commit

Permalink
Deprecate Real diff in favor of UTC diff
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekatarnls committed Mar 22, 2024
1 parent 6b6383a commit a4c5703
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 26 deletions.
18 changes: 12 additions & 6 deletions src/Carbon/CarbonInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -1626,10 +1626,11 @@ public function diffForHumans($other = null, $syntax = null, $short = false, $pa
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInDays($date = null, bool $absolute = false): float;
public function diffInDays($date = null, bool $absolute = false, bool $utc = false): float;

/**
* Get the difference in days using a filter closure rounded down.
Expand Down Expand Up @@ -1698,20 +1699,22 @@ public function diffInMinutes($date = null, bool $absolute = false): float;
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInMonths($date = null, bool $absolute = false): float;
public function diffInMonths($date = null, bool $absolute = false, bool $utc = false): float;

/**
* Get the difference in quarters rounded down.
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInQuarters($date = null, bool $absolute = false): float;
public function diffInQuarters($date = null, bool $absolute = false, bool $utc = false): float;

/**
* Get the difference in seconds rounded down.
Expand All @@ -1729,10 +1732,11 @@ public function diffInSeconds($date = null, bool $absolute = false): float;
* century, millennium
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = false): float;
public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = false, bool $utc = false): float;

/**
* Get the difference in weekdays rounded down.
Expand All @@ -1759,20 +1763,22 @@ public function diffInWeekendDays($date = null, bool $absolute = false): int;
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInWeeks($date = null, bool $absolute = false): float;
public function diffInWeeks($date = null, bool $absolute = false, bool $utc = false): float;

/**
* Get the difference in years
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInYears($date = null, bool $absolute = false): float;
public function diffInYears($date = null, bool $absolute = false, bool $utc = false): float;

/**
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
Expand Down
2 changes: 1 addition & 1 deletion src/Carbon/CarbonInterval.php
Original file line number Diff line number Diff line change
Expand Up @@ -3184,7 +3184,7 @@ private function checkIntegerValue(string $name, mixed $value): void
"From 3.0.0, decimal part will no longer be truncated and will be cascaded to smaller units.\n".
"- To maintain the current behavior, use explicit cast: $name((int) \$value)\n".
"- To adopt the new behavior globally, call CarbonInterval::enableFloatSetters()\n",
\E_USER_DEPRECATED
\E_USER_DEPRECATED,
);
}
}
Expand Down
25 changes: 23 additions & 2 deletions src/Carbon/Traits/Date.php
Original file line number Diff line number Diff line change
Expand Up @@ -2592,8 +2592,29 @@ public static function sleep(int|float $seconds): void
*/
public function __call(string $method, array $parameters): mixed
{
if (preg_match('/^(?:diff|floatDiff)In(?:Real)?(.+)$/', $method, $match)) {
$method = 'diffIn'.$match[1];
if (preg_match('/^(diff|floatDiff)In(Real|UTC|Utc)?(.+)$/', $method, $match)) {
$mode = strtoupper($match[2] ?? '');
$betterMethod = $match[1] === 'floatDiff' ? str_replace('floatDiff', 'diff', $method) : null;

if ($mode === 'REAL') {
$mode = 'UTC';
$betterMethod = str_replace($match[1], 'UTC', $betterMethod ?? $method);
}

if ($betterMethod) {
@trigger_error(
"Use the method $betterMethod instead to make it more explicit about what it does.\n".
'On next major version, "float" prefix will be removed (as all diff are now returning floating numbers)'.
' and "Real" methods will be removed in favor of "UTC" because what it actually does is to convert both'.
' dates to UTC timezone before comparison, while by default it does it only if both dates don\'t have'.
' exactly the same timezone (Note: 2 timezones with the same offset but different names are considered'.
' different as it\'s not safe to assume they will always have the same offset).',
\E_USER_DEPRECATED,
);
}

$method = 'diffIn'.$match[3];
$parameters['utc'] = ($mode === 'UTC');

if (method_exists($this, $method)) {
return $this->$method(...$parameters);
Expand Down
54 changes: 37 additions & 17 deletions src/Carbon/Traits/Difference.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ public function diff($date = null, bool $absolute = false, array $skip = []): Ca
* century, millennium
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = false): float
public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = false, bool $utc = false): float
{
$unit = static::pluralUnit($unit instanceof Unit ? $unit->value : rtrim($unit, 'z'));
$method = 'diffIn'.$unit;
Expand All @@ -111,26 +112,35 @@ public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = fal
throw new UnknownUnitException($unit);
}

return $this->$method($date, $absolute);
return $this->$method($date, $absolute, $utc);
}

/**
* Get the difference in years
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInYears($date = null, bool $absolute = false): float
public function diffInYears($date = null, bool $absolute = false, bool $utc = false): float
{
$start = $this;
$end = $this->resolveCarbon($date);

if ($utc) {
$start = $start->avoidMutation()->utc();
$end = $end->avoidMutation()->utc();
}

$ascending = ($start <= $end);
$sign = $absolute || $ascending ? 1 : -1;

if (!$ascending) {
[$start, $end] = [$end, $start];
}

$yearsDiff = (int) $start->diff($end, $absolute)->format('%r%y');
/** @var Carbon|CarbonImmutable $floorEnd */
$floorEnd = $start->copy()->addYears($yearsDiff);
Expand All @@ -154,26 +164,34 @@ public function diffInYears($date = null, bool $absolute = false): float
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInQuarters($date = null, bool $absolute = false): float
public function diffInQuarters($date = null, bool $absolute = false, bool $utc = false): float
{
return $this->diffInMonths($date, $absolute) / static::MONTHS_PER_QUARTER;
return $this->diffInMonths($date, $absolute, $utc) / static::MONTHS_PER_QUARTER;
}

/**
* Get the difference in months rounded down.
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInMonths($date = null, bool $absolute = false): float
public function diffInMonths($date = null, bool $absolute = false, bool $utc = false): float
{
$start = $this;
$end = $this->resolveCarbon($date)->avoidMutation()->setTimezone($this->tz);
$end = $this->resolveCarbon($date);
$compareUsingUtc = $utc || ($end->timezoneName !== $start->timezoneName);

if ($compareUsingUtc) {
$start = $start->avoidMutation()->utc();
$end = $end->avoidMutation()->utc();
}

[$yearStart, $monthStart, $dayStart] = explode('-', $start->format('Y-m-dHisu'));
[$yearEnd, $monthEnd, $dayEnd] = explode('-', $end->format('Y-m-dHisu'));
Expand All @@ -196,14 +214,14 @@ public function diffInMonths($date = null, bool $absolute = false): float
}

/** @var Carbon|CarbonImmutable $floorEnd */
$floorEnd = $start->copy()->addMonths($monthsDiff);
$floorEnd = $start->avoidMutation()->addMonths($monthsDiff);

if ($floorEnd >= $end) {
return $sign * $monthsDiff;
}

/** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
$startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonthNoOverflow()->startOfMonth();
$startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonthNoOverflow()->startOfMonth();

if ($startOfMonthAfterFloorEnd > $end) {
return $sign * ($monthsDiff + $floorEnd->diffInDays($end) / $floorEnd->daysInMonth);
Expand All @@ -217,36 +235,38 @@ public function diffInMonths($date = null, bool $absolute = false): float
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInWeeks($date = null, bool $absolute = false): float
public function diffInWeeks($date = null, bool $absolute = false, bool $utc = false): float
{
return $this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK;
return $this->diffInDays($date, $absolute, $utc) / static::DAYS_PER_WEEK;
}

/**
* Get the difference in days rounded down.
*
* @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
* @param bool $absolute Get the absolute of the difference
* @param bool $utc Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
*
* @return float
*/
public function diffInDays($date = null, bool $absolute = false): float
public function diffInDays($date = null, bool $absolute = false, bool $utc = false): float
{
$date = $this->resolveCarbon($date);
$current = $this;
$sameTimezone = ($date->timezoneName === $current->timezoneName);
$compareUsingUtc = $utc || ($date->timezoneName !== $current->timezoneName);

if (!$sameTimezone) {
$date = $date->copy()->utc();
$current = $current->copy()->utc();
if ($compareUsingUtc) {
$date = $date->avoidMutation()->utc();
$current = $current->avoidMutation()->utc();
}

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

if ($sameTimezone) {
if (!$compareUsingUtc) {
$minutes = $interval->i + ($interval->s + $interval->f) / static::SECONDS_PER_MINUTE;
$hours = $interval->h + $minutes / static::MINUTES_PER_HOUR;

Expand Down

0 comments on commit a4c5703

Please sign in to comment.