Laravel Carbon how to change timezone without changing the hour

Use the shiftTimezone() method instead of setTimezone().

If you call setTimezone() on an existing instance of Carbon, it will change the date/time to the new timezone, for example:

$datetime = Carbon::createFromFormat('Y-m-d H:i:s', '2020-09-15 23:45:00');
echo $datetime->toAtomString() . "\n";
// 2020-09-15T23:45:00+00:00

$datetime->setTimezone('America/Los_Angeles');
echo $datetime . "\n";
// 2020-09-15T16:45:00-07:00

However, calling shiftTimezone() instead will set the timezone without changing the time. Lets try it again from the start:

$datetime = Carbon::createFromFormat('Y-m-d H:i:s', '2020-09-15 23:45:00');
echo $datetime->toAtomString() . "\n";
// 2020-09-15T23:45:00+00:00

$datetime->shiftTimezone('America/Los_Angeles');
echo $datetime->toAtomString() . "\n";
// 2020-09-15T23:45:00-07:00

Of course you can chain the methods together as well:

$datetime = Carbon::createFromFormat('Y-m-d H:i:s', '2020-09-15 23:45:00')
    ->shiftTimezone('America/Los_Angeles');
echo $datetime->toAtomString() . "\n";
// 2020-09-15T23:45:00-07:00

You can also "shift" the timezone by passing the timezone as part of the settings array:

$datetime = Carbon::createFromFormat('Y-m-d H:i:s', '2020-09-15 23:45:00')
    ->settings(['timezone' => 'America/Los_Angeles']);
echo $datetime->toAtomString() . "\n";
// 2020-09-15T23:45:00-07:00

My response to this question will be a little different. For my situation, I had a date string that needed to be parsed as if it was the 0th hour (midnight) on the given day in a custom timezone - but all the dates in my database are tracked in UTC, so what I really needed to do was keep the date in UTC timezone, but give it kind a "reverse offset" of what the expected timezone was.

Situation: I get a datestring of "2020-09-02" that I will use to see if X records have a field that is on or after this same date; however, I am in the America/Chicago timezone which currently is -05:00 from UTC, so I need to adjust the UTC version of this date string to be 2020-09-02 05:00 to accurately account for midnight in my timezone.

To do that, I needed to parse the datestring as being in the America/Chicago timezone, and then change the timezone to UTC:

$value = "2020-09-02"
Carbon::parse($value . '  America/Chicago')->tz('UTC')

A better and simpler way would be:

$carbon = new Carbon('YYYY-MM-DD HH:II:SS', 'America/Los_Angeles');

NOTE: Don't forget to add dependency use \Carbon\Carbon;.


I think that what you'r looking for is this:

Carbon::createFromFormat('Y-m-d H:i:s', $some_date, 'UTC')
    ->setTimezone('America/Los_Angeles')

First, you set the timezone you initially have, so if you store your date in the database as UTC, then set the default timezone to UTC, then use ->setTimeZone('Valid/Timezone') to make the change from what you'v had to the new timezone.