Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Marijn's avatar

Laravel doesnt convert dates correctly

Hi guys. I don't know if this is intended behaviour of laravel or not, but when I have casts such as this (note the dateFormat)

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

    protected $dateFormat = "U"; // unix timestamp

On some model Time, then if I do

        $time = new Time;
        $time->time_date = now();
        $time->time_enddate = now();
        dd($time);

I see the following printed in the dump and die

  #attributes: array:3 [▼
    "time_date" => Illuminate\Support\Carbon @1645374270 {#1844 ▶}
    "time_enddate" => "1645374270"
  ]

This to me is unexpected behaviour. The way that a variable should be cast should have no impact on the way it is set. Furthermore, this behaviour is not in line with what I read in the laravel docs.

/**
 * The attributes that should be cast.
 *
 * @var array
 */
protected $casts = [
    'created_at' => 'datetime:Y-m-d',
];


When a column is cast as a date, you may set the corresponding model attribute value to a UNIX timestamp, date string (Y-m-d), date-time string, or a DateTime / Carbon instance. The date's value will be correctly converted and stored in your database.

Can someone explain why this happens?

0 likes
4 replies
rodrigo.pedra's avatar

Are there any errors, or unexpected formats, when saving it to the database?

As you quoted:

The date's value will be correctly converted and stored in your database.

So the guarantee is to honor the date format when serializing it. How Laravel holds the attribute on memory is not mentioned.

Try this:

$time = new Time;
$time->time_date = now();
$time->time_enddate = now();
dd($time->toArray());
Marijn's avatar

@rodrigo.pedra Well yes as I showed, time_date gets stored as a Carbon instance, while time_enddate gets (correctly) stored to a timestamp in the attributes array of the model. When I do toArray(), then I get this

array:2 [▼
  "time_date" => "2022-02-21"
  "time_enddate" => "2022-02-21T08:28:12.000000Z"
]

I found that the setAttribute (in the trait hasAttributes.php on the eloquent model class) function has this

        // First we will check for the presence of a mutator for the set operation
        // which simply lets the developers tweak the attribute as it is set on
        // this model, such as "json_encoding" a listing of data for storage.
        if ($this->hasSetMutator($key)) {
            return $this->setMutatedAttributeValue($key, $value);
        }

        // If an attribute is listed as a "date", we'll convert it from a DateTime
        // instance into a form proper for storage on the database tables using
        // the connection grammar's date format. We will auto set the values.
        elseif ($value && $this->isDateAttribute($key)) {
            $value = $this->fromDateTime($value);
        }

The first one datetime:Y-m-d is apparently NOT a DateAttribute. So isDateAttribute() returns false and it is not changed to the correct saving form (unix timestamp) in $value = $this->fromDateTime($value)

rodrigo.pedra's avatar

@Marijn the key here is

…stored in your DATABASE

What you showed is how Laravel keeps their values in the memory inside the Model's $attributes property.

  • Have you tested how it is saved into the database?
  • Have you tested the return of dd($model->toArray()) as suggested? To check if Laravel serializes the dates as expected?

Please or to participate in this conversation.