Skip to content

Commit

Permalink
Merge pull request #2762 from kylekatarnls/feature/round-with-cascade…
Browse files Browse the repository at this point in the history
…-factor

Handle rounding with cascade factors
  • Loading branch information
kylekatarnls authored Jan 29, 2023
2 parents 077657b + 99d2881 commit 4967128
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/Carbon/CarbonInterval.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,12 @@ public function shiftTimezone($tzName)
*/
public static function getCascadeFactors()
{
return static::$cascadeFactors ?: [
return static::$cascadeFactors ?: static::getDefaultCascadeFactors();
}

protected static function getDefaultCascadeFactors(): array
{
return [
'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
Expand Down Expand Up @@ -2720,6 +2725,15 @@ public function isBetween($interval1, $interval2, $equal = true): bool
*/
public function roundUnit($unit, $precision = 1, $function = 'round')
{
if (static::getCascadeFactors() !== static::getDefaultCascadeFactors()) {
$value = $function($this->total($unit) / $precision) * $precision;
$inverted = $value < 0;

return $this->copyProperties(self::fromString(
number_format(abs($value), 12, '.', '').' '.$unit
)->invert($inverted)->cascade());
}

$base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC')
->roundUnit($unit, $precision, $function);
$next = $base->add($this);
Expand Down
47 changes: 47 additions & 0 deletions tests/CarbonInterval/RoundingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,53 @@ public function testTotalAfterRound()
$this->assertSame(43.05, CarbonInterval::make('43h3m6s')->roundMinutes()->totalHours);
}

public function testWithCascadeFactors()
{
$cascades = CarbonInterval::getCascadeFactors();
CarbonInterval::setCascadeFactors([
'millisecond' => [1000, 'microseconds'],
'second' => [1000, 'milliseconds'],
'minute' => [60, 'seconds'],
'hour' => [60, 'minutes'],
]);

$this->assertEqualsWithDelta(
43.166666666666664,
CarbonInterval::make('43h3m6s')
->ceilMinutes(10)
->totalHours,
0.00000001
);
$this->assertSame(
43,
CarbonInterval::make('43h3m6s')
->floorMinutes(6)
->totalHours
);
$this->assertSame(
43.05,
CarbonInterval::make('43h3m6s')
->roundMinutes()
->totalHours
);
$this->assertEqualsWithDelta(
43.05833333333333,
CarbonInterval::make('43h3m26s')
->roundMinutes(0.5)
->totalHours,
0.00000001
);
$this->assertSame(
-43.05,
CarbonInterval::make('43h3m6s')
->invert()
->roundMinutes(0.5)
->totalHours
);

CarbonInterval::setCascadeFactors($cascades);
}

public function testCeil()
{
$this->assertSame(21, CarbonInterval::days(21)->ceilWeeks()->totalDays);
Expand Down

0 comments on commit 4967128

Please sign in to comment.