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

EnvironmentLaravel Version: 13.18.1PHP Version: 8.5.7Composer Version: 2.10.1Environment: localDebug Mode: ENABLEDMaintenance Mode: OFFTimezone: UTCLocale: enCacheConfig: NOT CACHEDEvents: NOT CACHEDRoutes: NOT CACHEDViews: CACHEDDriversBroadcasting: logCache: fileDatabase: sqliteLogs: stack / singleMail: logQueue: syncSession: fileStoragepublic/storage: NOT LINKEDStatamicAddons: 0License Key: Not setSites: 1Stache Watcher: Enabled (auto)Static Caching: DisabledVersion: 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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions