From b56746ab663ba5baa464e8ae1cc207c922d928cf Mon Sep 17 00:00:00 2001 From: Corey Taylor Date: Fri, 7 Jul 2023 02:38:59 -0500 Subject: [PATCH] Add rollover from microseconds to days in createInterval() --- src/Chronos.php | 25 +++++++++++++++++++ .../TestCase/DateTime/CreateIntervalTest.php | 15 +++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/Chronos.php b/src/Chronos.php index e9002e7d..52cd9f83 100644 --- a/src/Chronos.php +++ b/src/Chronos.php @@ -802,6 +802,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'; } @@ -817,6 +829,7 @@ public static function createInterval( if ($hours || $minutes || $seconds) { $spec .= 'T'; + if ($hours) { $spec .= $hours . 'H'; } @@ -841,6 +854,18 @@ public static function createInterval( return $instance; } + 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. * diff --git a/tests/TestCase/DateTime/CreateIntervalTest.php b/tests/TestCase/DateTime/CreateIntervalTest.php index 133cca3b..d97cd1f5 100644 --- a/tests/TestCase/DateTime/CreateIntervalTest.php +++ b/tests/TestCase/DateTime/CreateIntervalTest.php @@ -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); + } }