diff --git a/src/Phaseolies/Database/Entity/Builder.php b/src/Phaseolies/Database/Entity/Builder.php index 3b6efe3e..1e9af78b 100644 --- a/src/Phaseolies/Database/Entity/Builder.php +++ b/src/Phaseolies/Database/Entity/Builder.php @@ -1507,9 +1507,13 @@ protected function updatePivot($id, array $pivotData, string $pivotTable, string foreach ($pivotData as $key => $value) { $sets[] = "{$key} = ?"; - $params[] = $value instanceof \DateTimeInterface - ? $value->format('Y-m-d H:i:s') - : $value; + if ($value instanceof \DateTimeInterface) { + $params[] = $value->format('Y-m-d H:i:s') . ($value->format('u') !== '000000' + ? '.' . $value->format('u') + : ''); + } else { + $params[] = $value; + } } $params[] = $parentKey; diff --git a/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php b/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php index 61dd0267..4781f998 100644 --- a/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php +++ b/src/Phaseolies/Database/Entity/Query/InteractsWithTimeframe.php @@ -384,7 +384,9 @@ public function formatDate($date): string public function formatDateTime($date, string $type = 'start'): string { if ($date instanceof \DateTimeInterface) { - return $date->format('Y-m-d H:i:s'); + return $date->format('Y-m-d H:i:s') . ($date->format('u') !== '000000' + ? '.' . $date->format('u') + : ''); } if (is_string($date)) { diff --git a/src/Phaseolies/Helpers/helpers.php b/src/Phaseolies/Helpers/helpers.php index 7976bcf0..671b2bc5 100644 --- a/src/Phaseolies/Helpers/helpers.php +++ b/src/Phaseolies/Helpers/helpers.php @@ -927,11 +927,12 @@ function abort_if($condition, $code, $message = '', array $headers = []): void /** * Get the current timestamp with optional timezone * + * @param \DateTimeZone|string|null $timezone * @return \Carbon\Carbon */ - function now() + function now(\DateTimeZone|string|null $timezone = null): Carbon { - return Carbon::now(); + return Carbon::now($timezone); } } diff --git a/src/Phaseolies/Support/TimezoneHandler.php b/src/Phaseolies/Support/TimezoneHandler.php index 7b2e7072..1a10f28e 100644 --- a/src/Phaseolies/Support/TimezoneHandler.php +++ b/src/Phaseolies/Support/TimezoneHandler.php @@ -47,8 +47,7 @@ public function setTimezone(): void throw new \InvalidArgumentException("Invalid timezone: {$this->currentTimezone}"); } - $dt = Carbon::now(); - $dt->setTimezone($this->currentTimezone); + date_default_timezone_set($this->currentTimezone); } /** @@ -68,6 +67,6 @@ public function getTimezone(): string */ public function now(): Carbon { - return Carbon::now(); + return Carbon::now($this->currentTimezone); } } diff --git a/tests/Application/TimezoneHandlerTest.php b/tests/Application/TimezoneHandlerTest.php index 8660b19c..59f43d5e 100644 --- a/tests/Application/TimezoneHandlerTest.php +++ b/tests/Application/TimezoneHandlerTest.php @@ -64,6 +64,23 @@ public function testConstructorWithCustomTimezone() $this->assertEquals($timezone, date_default_timezone_get()); } + public function testHandlerNowUsesConfiguredTimezoneWithoutPriorGlobalSetup(): void + { + date_default_timezone_set('UTC'); + + $handler = new TimezoneHandler('Asia/Tokyo'); + + $this->assertSame('Asia/Tokyo', $handler->now()->timezoneName); + $this->assertSame('Asia/Tokyo', date_default_timezone_get()); + } + + public function testNowHelperAcceptsAnExplicitTimezone(): void + { + date_default_timezone_set('UTC'); + + $this->assertSame('Asia/Dhaka', now('Asia/Dhaka')->timezoneName); + } + public function testTimezoneAffectsDateFunctions() { $timezone = 'Australia/Sydney'; diff --git a/tests/Builder/TimeframeOrConditionsTest.php b/tests/Builder/TimeframeOrConditionsTest.php index 3c13e70c..57ba4dfc 100644 --- a/tests/Builder/TimeframeOrConditionsTest.php +++ b/tests/Builder/TimeframeOrConditionsTest.php @@ -306,6 +306,17 @@ public function testFormatDateTimeWithDateTimeInterface() $this->assertEquals('2024-03-20 15:45:00', $b->formatDateTime($dt)); } + public function testFormatDateTimePreservesMicroseconds(): void + { + $b = $this->builder(); + $dt = \DateTimeImmutable::createFromFormat( + 'Y-m-d H:i:s.u', + '2024-03-20 15:45:00.123456' + ); + + $this->assertSame('2024-03-20 15:45:00.123456', $b->formatDateTime($dt)); + } + public function testFormatDateTimeThrowsOnInvalidInput() { $this->expectException(\InvalidArgumentException::class);