diff --git a/src/Query/IteratorBuilder.php b/src/Query/IteratorBuilder.php index 0eb6c983d91..36c73f37767 100644 --- a/src/Query/IteratorBuilder.php +++ b/src/Query/IteratorBuilder.php @@ -259,7 +259,9 @@ protected function filterWhereDate($entries, $where) return false; } - return $value->copy()->startOfDay()->$method($where['value']); + $value = $value->copy()->setTimezone(config('app.timezone')); + + return $value->startOfDay()->$method($where['value']); }); } @@ -319,6 +321,8 @@ protected function filterWhereTime($entries, $where) return false; } + $value = $value->copy()->setTimezone(config('app.timezone')); + $compareValue = $value->copy()->setTimeFromTimeString($where['value']); return $value->$method($compareValue); diff --git a/src/Stache/Query/Builder.php b/src/Stache/Query/Builder.php index 58dfd01bade..b412a8923a8 100644 --- a/src/Stache/Query/Builder.php +++ b/src/Stache/Query/Builder.php @@ -206,7 +206,9 @@ protected function filterWhereDate($values, $where) return false; } - return $value->copy()->startOfDay()->$method($where['value']); + $value = $value->copy()->setTimezone(config('app.timezone')); + + return $value->startOfDay()->$method($where['value']); }); } @@ -258,6 +260,8 @@ protected function filterWhereTime($values, $where) return false; } + $value = $value->copy()->setTimezone(config('app.timezone')); + $compareValue = $value->copy()->setTimeFromTimeString($where['value']); return $value->$method($compareValue); diff --git a/tests/Data/Entries/EntryQueryBuilderTest.php b/tests/Data/Entries/EntryQueryBuilderTest.php index 35e34b3a915..92350499bce 100644 --- a/tests/Data/Entries/EntryQueryBuilderTest.php +++ b/tests/Data/Entries/EntryQueryBuilderTest.php @@ -188,6 +188,21 @@ public function entries_are_found_using_where_date_with_a_carbon_instance_in_a_d $this->assertEquals(['Post 2'], $entries->map->title->all()); } + #[Test] + public function entries_are_found_using_where_date_when_the_app_timezone_is_not_utc() + { + config()->set('app.timezone', 'Europe/Zurich'); + + $this->createWhereDateTestEntries(); + + // The entries are indexed in UTC, so Post 3 (2021-11-15 00:00 in Zurich) is stored + // as 2021-11-14 23:00. It should still be found when querying for the 15th. + $entries = Entry::query()->whereDate('test_date', Carbon::parse('2021-11-15', 'Europe/Zurich'))->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 1', 'Post 3'], $entries->map->title->all()); + } + #[Test] public function entries_are_found_using_where_month() { @@ -281,6 +296,21 @@ public function entries_are_found_using_where_time_with_a_carbon_instance_in_a_d $this->assertEquals(['Post 2'], $entries->map->title->all()); } + #[Test] + public function entries_are_found_using_where_time_when_the_app_timezone_is_not_utc() + { + config()->set('app.timezone', 'Europe/Zurich'); + + $this->createWhereDateTestEntries(); + + // Post 2's 09:00 in Zurich (+01:00) is indexed as 08:00 in UTC, so it should + // still be found when querying for 09:00. + $entries = Entry::query()->whereTime('test_date', Carbon::parse('2021-11-13 09:00', 'Europe/Zurich'))->get(); + + $this->assertCount(1, $entries); + $this->assertEquals(['Post 2'], $entries->map->title->all()); + } + private function createWhereDateTestEntries() { $blueprint = Blueprint::makeFromFields(['test_date' => ['type' => 'date', 'time_enabled' => true]]); diff --git a/tests/Search/QueryBuilderTest.php b/tests/Search/QueryBuilderTest.php index 23b3a65a2ad..8748672a687 100644 --- a/tests/Search/QueryBuilderTest.php +++ b/tests/Search/QueryBuilderTest.php @@ -136,6 +136,25 @@ public function results_are_found_using_where_date() $this->assertEquals(['a', 'c'], $results->map->reference->all()); } + #[Test] + public function results_are_found_using_where_date_when_the_app_timezone_is_not_utc() + { + config()->set('app.timezone', 'Europe/Zurich'); + + // The indexed values are in UTC, so 'b' (2021-11-15 00:00 in Zurich) is stored + // as 2021-11-14 23:00. It should still be found when querying for the 15th. + $items = collect([ + ['reference' => 'a', 'test_date' => Carbon::parse('2021-11-15 20:31:04', 'Europe/Zurich')->utc()], + ['reference' => 'b', 'test_date' => Carbon::parse('2021-11-15 00:00:00', 'Europe/Zurich')->utc()], + ['reference' => 'c', 'test_date' => Carbon::parse('2021-11-14 09:00:00', 'Europe/Zurich')->utc()], + ]); + + $results = (new FakeQueryBuilder($items))->withoutData()->whereDate('test_date', Carbon::parse('2021-11-15', 'Europe/Zurich'))->get(); + + $this->assertCount(2, $results); + $this->assertEquals(['a', 'b'], $results->map->reference->all()); + } + #[Test] public function results_are_found_using_where_month() { @@ -200,6 +219,24 @@ public function results_are_found_using_where_time() $this->assertEquals(['a', 'd'], $results->map->reference->all()); } + #[Test] + public function results_are_found_using_where_time_when_the_app_timezone_is_not_utc() + { + config()->set('app.timezone', 'Europe/Zurich'); + + // 'a' is at 09:00 in Zurich (+01:00), so it is indexed as 08:00 in UTC. + // It should still be found when querying for 09:00. + $items = collect([ + ['reference' => 'a', 'test_date' => Carbon::parse('2021-11-14 09:00:00', 'Europe/Zurich')->utc()], + ['reference' => 'b', 'test_date' => Carbon::parse('2021-11-15 20:31:04', 'Europe/Zurich')->utc()], + ]); + + $results = (new FakeQueryBuilder($items))->withoutData()->whereTime('test_date', Carbon::parse('2021-11-14 09:00', 'Europe/Zurich'))->get(); + + $this->assertCount(1, $results); + $this->assertEquals(['a'], $results->map->reference->all()); + } + private function createWhereDateTestItems() { return collect([