diff --git a/src/Instant.php b/src/Instant.php index 1da4465..49238bd 100644 --- a/src/Instant.php +++ b/src/Instant.php @@ -333,6 +333,16 @@ public function atTimeZone(TimeZone $timeZone): ZonedDateTime return ZonedDateTime::ofInstant($this, $timeZone); } + /** + * Returns an Interval from this Instant (inclusive) to the given one (exclusive). + * + * @throws DateTimeException If the given Instant is before this Instant. + */ + public function getIntervalTo(Instant $that): Interval + { + return Interval::of($this, $that); + } + /** * Returns a decimal representation of the timestamp represented by this instant. * diff --git a/src/ZonedDateTime.php b/src/ZonedDateTime.php index 18c2eeb..2ced2b0 100644 --- a/src/ZonedDateTime.php +++ b/src/ZonedDateTime.php @@ -435,6 +435,16 @@ public function plusDuration(Duration $duration): ZonedDateTime return ZonedDateTime::ofInstant($this->instant->plus($duration), $this->timeZone); } + /** + * Returns an Interval from this ZonedDateTime (inclusive) to the given one (exclusive). + * + * @throws DateTimeException If the given ZonedDateTime is before this ZonedDateTime. + */ + public function getIntervalTo(ZonedDateTime $that): Interval + { + return $this->getInstant()->getIntervalTo($that->getInstant()); + } + /** * Returns a Duration representing the time elapsed between this ZonedDateTime and the given one. * This method will return a negative duration if the given ZonedDateTime is before the current one. diff --git a/tests/InstantTest.php b/tests/InstantTest.php index 7d5844d..c5273ab 100644 --- a/tests/InstantTest.php +++ b/tests/InstantTest.php @@ -583,6 +583,27 @@ public function providerIsBetweenInclusive(): array ]; } + /** + * @dataProvider providerGetIntervalTo + */ + public function testGetIntervalTo(int $second1, int $nano1, int $second2, int $nano2, string $expectedInterval): void + { + $actualResult = Instant::of($second1, $nano1)->getIntervalTo(Instant::of($second2, $nano2)); + + $this->assertSame($expectedInterval, (string) $actualResult); + } + + public function providerGetIntervalTo(): array + { + return [ + [1672567200, 0, 1672567200, 0, '2023-01-01T10:00Z/2023-01-01T10:00Z'], + [1672567200, 0, 1672567210, 0, '2023-01-01T10:00Z/2023-01-01T10:00:10Z'], + [1672567200, 1000000, 1672567210, 2000000, '2023-01-01T10:00:00.001Z/2023-01-01T10:00:10.002Z'], + [1672567200, 1, 1672567200, 9, '2023-01-01T10:00:00.000000001Z/2023-01-01T10:00:00.000000009Z'], + [1672567200, 0, 1672653600, 0, '2023-01-01T10:00Z/2023-01-02T10:00Z'], + ]; + } + /** * @dataProvider providerToDecimal * diff --git a/tests/ZonedDateTimeTest.php b/tests/ZonedDateTimeTest.php index 91fb7df..04ec3bd 100644 --- a/tests/ZonedDateTimeTest.php +++ b/tests/ZonedDateTimeTest.php @@ -857,6 +857,29 @@ public function providerGetDurationTo(): array ]; } + /** + * @dataProvider providerGetIntervalTo + */ + public function testGetIntervalTo(string $firstDate, string $secondDate, string $expectedInterval): void + { + $actualResult = ZonedDateTime::parse($firstDate)->getIntervalTo(ZonedDateTime::parse($secondDate)); + + $this->assertSame($expectedInterval, (string) $actualResult); + } + + public function providerGetIntervalTo(): array + { + return [ + ['2023-01-01T10:00:00Z', '2023-01-01T10:00:00Z', '2023-01-01T10:00Z/2023-01-01T10:00Z'], + ['2023-01-01T10:00:00Z', '2023-01-01T10:00:10Z', '2023-01-01T10:00Z/2023-01-01T10:00:10Z'], + ['2023-01-01T10:00:00.001Z', '2023-01-01T10:00:10.002Z', '2023-01-01T10:00:00.001Z/2023-01-01T10:00:10.002Z'], + ['2023-01-01T10:00:00.001Z', '2023-01-01T13:00:10.002+03:00', '2023-01-01T10:00:00.001Z/2023-01-01T10:00:10.002Z'], + ['2023-01-01T10:00:00.001+03:00', '2023-01-01T13:00:10.002+03:00', '2023-01-01T07:00:00.001Z/2023-01-01T10:00:10.002Z'], + ['2023-01-01T10:00:00.000000001Z', '2023-01-01T10:00:00.000000009Z', '2023-01-01T10:00:00.000000001Z/2023-01-01T10:00:00.000000009Z'], + ['2023-01-01T10:00:00Z', '2023-01-02T10:00:00Z', '2023-01-01T10:00Z/2023-01-02T10:00Z'], + ]; + } + private function getTestZonedDateTime(): ZonedDateTime { $timeZone = TimeZone::parse('America/Los_Angeles');