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

philipbaginski's avatar

Default datetime value.

Hi everyone! Trying to set up default value for datetime field. The idea is: when you edit resource you don't have to set up new time (last update time). I used: ->withMeta(['value' => Carbon::now()]). But saved time is different by 2 hours. In app.php file I set up: 'timezone' => 'UTC'. I also tried to add 'UTC' into: Carbon::now('UTC')]).

Nothing works. Every time different is by 2 hours.

Aby idea?

0 likes
5 replies
MichalOravec's avatar

@philipbaginski You can implement your own ValueObject like

<?php

namespace App\ValueObjects;

use Carbon\CarbonInterface;
use DateTimeInterface;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Date;

class LocalDateValueObject
{
    protected $date;

    public function __construct($date)
    {
        $this->date = $date ? $this->inLocalTimezone($date) : null;
    }

    public function asDateFormat()
    {
        return optional($this->date)->format('M jS, Y');
    }

    public function asDateTimeFormat()
    {
        return optional($this->date)->format('H:i M jS, Y');
    }

    public function diffForHumans()
    {
        return optional($this->date)->diffForHumans();
    }

    public function toDateTimeString()
    {
        return optional($this->date)->toDateTimeString();
    }

    public function format($format)
    {
        return optional($this->date)->format($format);
    }

    protected function inLocalTimezone($date)
    {
        $timezone = optional(user())->timezone ?? config('app.local_timezone');

        return $this->asDateTime($date)->timezone($timezone);
    }

    protected function asDateTime($value)
    {
        if ($value instanceof Carbon || $value instanceof CarbonInterface) {
            return Date::instance($value);
        }

        if ($value instanceof DateTimeInterface) {
            return Date::parse(
                $value->format('Y-m-d H:i:s.u'),
                $value->getTimezone()
            );
        }

        if (is_numeric($value)) {
            return Date::createFromTimestamp($value);
        }

        if ($this->isStandardDateFormat($value)) {
            return Date::instance(Carbon::createFromFormat('Y-m-d', $value)->startOfDay());
        }

        $format = $this->getDateFormat();

        return Date::createFromFormat($format, $value);
    }

    protected function isStandardDateFormat($value)
    {
        return preg_match('/^(\d{4})-(\d{1,2})-(\d{1,2})$/', $value);
    }

    protected function getDateFormat()
    {
        return 'Y-m-d H:i:s';
    }

    public function __toString()
    {
        if (is_null($this->date)) {
            return '';
        }

        return $this->date->toDateTimeString() == $this->date ? $this->date->toDateTimeString() : $this->date->toDateString();
    }
}

Then you can use it in your model

use App\ValueObjects\LocalDateValueObject;

...

public function getLocalCreatedAtAttribute()
{
    return new LocalDateValueObject($this->created_at);
}
$model->local_created_at

Of course save date in UTC is good practise.

With this it's $timezone = optional(user())->timezone ?? config('app.local_timezone'); configurable by user. And default you save in config/app.php

'local_timezone' => 'America/New_York',
philipbaginski's avatar

I did a test. During editing time is displayed proper, but after saving is minus 2 hours. But when I set up time manually, it is saved proper. So, as I understand the mistake is made by Carbon - shows proper value but saving another.

MThomas's avatar

dit you check the server timezone? I think, you should set the timezone in app.php to the seame timezone as the timezone your server of machine is configured.

philipbaginski's avatar

I checked timezone in php.ini file for local server. It is Europe/Berlin. I set up the same value in app.php file. And did a test. What is funny, new record was created with current time minus 2 hourse, but the field 'updated_at' was saved in the same time with proper value. I checked both values in database. Next I updated record without touching updated at field (default value is set up Carbon::now. And record was saved with minus 2 hours for updated at field :-)

philipbaginski's avatar

Ended up with code:

->withMeta(['value' => $date->updated_at ?? Carbon::now()->toDatetimeString()]),

and:

protected $dates = [ 'created_at', 'updated_at', ];

in the model. Checked twice, works proper. Thanks for any advice and, what the most imprtant, keep going :-)

Please or to participate in this conversation.