304 lines
9.5 KiB
PHP
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'],
|
|
];
|
|
}
|
|
}
|