diff --git a/src/Casts/DateTimeInterfaceCast.php b/src/Casts/DateTimeInterfaceCast.php index ac71df9e..9230c8b3 100644 --- a/src/Casts/DateTimeInterfaceCast.php +++ b/src/Casts/DateTimeInterfaceCast.php @@ -38,6 +38,11 @@ protected function castValue( return Uncastable::create(); } + // Truncate nanoseconds to microseconds (first 6 digits) + // Input: 2024-12-02T16:20:15.969827247Z + $value = preg_replace('/\.(\d{6})\d*Z$/', '.$1Z', $value); + // Output: 2024-12-02T16:20:15.969827Z + /** @var DateTimeInterface|null $datetime */ $datetime = $formats ->map(fn (string $format) => rescue(fn () => $type::createFromFormat( diff --git a/tests/Casts/DateTimeInterfaceCastTest.php b/tests/Casts/DateTimeInterfaceCastTest.php index 46054ec1..9a3655fd 100644 --- a/tests/Casts/DateTimeInterfaceCastTest.php +++ b/tests/Casts/DateTimeInterfaceCastTest.php @@ -281,3 +281,64 @@ public function __construct( ->and($data::from(['date' => '2022-05-16 17:00:00']))->toArray() ->toMatchArray(['date' => '2022-05-16T17:00:00+00:00']); }); + + +it('can cast date times with nanosecond precision by truncating nanoseconds to microseconds', function () { + $caster = new DateTimeInterfaceCast("Y-m-d\TH:i:s.u\Z"); + + $class = new class () { + public Carbon $carbon; + + public CarbonImmutable $carbonImmutable; + + public DateTime $dateTime; + + public DateTimeImmutable $dateTimeImmutable; + }; + + + expect( + $caster->cast( + FakeDataStructureFactory::property($class, 'carbon'), + '2024-12-02T16:20:15.969827247Z', + [], + CreationContextFactory::createFromConfig($class::class)->get() + ) + )->toEqual(new Carbon('2024-12-02T16:20:15.969827247Z')); + + expect( + $caster->cast( + FakeDataStructureFactory::property($class, 'carbonImmutable'), + '2024-12-02T16:20:15.969827247Z', + [], + CreationContextFactory::createFromConfig($class::class)->get() + ) + )->toEqual(new CarbonImmutable('2024-12-02T16:20:15.969827247Z')); + + expect( + $caster->cast( + FakeDataStructureFactory::property($class, 'dateTime'), + '2024-12-02T16:20:15.969827247Z', + [], + CreationContextFactory::createFromConfig($class::class)->get() + ) + )->toEqual(new DateTime('2024-12-02T16:20:15.969827247Z')); + + expect( + $caster->cast( + FakeDataStructureFactory::property($class, 'dateTimeImmutable'), + '2024-12-02T16:20:15.969827247Z', + [], + CreationContextFactory::createFromConfig($class::class)->get() + ) + )->toEqual(new DateTimeImmutable('2024-12-02T16:20:15.969827247Z')); + + expect( + $caster->cast( + FakeDataStructureFactory::property($class, 'dateTimeImmutable'), + '2024-12-02T16:20:15.969827247Z', + [], + CreationContextFactory::createFromConfig($class::class)->get() + ) + )->toEqual(new DateTimeImmutable('2024-12-02T16:20:15.969827247Z')); +}); \ No newline at end of file