-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Description
Laravel Version
12.32.5
PHP Version
8.3.14
Database Driver & Version
PostgreSQL 16.2 on aarch64-apple-darwin21.6.0, compiled by Apple clang version 14.0.0 (clang-1400.0.29.202), 64-bit
Description
When creating a new entity of a model with a cast of type datetime
or timestamp
when the database field is generated with timestamptz (timestamp with time zone) Laravel does not specify the timezone in the resulting query. As a result, PostgreSQL uses the client's timezone ("PostgreSQL assumes your local time zone for any type containing only date or time." - https://www.postgresql.org/docs/current/datatype-datetime.html)
Example:
Model Article with cast 'published_at' => 'datetime'
UTC time: 2025-10-05 20:00:00
Server timezone: Europe/Bucharest (date and time: 2025-10-05 23:00:00)
Database column: $table->timestamptz('published_at')
Creating an article Article::create(['published_at' => now()])
the resulting query will be: insert into "articles" ("published_at", "updated_at", "created_at") values ('2025-10-04 20:00:00', '2025-10-04 20:00:00', '2025-10-04 20:00:00) returning "id"
Because in the query, for the column published_at
, no time zone is specified, PostgreSQL uses the client's time zone (the server, in this case UTC+3), as a result in the database will be stored 2025-10-05 17:00:00 +00:00
.
There is a solution, we can add $dateFormat = 'Y-m-d H:i:s P';
in the Article model.
However, I believe that the above format can be used as default (when using pgsql database connection).
If we use a string with the time zone specified on a simple timestamp column, the timezone is stripped without modifying the date:
update articles set updated_at= '2025-10-05 23:00:00 +03:00'
update articles set published_at= '2025-10-05 23:00:00 +03:00'
First query sets updated_at = 2025-10-05 23:00:00
(it simply stripped the time zone)
The second query sets published_at = 2025-10-04 20:00:00 +00:00
This is mentioned in the documentation "If a time zone is specified in the input for time without time zone, it is silently ignored In a value that has been determined to be timestamp without time zone, PostgreSQL will silently ignore any time zone indication. That is, the resulting value is derived from the date/time fields in the input string, and is not adjusted for time zone." - https://www.postgresql.org/docs/current/datatype-datetime.html
Steps To Reproduce
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->dateTimeTz('published_at');
$table->timestamps();
});
class Article extends Model
{
protected function casts(): array
{
return [
'published_at' => 'datetime',
];
}
}
Article::create(['published_at' => now()])