Yura
Yura

Reputation: 2248

Laravel timestamp (from json response) is different from the one that generated from the artisan & mysql select command

TL;DR: There is no 2020-08-09 in the json response.

I just found a weird behavior in my Laravel 7.x project today. As mentioned on the title above, the created_at and updated_at of json response is different from the one generated from artisan command.

The problem appears when I change the default timezone in app/config.php from UTC to Asia/Jakarta. To make it clear, here is some result of my queries:

mysql> select * from field_reports

+----+------------+-----------+---------+-------------+------------------------+--------------------------------------------+---------------------+---------------------+
| id | company_id | branch_id | user_id | title       | chronology             | images                                     | created_at          | updated_at          |
+----+------------+-----------+---------+-------------+------------------------+--------------------------------------------+---------------------+---------------------+
|  1 |          1 |         1 |       1 | example     | example chronology     | [{"url": "some_url", "path": "some_path"}] | 2020-08-08 16:02:53 | 2020-08-08 16:29:46 |
|  2 |          1 |         1 |       1 | new fr      | new chronology         | [{"url": "some_url", "path": "some_path"}] | 2020-08-08 18:31:32 | 2020-08-08 18:31:32 |
|  3 |          1 |         1 |       1 | new fr      | new chronology         | [{"url": "some_url", "path": "some_path"}] | 2020-08-08 18:32:48 | 2020-08-08 18:32:48 |
|  4 |          1 |         1 |       1 | example     | example chronology     | [{"url": "some_url", "path": "some_path"}] | 2020-08-09 01:33:31 | 2020-08-09 01:33:31 |
|  5 |          1 |         1 |       1 | NEW         | NEW CHRONOLOGY         | [{"url": "some_url", "path": "some_path"}] | 2020-08-09 01:44:41 | 2020-08-09 01:44:41 |
+----+------------+-----------+---------+-------------+------------------------+--------------------------------------------+---------------------+---------------------+
5 rows in set (0.02 sec)

php artisan tinker

>>> App\User::first()->fieldReports;
=> Illuminate\Database\Eloquent\Collection {#4033
     all: [
       App\FieldReport {#4035
         id: 2,
         company_id: 1,
         branch_id: 1,
         user_id: 1,
         title: "new fr",
         chronology: "new chronology",
         images: "[{"url": "some_url", "path": "some_path"}]",
         created_at: "2020-08-08 18:31:32",
         updated_at: "2020-08-08 18:31:32",
       },
       App\FieldReport {#4038
         id: 3,
         company_id: 1,
         branch_id: 1,
         user_id: 1,
         title: "new fr",
         chronology: "new chronology",
         images: "[{"url": "some_url", "path": "some_path"}]",
         created_at: "2020-08-08 18:32:48",
         updated_at: "2020-08-08 18:32:48",
       },
       App\FieldReport {#4039
         id: 4,
         company_id: 1,
         branch_id: 1,
         user_id: 1,
         title: "example",
         chronology: "example chronology",
         images: "[{"url": "some_url", "path": "some_path"}]",
         created_at: "2020-08-09 01:33:31",
         updated_at: "2020-08-09 01:33:31",
       },
       App\FieldReport {#4040
         id: 5,
         company_id: 1,
         branch_id: 1,
         user_id: 1,
         title: "NEW",
         chronology: "NEW CHRONOLOGY",
         images: "[{"url": "some_url", "path": "some_path"}]",
         created_at: "2020-08-09 01:44:41",
         updated_at: "2020-08-09 01:44:41",
       },
     ],
   }
>>> 

and this one from get request in POSTMAN, here is where the problem exist, please have a look at the timestamp:

{
    "success": true,
    "data": [
        {
            "id": 2,
            "company_id": 1,
            "branch_id": 1,
            "user_id": 1,
            "title": "new fr",
            "chronology": "new chronology",
            "images": "[{\"url\": \"some_url\", \"path\": \"some_path\"}]",
            "created_at": "2020-08-08T11:31:32.000000Z",
            "updated_at": "2020-08-08T11:31:32.000000Z"
        },
        {
            "id": 3,
            "company_id": 1,
            "branch_id": 1,
            "user_id": 1,
            "title": "new fr",
            "chronology": "new chronology",
            "images": "[{\"url\": \"some_url\", \"path\": \"some_path\"}]",
            "created_at": "2020-08-08T11:32:48.000000Z",
            "updated_at": "2020-08-08T11:32:48.000000Z"
        },
        {
            "id": 4,
            "company_id": 1,
            "branch_id": 1,
            "user_id": 1,
            "title": "example",
            "chronology": "example chronology",
            "images": "[{\"url\": \"some_url\", \"path\": \"some_path\"}]",
            "created_at": "2020-08-08T18:33:31.000000Z",
            "updated_at": "2020-08-08T18:33:31.000000Z"
        },
        {
            "id": 5,
            "company_id": 1,
            "branch_id": 1,
            "user_id": 1,
            "title": "NEW",
            "chronology": "NEW CHRONOLOGY",
            "images": "[{\"url\": \"some_url\", \"path\": \"some_path\"}]",
            "created_at": "2020-08-08T18:44:41.000000Z",
            "updated_at": "2020-08-08T18:44:41.000000Z"
        }
    ]
}

Finally, here is the script in the controller: FieldReportController.php

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index(Request $request)
{
    $fieldReports = $request->user()->fieldReports;
    
    return response()->json([
        'success' => true,
        'data' => $fieldReports,
    ]);
}

I've tried several things like:

But the problem is still there. Any clue?

Upvotes: 11

Views: 4876

Answers (2)

STA
STA

Reputation: 34678

Laravel 7 uses a new date serialization format when using the toArray or toJson method on Eloquent models. To format dates for serialization, the framework now uses Carbon's toJSON method, which produces an ISO-8601 compatible date including timezone information and fractional seconds. In addition, this change provides better support and integration with client-side date parsing libraries.

Previously, dates would be serialized to a format like the following: 2020-12-02 20:01:00. Dates serialized using the new format will appear like: 2020-12-02T20:01:00.283041Z. Please note that ISO-8601 dates are always expressed in UTC.


If you would like to keep using the previous behavior you can override the serializeDate method on your model :

use DateTimeInterface;

/**
 * Prepare a date for array / JSON serialization.
 *
 * @param  \DateTimeInterface  $date
 * @return string
 */
protected function serializeDate(DateTimeInterface $date)
{
    return $date->format('Y-m-d H:i:s');
}

Note :This change only affects serialization of models and model collections to arrays and JSON. This change has no effect on how dates are stored in your database.

See the Upgrade Guide 7.x

Upvotes: 18

Sarnodeep Agarwalla
Sarnodeep Agarwalla

Reputation: 237

Inside model use

protected $casts = [
    'created_at' => 'datetime:Y-m-d',
];

Upvotes: 0

Related Questions