From 1763241dc4d8c1d8968067b70f45e29b20787093 Mon Sep 17 00:00:00 2001 From: techmahedy Date: Thu, 12 Nov 2026 19:07:06 +0600 Subject: [PATCH] fix: complete datetime boundary and microsecond consistency --- .../Entity/Casts/Handlers/DateTimeCast.php | 8 +++++++- .../Entity/Query/InteractsWithTimeframe.php | 4 ++-- tests/Builder/TimeframeOrConditionsTest.php | 20 +++++++++++++++++++ tests/Model/CastSystemTest.php | 8 ++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/Phaseolies/Database/Entity/Casts/Handlers/DateTimeCast.php b/src/Phaseolies/Database/Entity/Casts/Handlers/DateTimeCast.php index 628c00bc..e17b458b 100644 --- a/src/Phaseolies/Database/Entity/Casts/Handlers/DateTimeCast.php +++ b/src/Phaseolies/Database/Entity/Casts/Handlers/DateTimeCast.php @@ -51,7 +51,13 @@ public function set(mixed $value): mixed } if ($value instanceof DateTimeInterface) { - return $value->format($this->format); + $formatted = $value->format($this->format); + + if ($this->format === 'Y-m-d H:i:s' && $value->format('u') !== '000000') { + return $formatted . '.' . $value->format('u'); + } + + return $formatted; } return $value; diff --git a/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php b/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php index 4781f998..936c4fac 100644 --- a/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php +++ b/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php @@ -349,8 +349,8 @@ public function whereDateBetween(string $column, $start, $end): self */ public function whereDateTimeBetween(string $column, $start, $end): self { - $start = $this->formatDateTime($start, true); - $end = $this->formatDateTime($end, true); + $start = $this->formatDateTime($start, 'start'); + $end = $this->formatDateTime($end, 'end'); return $this->whereBetween($column, [$start, $end]); } diff --git a/tests/Builder/TimeframeOrConditionsTest.php b/tests/Builder/TimeframeOrConditionsTest.php index 57ba4dfc..74ac30b4 100644 --- a/tests/Builder/TimeframeOrConditionsTest.php +++ b/tests/Builder/TimeframeOrConditionsTest.php @@ -306,6 +306,26 @@ public function testFormatDateTimeWithDateTimeInterface() $this->assertEquals('2024-03-20 15:45:00', $b->formatDateTime($dt)); } + public function testWhereDateTimeBetweenUsesStartAndEndOfDayForDateStrings(): void + { + $builder = $this->builder(); + + $builder->whereDateTimeBetween('created_at', '2024-03-20', '2024-03-21'); + + $property = (new \ReflectionClass(Builder::class))->getProperty('conditions'); + + $this->assertSame([ + [ + 'AND', + 'created_at', + 'BETWEEN', + '2024-03-20 00:00:00', + '2024-03-21 23:59:59', + 'AND', + ], + ], $property->getValue($builder)); + } + public function testFormatDateTimePreservesMicroseconds(): void { $b = $this->builder(); diff --git a/tests/Model/CastSystemTest.php b/tests/Model/CastSystemTest.php index fe758769..e6a1679f 100644 --- a/tests/Model/CastSystemTest.php +++ b/tests/Model/CastSystemTest.php @@ -497,6 +497,14 @@ public function testCustomDateTimeFormatCast(): void $this->assertSame('2024-06-15', $model->invoiced_at->format('Y-m-d')); } + public function testDateTimeCastSetPreservesNonZeroMicroseconds(): void + { + $handler = CastManager::resolve('datetime'); + $value = Carbon::createFromFormat('Y-m-d H:i:s.u', '2024-06-15 09:30:00.123456'); + + $this->assertSame('2024-06-15 09:30:00.123456', $handler->set($value)); + } + public function testDateTimeCastNullPassthrough(): void { $model = new MockDateCastModel(['published_at' => null]);