Skip to content

Commit

Permalink
Merge pull request #402 from cakephp/interval-rollover
Browse files Browse the repository at this point in the history
Add rollover from microseconds to days in createInterval()
  • Loading branch information
dereuromark committed Jul 7, 2023
2 parents 9709794 + 555f274 commit 98911ff
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/Chronos.php
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,18 @@ public static function createInterval(
): DateInterval {
$spec = 'P';

$rollover = static::rolloverTime($microseconds, 1_000_000);
$seconds = $seconds === null ? $rollover : $seconds + (int)$rollover;

$rollover = static::rolloverTime($seconds, 60);
$minutes = $minutes === null ? $rollover : $minutes + (int)$rollover;

$rollover = static::rolloverTime($minutes, 60);
$hours = $hours === null ? $rollover : $hours + (int)$rollover;

$rollover = static::rolloverTime($hours, 24);
$days = $days === null ? $rollover : $days + (int)$rollover;

if ($years) {
$spec .= $years . 'Y';
}
Expand All @@ -797,6 +809,7 @@ public static function createInterval(

if ($hours || $minutes || $seconds) {
$spec .= 'T';

if ($hours) {
$spec .= $hours . 'H';
}
Expand All @@ -821,6 +834,26 @@ public static function createInterval(
return $instance;
}

/**
* Updates value to remaininger and returns rollover value for time
* unit or null if no rollover.
*
* @param int|null $value Time unit value
* @param int $max Time unit max value
* @return int|null
*/
protected static function rolloverTime(?int &$value, int $max): ?int
{
if ($value === null || $value < $max) {
return null;
}

$rollover = intdiv($value, $max);
$value = $value % $max;

return $rollover;
}

/**
* Sets the date and time.
*
Expand Down
15 changes: 15 additions & 0 deletions tests/TestCase/DateTime/CreateIntervalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,19 @@ public function testCreateInterval(): void
$interval = Chronos::createInterval(microseconds: 2);
$this->assertDateInterval($interval, seconds: 0, microseconds: 0.000002);
}

public function testRollover(): void
{
$i = Chronos::createInterval(microseconds: 1);
$this->assertDateInterval($i, days: 0, hours: 0, minutes: 0, seconds: 0, microseconds: 0.000001);

$i = Chronos::createInterval(days: 1, hours: 25, minutes: 61, seconds: 61, microseconds: 1_000_001);
$this->assertDateInterval($i, days: 2, hours: 2, minutes: 2, seconds: 2, microseconds: 0.000001);

$i = Chronos::createInterval(days: null, hours: 25, minutes: null, seconds: null, microseconds: 1_000_001);
$this->assertDateInterval($i, days: 1, hours: 1, minutes: 0, seconds: 1, microseconds: 0.000001);

$i = Chronos::createInterval(days: null, hours: null, minutes: 61, seconds: null, microseconds: null);
$this->assertDateInterval($i, days: 0, hours: 1, minutes: 1, seconds: 0, microseconds: 0.0);
}
}

0 comments on commit 98911ff

Please sign in to comment.