When using the toArray() method on a modal, it does not show the timestamps in the correct timezone.
app.php timezone to America/TorontoCreate 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.
That's intentional: https://laravel.com/docs/7.x/upgrade#date-serialization
杩欐槸鏁呮剰鐨勶細https : //laravel.com/docs/7.x/upgrade#date-serialization
But the time zone is wrong. The real-time environment variable is set
This is expected. Carbon will format the (string) typecast according to its __toString function and the toArray method will serialize it with the new serialization.
Note the upgrade guide specifies how to keep the old behavior if you want.
OK thanks. I just ended up using an accessor for now.
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:
$invoiceModel = Invoice::make(['number' => 'foobar', 'date' => '2020-03-01']);
$customer->invoices()->updateOrCreate(
['number' => $invoiceModel->number],
$invoiceModel->attributesToArray()
);
If the Invoice model has a date cast for the the date attribute, the date will be saved as 2020-02-29 instead of the correct 2020-03-01 because our timezone is set to Europe/Stockholm and not UTC.
The solution is to either set the timezone to UTC (which of course is not an option), set the cast as date:y-m-d or use the suggested upgrade guide solution of declaring our own serializedDate method on the model.
Is this really intended behaviour forattributesToArray/toArray regarding the date cast?
@viirre @taylorotwell I really think it is wrong. Carbon::toJSON() method will create a copy of current $date and set it to utc(), ignoring the app.timezone. So non-UTC dates will have a wrong output when toArray() or similar is called. It is really intentional?
A simple solution is modify how serializeDate() works by calling toISOString(true) instead of toJSON(). The true on toISOString(true) means "do not set timezone to UTF, keep as is".
Most helpful comment
@viirre @taylorotwell I really think it is wrong.
Carbon::toJSON()method will create a copy of current$dateand 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(). ThetrueontoISOString(true)means "do not set timezone to UTF, keep as is".