diff --git a/CHANGELOG.md b/CHANGELOG.md index f59a4807..8499c1a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 2.6.1 under development +- Bug #819: Preserve microsecond precision when comparing date values in `UniqueIterable` (@samdark) - Bug #817: Fix `UniqueIterable` comparing the whole iterable instead of its items (@CorvusSharp) ## 2.6.0 June 02, 2026 diff --git a/src/Rule/UniqueIterableHandler.php b/src/Rule/UniqueIterableHandler.php index 7f20739c..7f35c885 100644 --- a/src/Rule/UniqueIterableHandler.php +++ b/src/Rule/UniqueIterableHandler.php @@ -60,7 +60,8 @@ public function validate(mixed $value, RuleInterface $rule, ValidationContext $c if ($item instanceof Stringable) { $stack[] = (string) $item; } elseif ($item instanceof DateTimeInterface) { - $stack[] = $item->getTimestamp(); + // Use a non-numeric separator to preserve microseconds during comparison. + $stack[] = $item->format('U:u'); } else { $stack[] = $item; } diff --git a/tests/Rule/UniqueIterableTest.php b/tests/Rule/UniqueIterableTest.php index ac6031d7..f925e426 100644 --- a/tests/Rule/UniqueIterableTest.php +++ b/tests/Rule/UniqueIterableTest.php @@ -5,6 +5,7 @@ namespace Yiisoft\Validator\Tests\Rule; use DateTime; +use DateTimeImmutable; use stdClass; use Stringable; use Yiisoft\Validator\PropertyTranslator\ArrayPropertyTranslator; @@ -120,6 +121,20 @@ public function __toString() [new DateTime('2024-04-10 14:05:01'), new DateTime('2024-04-10 14:05:02')], new UniqueIterable(), ], + 'datetime values with different microseconds' => [ + [ + new DateTime('2024-04-10 14:05:01.000001 UTC'), + new DateTime('2024-04-10 14:05:01.000002 UTC'), + ], + new UniqueIterable(), + ], + 'distant datetime values with different microseconds' => [ + [ + new DateTimeImmutable('9999-04-10 14:05:01.000001 UTC'), + new DateTimeImmutable('9999-04-10 14:05:01.000002 UTC'), + ], + new UniqueIterable(), + ], 'more than two unique strings' => [['a', 'b', 'c'], new UniqueIterable()], 'more than two unique integers' => [[1, 2, 3, 4], new UniqueIterable()], 'more than two unique floats' => [[1.5, 2.5, 3.5], new UniqueIterable()], @@ -284,6 +299,14 @@ public function __toString() new UniqueIterable(), ['' => [$message]], ], + 'equal datetime values with microseconds in different timezones' => [ + [ + new DateTime('2024-04-10 14:05:01.123456 +00:00'), + new DateTime('2024-04-10 17:05:01.123456 +03:00'), + ], + new UniqueIterable(), + ['' => [$message]], + ], 'strings' => [['a', 'b', 'a', 'c'], new UniqueIterable(), ['' => [$message]]], 'integers' => [[1, 2, 1, 3], new UniqueIterable(), ['' => [$message]]], 'floats' => [[1.5, 2.5, 1.5, 3.5], new UniqueIterable(), ['' => [$message]]],