Files
brick-date-time/tests/IntervalTest.php
T

304 lines
9.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Brick\DateTime\Tests;
use Brick\DateTime\DateTimeException;
use Brick\DateTime\Instant;
use Brick\DateTime\Interval;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Depends;
use function json_encode;
use const JSON_THROW_ON_ERROR;
/**
* Unit tests for class Interval.
*/
class IntervalTest extends AbstractTestCase
{
public function testEndInstantIsNotBeforeStartInstant(): void
{
$start = Instant::of(2000000000, 987654321);
$end = Instant::of(2000000009, 123456789);
$this->expectException(DateTimeException::class);
$this->expectExceptionMessage('The end instant must not be before the start instant.');
Interval::of($end, $start);
}
public function testGetStartEnd(): void
{
$start = Instant::of(2000000000, 987654321);
$end = Instant::of(2000000009, 123456789);
$interval = Interval::of($start, $end);
self::assertInstantIs(2000000000, 987654321, $interval->getStart());
self::assertInstantIs(2000000009, 123456789, $interval->getEnd());
}
#[Depends('testGetStartEnd')]
public function testWithStart(): void
{
$interval = Interval::of(
Instant::of(2000000000),
Instant::of(2000000001),
);
$newInterval = $interval->withStart(Instant::of(1999999999, 999999999));
self::assertNotSame($newInterval, $interval);
// ensure that the original isn't changed
self::assertInstantIs(2000000000, 0, $interval->getStart());
self::assertInstantIs(2000000001, 0, $interval->getEnd());
// test the new instance
self::assertInstantIs(1999999999, 999999999, $newInterval->getStart());
self::assertInstantIs(2000000001, 0, $newInterval->getEnd());
}
#[Depends('testGetStartEnd')]
public function testWithEnd(): void
{
$interval = Interval::of(
Instant::of(2000000000),
Instant::of(2000000001),
);
$newInterval = $interval->withEnd(Instant::of(2000000002, 222222222));
self::assertNotSame($newInterval, $interval);
// ensure that the original isn't changed
self::assertInstantIs(2000000000, 0, $interval->getStart());
self::assertInstantIs(2000000001, 0, $interval->getEnd());
// test the new instance
self::assertInstantIs(2000000000, 0, $newInterval->getStart());
self::assertInstantIs(2000000002, 222222222, $newInterval->getEnd());
}
public function testGetDuration(): void
{
$interval = Interval::of(
Instant::of(1999999999, 555555),
Instant::of(2000000001, 111),
);
$duration = $interval->getDuration();
self::assertDurationIs(1, 999444556, $duration);
}
#[DataProvider('providerContains')]
public function testContains(int $start, int $end, int $now, bool $expected, string $errorMessage): void
{
$interval = Interval::of(Instant::of($start), Instant::of($end));
self::assertSame($expected, $interval->contains(Instant::of($now)), $errorMessage);
}
public static function providerContains(): array
{
return [
'at the start' => [
1000000000,
2000000000,
1000000000,
true,
'an Interval must contain its start',
],
'at the end' => [
1000000000,
2000000000,
2000000000,
false,
'an Interval must not contain its end',
],
'in the middle' => [
1000000001,
1000000003,
1000000002,
true,
'an Interval must contain its intermediate values',
],
];
}
#[DataProvider('providerIntersectsWith')]
public function testIntersectsWith(int $start1, int $end1, int $start2, int $end2, bool $expected): void
{
$interval1 = Interval::of(Instant::of($start1), Instant::of($end1));
$interval2 = Interval::of(Instant::of($start2), Instant::of($end2));
self::assertSame($expected, $interval1->intersectsWith($interval2));
}
public static function providerIntersectsWith(): array
{
return [
'second is after first' => [
100000, 200000,
400000, 500000,
false,
],
'second is before first' => [
400000, 500000,
100000, 200000,
false,
],
'end of the first is start of the second' => [
100000, 200000,
200000, 300000,
false,
],
'start of the first is end of the second' => [
200000, 300000,
100000, 200000,
false,
],
'intersection' => [
100000, 200000,
150000, 250000,
true,
],
];
}
#[DataProvider('providerGetIntersectionWith')]
public function testGetIntersectionWith(
int $start1,
int $end1,
int $start2,
int $end2,
int $expectedStart,
int $expectedEnd,
): void {
$interval1 = Interval::of(Instant::of($start1), Instant::of($end1));
$interval2 = Interval::of(Instant::of($start2), Instant::of($end2));
$expected = Interval::of(Instant::of($expectedStart), Instant::of($expectedEnd));
self::assertTrue($expected->isEqualTo($interval1->getIntersectionWith($interval2)));
}
public static function providerGetIntersectionWith(): array
{
return [
'first before second' => [
100000, 200000,
150000, 250000,
150000, 200000,
],
'first after second' => [
150000, 250000,
100000, 200000,
150000, 200000,
],
'first inside second' => [
200000, 300000,
100000, 400000,
200000, 300000,
],
'second inside first' => [
100000, 400000,
200000, 300000,
200000, 300000,
],
'first = second' => [
5000, 6000,
5000, 6000,
5000, 6000,
],
];
}
public function testGetIntersectionWithInvalidParams(): void
{
$interval1 = Interval::of(Instant::of(100000), Instant::of(200000));
$interval2 = Interval::of(Instant::of(300000), Instant::of(400000));
$this->expectException(DateTimeException::class);
$this->expectExceptionMessage('Intervals "1970-01-02T03:46:40Z/1970-01-03T07:33:20Z" and "1970-01-04T11:20Z/1970-01-05T15:06:40Z" do not intersect.');
$interval1->getIntersectionWith($interval2);
}
#[DataProvider('providerIsEqualTo')]
public function testIsEqualTo(Interval $a, Interval $b, bool $expectedResult): void
{
self::assertSame($expectedResult, $a->isEqualTo($b));
self::assertSame($expectedResult, $b->isEqualTo($a));
}
public static function providerIsEqualTo(): array
{
return [
'start is not equal' => [
Interval::of(Instant::of(100000), Instant::of(200000)),
Interval::of(Instant::of(150000), Instant::of(200000)),
false,
],
'end is not equal' => [
Interval::of(Instant::of(100000), Instant::of(200000)),
Interval::of(Instant::of(100000), Instant::of(250000)),
false,
],
'both start and end are not equal' => [
Interval::of(Instant::of(100000), Instant::of(200000)),
Interval::of(Instant::of(150000), Instant::of(250000)),
false,
],
'intervals are equal' => [
Interval::of(Instant::of(100000), Instant::of(200000)),
Interval::of(Instant::of(100000), Instant::of(200000)),
true,
],
];
}
#[DataProvider('providerToString')]
public function testJsonSerialize(int $epochSecondStart, int $epochSecondEnd, string $expectedString): void
{
$interval = Interval::of(
Instant::of($epochSecondStart),
Instant::of($epochSecondEnd),
);
self::assertSame(json_encode($expectedString, JSON_THROW_ON_ERROR), json_encode($interval, JSON_THROW_ON_ERROR));
}
#[DataProvider('providerToString')]
public function testToISOString(int $epochSecondStart, int $epochSecondEnd, string $expectedString): void
{
$interval = Interval::of(
Instant::of($epochSecondStart),
Instant::of($epochSecondEnd),
);
self::assertSame($expectedString, $interval->toISOString());
}
#[DataProvider('providerToString')]
public function testToString(int $epochSecondStart, int $epochSecondEnd, string $expectedString): void
{
$interval = Interval::of(
Instant::of($epochSecondStart),
Instant::of($epochSecondEnd),
);
self::assertSame($expectedString, (string) $interval);
}
public static function providerToString(): array
{
return [
[1000000000, 1000000000, '2001-09-09T01:46:40Z/2001-09-09T01:46:40Z'],
[1000000000, 2000000000, '2001-09-09T01:46:40Z/2033-05-18T03:33:20Z'],
];
}
}