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

juhasev's avatar

Laravel and MySQL timezone

I've been trying to research for a solution getting user specific timezones working properly with Laravel and MySQL, but all I can find are Eloquent mutations or in SPA front end mutations using Momentjs.... This however is not a good solution because you end up converting timezones all over the app and sooner or later something slips by unconverted causing issues. In addition if user supplies a time it needs to be converted back to UTC... In my previous apps this was accomplished by setting:

  1. Laravel app.timezone (PHP Timezone)
  2. MySQL timezone

So basically MySQL runs and stores everything in UTC. Webserver's timezone is also set to UTC. Now when the application connects to MySQL it sets connection setting based on the user's timezone. When done this way every date/time that comes out of the database is automatically converted to/from the user's timezone and application logic doesn't get cluttered with timezone conversions.

The big guestion is: How does one set the MySQL timezone in Laravel so that it gets applied to all database queries whether they use query builder or Eloquent?

Thanks for any pointers you may have!

0 likes
12 replies
ekhlas's avatar

In

config/app.php 
'timezone' => 'UTC',
juhasev's avatar

The Laravel timezone configuration unfortunately sets PHP timezone only and has no effect on the underlying MySQL instance.

1 like
wesmahler's avatar

@juhavehnia - have you found a solution for this? I've been dealing with this for a while.

Even if you force set the database connection to a timezone for a user using:

DB::update('SET time_zone = ?', [$request->user()->timezone]);

When you retrieve a model resource via the API, it returns the datetime string with the correct time for the timezone, but the API's data resource object says it's in UTC and is wrong.

There needs to be a way to update the underlying MySQL instance's timezone.

Cronix's avatar

Is the user()->timezone a named timezone, or an offset? In mysql docs, it says:

Named time zones can be used only if the time zone information tables in the mysql database have been created and populated

Helmchen's avatar

The Laravel timezone configuration unfortunately sets PHP timezone only and has no effect on the underlying MySQL instance.

that's right .. but that's also a good thing :)

always expect UTC at your database level and the world becomes much easier.

you can format or convert the date in your app however you like, after you've retrieved it from the database.

Cronix's avatar

I agree with @Helmchen. Convert when saving or retrieving using carbon. Everything stored as UTC in the db. It makes life easier and more straightforward.

juhasev's avatar

@wesmahler I have not... I put it on the back burner hoping the community would know answer to this....

So did you also set the laravel timezone dynamically when you tested? That should force any resource object timezone to be the same. I need to play around with this a bit more. Also did you figure out a place where to set the MySQL timezone transparently so it is applies to all DB connections? In my previous apps this was done right after we know user is authenticated and can get to user’s timezone.

The only drawbacks to this approach are:

  1. MySQL timezone map can differ from PHP as timezones change occasionally. Now you need to make sure that both PHP and MySQL timezones are in the sync. This was a rare case and we served truly global audience. I believe this only happened just a few times over 7 years or so.

  2. You do need to load the MySQL timezone data which requires root privileges if I remember correctly. I believe PHP pulls its timezone data from the OS (at least on Linux). Therefore in cloud you may not be able to do this nor you have you any control on what timezone version has been loaded.

MatteoOreficeIT's avatar

The Laravel app.timezone configuration setting is totally misunderstood and totally undocumented on Official Laravel Documentation Site ( good work Laravel Team ! ) , it doesn't touch the database Layer but the php environment setting !

You can only find one reference in Illuminate\Foundation\Bootstrap\LoadConfiguration:49 ( Laravel 5.4 ):


date_default_timezone_set($config->get('app.timezone', 'UTC'));

The only effect is every PHP objects need to know default time zone will know ! But no effect will be yielded on database connection

What are you saying ? No effect on database ??? YESSS! Furthermore there is another totally undocumented configuration ....

It is database.connections.<connectionName>.timezone !!!!

This is the right configuration to tune timezone conversions !!! for example in \Illuminate\Database\Connectors\MySqlConnector::configureTimezone you can find reference about this configuration

After changing it MySQL will convert timezone between client and server time_zone , so you can put server time_zone = UTC and leave client's time_zone = User Timezone

NOTE : this conversion will take place only for TIMESTAMP columns , not for DATETIME

1 like
otaku's avatar

@MatteoOreficeIT this is the undocumented yet correct answer I believe. Adding a timezone key under config/database.php within connections.mysql worked. The timezone had to be specified in the offset hours format i.e. +05:30

realtebo's avatar

So, can we use timezone filed of our 'mysql' configuration to force a specific timezone?

How, for example, set 'utc' ?

I tried

'timezone' => "UTC",

But I got an error

SQLSTATE[HY000]: General error: 1298 Unknown or incorrect time zone: 'UTC'

sp4r74cus's avatar

Had the same error. so i looked for the valid values for set time_zone and got to this page.

so i used:

'timezone' => '+00:00',

and it worked.

juhasev's avatar

The best way to do this is to keep everything set to UTC on the server side. You can then offload the timezone conversions to the JavaScript on the front end. Here is an example using Moment.js.

      /**
         * Convert UTC datetime to local timezone and localized format
         *
         * @returns {string}
         * @param dateString
         */

        toLocalDateTime(dateString) {
            const dateTime = moment.utc(dateString).local().toDate();
            return dateTime.toLocaleDateString() + ' ' + dateTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
        },

     /**
         * Convert local time back to UTC time date
         *
         * @returns {*}
         * @param dateTimeString
         */

        toUTC(dateTimeString) {
            return moment(dateTimeString).utc().format('YYYY-MM-DD HH:mm:ss');
        },

1 like

Please or to participate in this conversation.