Skip to content

Commit 6711335

Browse files
committed
✨ DateTimeCollection
* ✅ **Tested!** upon `\DateTime` * ✅ **Tested!** upon `\DateTimeImmutable` ✨ Features ========== * Define `containsDateTimeValue()` function for all `DateTimeInterfaceCollection` - Verify upon "date time + timezone" rather than object hash - Same for nullable `\DateTimeInterface`
1 parent bedf5b5 commit 6711335

21 files changed

+974
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Steevanb\PhpCollection\ObjectCollection\DateTime;
6+
7+
trait ContainsDateTimeNullableValueTrait
8+
{
9+
public function containsDateTimeValue(\DateTimeInterface $dateTime): bool
10+
{
11+
foreach ($this->toArray() as $value) {
12+
if (
13+
$value === null
14+
|| ($dateTime->getTimestamp() + $dateTime->getOffset())
15+
!== ($value->getTimestamp() + $value->getOffset())
16+
) {
17+
continue;
18+
}
19+
20+
return true;
21+
}
22+
23+
return false;
24+
}
25+
26+
/** @return array<?\DateTimeInterface> */
27+
abstract protected function toArray(): array;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Steevanb\PhpCollection\ObjectCollection\DateTime;
6+
7+
trait ContainsDateTimeValueTrait
8+
{
9+
public function containsDateTimeValue(\DateTimeInterface $dateTime): bool
10+
{
11+
foreach ($this->toArray() as $value) {
12+
if (
13+
($dateTime->getTimestamp() + $dateTime->getOffset())
14+
!== ($value->getTimestamp() + $value->getOffset())
15+
) {
16+
continue;
17+
}
18+
19+
return true;
20+
}
21+
22+
return false;
23+
}
24+
25+
/** @return array<\DateTimeInterface> */
26+
abstract protected function toArray(): array;
27+
}

src/ObjectCollection/DateTimeCollection.php

+4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Steevanb\PhpCollection\ObjectCollection;
66

7+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait;
8+
79
/** @extends AbstractObjectCollection<\DateTime> */
810
class DateTimeCollection extends AbstractObjectCollection
911
{
12+
use ContainsDateTimeValueTrait;
13+
1014
public static function getValueFqcn(): string
1115
{
1216
return \DateTime::class;

src/ObjectCollection/DateTimeImmutableCollection.php

+4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Steevanb\PhpCollection\ObjectCollection;
66

7+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait;
8+
79
/** @extends AbstractObjectCollection<\DateTimeImmutable> */
810
class DateTimeImmutableCollection extends AbstractObjectCollection
911
{
12+
use ContainsDateTimeValueTrait;
13+
1014
public static function getValueFqcn(): string
1115
{
1216
return \DateTimeImmutable::class;

src/ObjectCollection/DateTimeImmutableNullableCollection.php

+4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Steevanb\PhpCollection\ObjectCollection;
66

7+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait;
8+
79
/** @extends AbstractObjectNullableCollection<\DateTimeImmutable|null> */
810
class DateTimeImmutableNullableCollection extends AbstractObjectNullableCollection
911
{
12+
use ContainsDateTimeNullableValueTrait;
13+
1014
public static function getValueFqcn(): string
1115
{
1216
return \DateTimeImmutable::class;

src/ObjectCollection/DateTimeInterfaceCollection.php

+4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Steevanb\PhpCollection\ObjectCollection;
66

7+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait;
8+
79
/** @extends AbstractObjectCollection<\DateTimeInterface> */
810
class DateTimeInterfaceCollection extends AbstractObjectCollection
911
{
12+
use ContainsDateTimeValueTrait;
13+
1014
public static function getValueFqcn(): string
1115
{
1216
return \DateTimeInterface::class;

src/ObjectCollection/DateTimeInterfaceNullableCollection.php

+4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Steevanb\PhpCollection\ObjectCollection;
66

7+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait;
8+
79
/** @extends AbstractObjectNullableCollection<\DateTimeInterface|null> */
810
class DateTimeInterfaceNullableCollection extends AbstractObjectNullableCollection
911
{
12+
use ContainsDateTimeNullableValueTrait;
13+
1014
public static function getValueFqcn(): string
1115
{
1216
return \DateTimeInterface::class;

src/ObjectCollection/DateTimeNullableCollection.php

+4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace Steevanb\PhpCollection\ObjectCollection;
66

7+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait;
8+
79
/** @extends AbstractObjectNullableCollection<\DateTime|null> */
810
class DateTimeNullableCollection extends AbstractObjectNullableCollection
911
{
12+
use ContainsDateTimeNullableValueTrait;
13+
1014
public static function getValueFqcn(): string
1115
{
1216
return \DateTime::class;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Steevanb\PhpCollection\Tests\Unit\ObjectCollection\DateTime\ContainsDateTimeValue;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait;
9+
use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait;
10+
use Steevanb\PhpCollection\ObjectCollection\DateTimeCollection;
11+
use Steevanb\PhpCollection\ObjectCollection\DateTimeImmutableCollection;
12+
use Steevanb\PhpCollection\ObjectCollection\DateTimeImmutableNullableCollection;
13+
use Steevanb\PhpCollection\ObjectCollection\DateTimeInterfaceCollection;
14+
use Steevanb\PhpCollection\ObjectCollection\DateTimeInterfaceNullableCollection;
15+
use Steevanb\PhpCollection\ObjectCollection\DateTimeNullableCollection;
16+
17+
/**
18+
* @covers \Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait
19+
* @covers \Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait
20+
* @internal
21+
*/
22+
final class TraitUsageTest extends TestCase
23+
{
24+
/**
25+
* @dataProvider provideCollectionUsingTrait
26+
* @param class-string $class
27+
*/
28+
public function testUsingTrait(string $class): void
29+
{
30+
$reflectionCollection = new \ReflectionClass($class);
31+
static::assertContains(
32+
needle: ContainsDateTimeValueTrait::class,
33+
haystack: array_map(
34+
static fn (\ReflectionClass $reflectionTrait): string => $reflectionTrait->getName(),
35+
$reflectionCollection->getTraits()
36+
)
37+
);
38+
}
39+
40+
/**
41+
* @dataProvider provideCollectionUsingNullableTrait
42+
* @param class-string $class
43+
*/
44+
public function testUsingNullableTrait(string $class): void
45+
{
46+
$reflectionCollection = new \ReflectionClass($class);
47+
static::assertContains(
48+
needle: ContainsDateTimeNullableValueTrait::class,
49+
haystack: array_map(
50+
static fn (\ReflectionClass $reflectionTrait): string => $reflectionTrait->getName(),
51+
$reflectionCollection->getTraits()
52+
)
53+
);
54+
}
55+
56+
/** @return iterable<string, array{class: class-string}> */
57+
public static function provideCollectionUsingTrait(): iterable
58+
{
59+
yield 'ContainsDateTimeValueTrait_is_used_by_DateTimeCollection' => [
60+
'class' => DateTimeCollection::class,
61+
];
62+
yield 'ContainsDateTimeValueTrait_is_used_by_DateTimeImmutableCollection' => [
63+
'class' => DateTimeImmutableCollection::class,
64+
];
65+
yield 'ContainsDateTimeValueTrait_is_used_by_DateTimeInterfaceCollection' => [
66+
'class' => DateTimeInterfaceCollection::class,
67+
];
68+
}
69+
70+
/** @return iterable<string, array{class: class-string}> */
71+
public static function provideCollectionUsingNullableTrait(): iterable
72+
{
73+
yield 'ContainsDateTimeNullableValueTrait_is_used_by_DateTimeNullableCollection' => [
74+
'class' => DateTimeNullableCollection::class,
75+
];
76+
yield 'ContainsDateTimeNullableValueTrait_is_used_by_DateTimeImmutableNullableCollection' => [
77+
'class' => DateTimeImmutableNullableCollection::class,
78+
];
79+
yield 'ContainsDateTimeNullableValueTrait_is_used_by_DateTimeInterfaceNullableCollection' => [
80+
'class' => DateTimeInterfaceNullableCollection::class,
81+
];
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Steevanb\PhpCollection\Tests\Unit\ObjectCollection\DateTimeCollection;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Steevanb\PhpCollection\ObjectCollection\DateTimeCollection;
9+
10+
/**
11+
* @covers \Steevanb\PhpCollection\ObjectCollection\DateTimeCollection::containsDateTimeValue
12+
* @internal
13+
*/
14+
final class ContainsDateTimeValueTest extends TestCase
15+
{
16+
public function testContainsDateTimeValue(): void
17+
{
18+
$dateTimeA = new \DateTime();
19+
$dateTimeCopy = $dateTimeA;
20+
// Asserting different timestamps
21+
$dateTimeB = (new \DateTime())->add(new \DateInterval('PT1S'));
22+
$dateTimeClone = clone $dateTimeA;
23+
$dateTimeSameTime = (new \DateTime())->setTimestamp($dateTimeA->getTimestamp());
24+
25+
$dateTimeCollection = new DateTimeCollection([$dateTimeA]);
26+
27+
static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeA));
28+
static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeCopy));
29+
static::assertFalse($dateTimeCollection->containsDateTimeValue($dateTimeB));
30+
static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeClone));
31+
static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeSameTime));
32+
}
33+
34+
public function testContainsDateTimeValueWithTimezone(): void
35+
{
36+
$dateTime = new \DateTime('2024-07-14 12:00:00');
37+
$dateTimeB = clone $dateTime;
38+
$dateTimeC = clone $dateTime;
39+
$dateTimeD = clone $dateTime;
40+
41+
// Setting timezones
42+
$dateTime->setTimezone(new \DateTimeZone('+0800'));
43+
$dateTimeB->setTimezone(new \DateTimeZone('+0600'));
44+
$dateTimeC->setTimezone(new \DateTimeZone('-0600'));
45+
$dateTimeD->setTimezone($dateTime->getTimezone());
46+
47+
$dateTimeCollection = new DateTimeCollection([$dateTime]);
48+
49+
static::assertFalse($dateTimeCollection->containsDateTimeValue($dateTimeB));
50+
static::assertFalse($dateTimeCollection->containsDateTimeValue($dateTimeC));
51+
static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeD));
52+
}
53+
54+
public function testContainsDateTimeValueAfterClone(): void
55+
{
56+
$dateTime = new \DateTime();
57+
58+
$dateTimeCollection = (new DateTimeCollection([$dateTime]));
59+
$dateTimeCollectionClone = clone ($dateTimeCollection);
60+
61+
static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTime));
62+
static::assertTrue($dateTimeCollectionClone->containsDateTimeValue($dateTime));
63+
}
64+
65+
public function testContainsDateTimeValueAfterMerge(): void
66+
{
67+
$dateTime = new \DateTime();
68+
69+
static::assertTrue(
70+
(new DateTimeCollection([$dateTime]))
71+
->merge(new DateTimeCollection([new \DateTime()]))
72+
->containsDateTimeValue($dateTime)
73+
);
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Steevanb\PhpCollection\Tests\Unit\ObjectCollection\DateTimeCollection;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Steevanb\PhpCollection\ObjectCollection\DateTimeCollection;
9+
10+
/**
11+
* @covers \Steevanb\PhpCollection\ObjectCollection\DateTimeCollection::contains
12+
* @internal
13+
*/
14+
final class ContainsTest extends TestCase
15+
{
16+
public function testContains(): void
17+
{
18+
$dateTimeA = new \DateTime();
19+
$dateTimeCopy = $dateTimeA;
20+
$dateTimeB = new \DateTime();
21+
$dateTimeClone = clone $dateTimeA;
22+
$dateTimeSameTime = (new \DateTime())->setTimestamp($dateTimeA->getTimestamp());
23+
24+
$dateTimeCollection = new DateTimeCollection([$dateTimeA]);
25+
26+
static::assertTrue($dateTimeCollection->contains($dateTimeA));
27+
static::assertTrue($dateTimeCollection->contains($dateTimeCopy));
28+
static::assertFalse($dateTimeCollection->contains($dateTimeB));
29+
static::assertFalse($dateTimeCollection->contains($dateTimeClone));
30+
static::assertFalse($dateTimeCollection->contains($dateTimeSameTime));
31+
}
32+
33+
public function testContainsAfterClone(): void
34+
{
35+
$dateTime = new \DateTime();
36+
37+
$dateTimeCollection = (new DateTimeCollection([$dateTime]));
38+
$dateTimeCollectionClone = clone ($dateTimeCollection);
39+
40+
static::assertTrue($dateTimeCollection->contains($dateTime));
41+
static::assertTrue($dateTimeCollectionClone->contains($dateTime));
42+
}
43+
44+
public function testContainsAfterMerge(): void
45+
{
46+
$dateTime = new \DateTime();
47+
48+
static::assertTrue(
49+
(new DateTimeCollection([$dateTime]))
50+
->merge(new DateTimeCollection([new \DateTime()]))
51+
->contains($dateTime)
52+
);
53+
}
54+
}

0 commit comments

Comments
 (0)