Question

I'm trying to figure out how to accept a date/time from a form, which is consequently in the user's timezone, and change it to UTC before inserting it into the database. For some reason, no amount of searching has netted me an answer.

My form will POST whatever date is selected by the user to my code, so I expect to be able to do something like this. Note: the $userDate may be relative to any number of timezones based on user's location

$userDate = $_POST['user_date'] // 2014-05-15 16:37:23

I anticipate using Date().getTimezoneOffset() on my form to also submit the users UTC offset (as detailed here).

$userOffset = $_POST['user_offset']

Then before inserting the date into my database, I would like to convert it to UTC -- but I am stumped on how to do that with PHP (I'm actually using Laravel so if you know of a way using Carbon, that would be even easier, but I couldn't find it in their docs).

I've been half tempted to manually parse the offset and convert it to number of seconds and add or subtract it to strtotime() output of the $userDate and then convert it back into a date format using date() -- but there has to be a better way!

What am I missing here? Does PHP have a function I just don't know about that lets me do something like:

$userDate = '2014-05-15 16:37:23';
$userOffset = '+04:00';
$utcDate = date_apply_offset($userDate, $userOffset);

echo $utcDate; // Outputs: 2014-05-15 20:37:23

Or am I making this harder than it has to be?


EDIT

Based on the solution provided by @vascowhite, I went with the following (added into question to improve answers for those seeking guidance)

I ended up using a function from moment.js since I was already using it to convert UTC to user's timezone on display.

HTML:

<input id="user_offset" type="hidden" name="user_offset" value="">

Javascript:

 var offset = moment().format('ZZ');
 $('#user_offset').val(offset);

PHP (in a custom date class):

class MyDate {

   /**
    * Convert Date to UTC
    * 
    * @param string $date      Any date parsable with strtotime()
    * @param string $offset    UTC offset of date
    */
   public static function toUTC($date, $offset = '+0:00')
   {
       if ($timestamp = strtotime($date) && ! empty($offset) )
       {
           $newDate = date('Y-m-d H:i:s', $timestamp);
           $newDate = new \DateTime($date . ' ' . $offset);
           $newDate->setTimezone(new DateTimeZone('UTC'));
           $date = $newDate->format('Y-m-d H:i:s');
       }
       return $date;
   }
}

// To convert
$userDate = trim($_POST['user_offset']);
$userOffset = trim($_POST['user_date']);
$utc = MyDate::toUTC($userDate, $userOffset)

That class method isn't perfect, and in the event something goes wrong, it just returns the date back -- when really it should throw an exception.

Was it helpful?

Solution

This is a simple task with the DateTime classes:-

$userDate = '2014-05-15 16:37:23';
$userOffset = '+04:00';

$date = new \DateTime($userDate . ' ' . $userOffset);
var_dump($date);
$date->setTimezone(new \DateTimeZone('UTC'));
var_dump($date);

You can then format the date as you wish for output eg:-

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

or:-

$utcDate = $date->format('Y-m-d H:i:s');
echo $utcDate; // Outputs: 2014-05-15 20:37:23

See it working.

If you are doing any work with dates and times in PHP it is worth taking the time to become familiar with these extremely useful classes.

OTHER TIPS

For all sorts of date/time manipulations you can make use of moment.php

For your example all what is needed are two lines of code:

$m = new \Moment\Moment('2014-05-15 16:37:23', '+0400');
echo $m->setTimezone('UTC')->format(); // 2014-05-15T12:37:23+0000

There is much more which helps to deal with date/time issues: https://github.com/fightbulc/moment.php

Cheers

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top