简体   繁体   中英

Converting a date from local timezone to UTC

I have a Laravel-based app that is used by people from various parts of the US.

I am capturing a timestamp in Javascript when the user takes a specific action, and then I am submitting that timestamp as form data, for the Laravel/PHP to process.

The timestamp that I am capture in Javascript is in typical "YYYY-MM-DD HH:MM:SS" format.

I have the timezone the user is in stored in a database.

I basically want to take that timestamp, and convert it to UTC time, so that all timestamps in the database are UTC.

That is where I am struggling.

I have the following PHP code:

$defaultTime = request('submitted-time-stamp'); //In this case, we'll say 2022-12-21 12:01:01
$defaultTZ = $user->time_zone; //Translates to America/Denver

$utcTime = new DateTime($defaultTime);
$convertedTime = $utcTime1->setTimeZone(new DateTimeZone('UTC'));
$formattedTime = $convertedTime->format("Y-m-d H:i:s");

echo $formattedTime;

This code – it isn't producing any errors per sé... but it is showing the wrong time. It's showing the time that it went in as, not the time converted to UTC.

Basically, if I submit "2022-12-21 12:01:01" as the time, the converted time SHOULD be "2022-12-21 19:01:01", but it's still just echoing out "2022-12-21 12:01:01".

What am I missing here?

setTimezone() changes the timezone of the object from whatever default it was created with. Ie, it means, "convert from the existing timezone to this new timezone." It does not mean, "interpret the time as if it were in this timezone." If the original string didn't contain some sort of timezone identifier, then that default is whatever your PHP config says.

$when = new DateTime('2022-12-21 12:01:01');
echo $when->getTimeZone()->getName();

This will be the same as:

echo date_default_timezone_get();

Which is probably not what you want unless all your users are in the same timezone as your server.

In order to create a DateTime object in a specific known timezone that is not the same as your server's default, you'll need one of two things -- either a timezone representation in the input string:

$when = new DateTime('2022-12-21 12:01:01 America/New_York');

Or an explicit default timezone passed as a second parameter to the DateTime constructor:

$userDefaultTzStr = 'America/New_York'; // read this value from the database
$defaultTz = new DateTimeZone($userDefaultTzStr);
$when = new DateTime('2022-12-21 12:01:01', $defaultTz);

This latter method is (probably) preferred. If the input string contains any sort of timezone identifier, that will be used and the second parameter will be ignored. But if the input string does not contain any sort of timezone identifier, then the string will be interpreted as if it were in the indicated timezone.

Using Carbon it's very trivial.

use Carbon\Carbon;

$date = Carbon::create(request('submitted-time-stamp'), $user->time_zone);
$date->tz('UTC');

echo $date->format('Y-m-d H:i:s');

It should be the same thing with Laravel's Date facade.

use Illuminate\Support\Facades\Date;

$date = Date::create(request('submitted-time-stamp'), $user->time_zone);
$date->tz('UTC');

echo $date->format('Y-m-d H:i:s');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM