framework: toArray uses incorrect timezone.
- Laravel Version: 7.0
- PHP Version: 7.3
- Database Driver & Version: Mysql 5.6
Description:
When using the toArray()
method on a modal, it does not show the timestamps in the correct timezone.
Steps To Reproduce:
-
Set the
app.php
timezone toAmerica/Toronto
-
Insert some rows for any model you want
-
Create a blade file with this code for the model:
created_at: {{ $model->created_at }} <br><br> via array: {{ print_r($model->toArray(), true) }}
You can clearly see that $model->created_at
is showing the correct date via the exact database value, and for whatever reason toArray
is deciding to change it to UTC.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 19 (10 by maintainers)
@viirre @taylorotwell I really think it is wrong.
Carbon::toJSON()
method will create a copy of current$date
and set it toutc()
, ignoring theapp.timezone
. So non-UTC dates will have a wrong output whentoArray()
or similar is called. It is really intentional?A simple solution is modify how
serializeDate()
works by callingtoISOString(true)
instead oftoJSON()
. Thetrue
ontoISOString(true)
means “do not set timezone to UTF, keep as is”.That’s intentional: https://laravel.com/docs/7.x/upgrade#date-serialization
I know this issue is closed but I’m trying anyway with a similar problem caused by this change.
There are some cases where this change might cause issues for a lot of apps, ours included. Consider:
If the
Invoice
model has adate
cast for the thedate
attribute, the date will be saved as2020-02-29
instead of the correct2020-03-01
because our timezone is set toEurope/Stockholm
and notUTC
.The solution is to either set the timezone to
UTC
(which of course is not an option), set the cast asdate:y-m-d
or use the suggested upgrade guide solution of declaring our ownserializedDate
method on the model.Is this really intended behaviour for
attributesToArray/toArray
regarding thedate
cast?@markking79
This issue is tricky to understand, I tried to explain as best I could in the post https://github.com/laravel/framework/issues/31722#issuecomment-1131875330 above and more details in #42447
2022-04-05T11:52:53.000000Z
is that it is a datetime + zone, i.e. UTC+0created_at
has to show07:52:53
, and we can see thatserializeDate
did not correct thatDon’t get me wrong. My concern is that this issue is hard to understand, so making it clear what does not work will better help everyone who reads this.
I was able to solve by adding the following method to my model…