Skip to content

whereDate() / whereTime() ignore timezone of Carbon/DateTimeInterface values, shifting comparison instant #14939

Description

@marcorieser

Bug description

Builder::whereDate() and Builder::whereTime() (src/Query/Builder.php) accept a DateTimeInterface value. Internally they format the value down to a date-only or time-only string, then reparse it:

$value = Carbon::parse($value->format('Y-m-d')); // whereDate
$value = $value->format('H:i:s'); // whereTime

format() reads the components in the value's own timezone, but the reparse (Carbon::parse, or the raw string in whereTime) uses the app's default timezone (config('app.timezone')). If the passed value is in a different timezone than the app, the calendar digits get reinterpreted as if they were already in the app timezone — silently shifting the represented instant instead of converting it.

How to reproduce

App timezone UTC. Entry has test_date = 2021-11-14 09:00:00 (stored/augmented in UTC).

$value = Carbon::create(2021, 11, 15, 2, 0, 0, 'Europe/Moscow'); // = 2021-11-14 23:00:00 UTC

Entry::query()->whereDate('test_date', $value)->get();
// Expected: matches entries on 2021-11-14 (the UTC calendar date of the instant)
// Actual: matches entries on 2021-11-15 instead

Same issue for whereTime():

$value = Carbon::create(2021, 11, 13, 12, 0, 0, 'Europe/Moscow'); // = 09:00:00 UTC

Entry::query()->whereTime('test_date', $value)->get();
// Expected: matches entries at 09:00:00
// Actual: compares against 12:00:00 instead

Logs

Environment

Environment
Laravel Version: 13.18.1
PHP Version: 8.5.7
Composer Version: 2.10.1
Environment: local
Debug Mode: ENABLED
Maintenance Mode: OFF
Timezone: UTC
Locale: en

Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: log
Cache: file
Database: sqlite
Logs: stack / single
Mail: log
Queue: sync
Session: file

Storage
public/storage: NOT LINKED

Statamic
Addons: 0
License Key: Not set
Sites: 1
Stache Watcher: Enabled (auto)
Static Caching: Disabled
Version: 6.24.1 PRO

Installation

Fresh statamic/statamic site via CLI

Additional details

  • Only affects passing an explicit DateTimeInterface/Carbon in a non-app timezone; plain date/time strings are unaffected since they're already parsed in the app timezone.
  • Affects the Stache/flat-file query builder (src/Query/Builder.php, consumed by IteratorBuilder) — the Eloquent-backed path (EloquentQueryBuilder) delegates straight to Laravel/DB and isn't affected.
  • Fix + tests in progress on branch fix/where-date-time-timezone.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions