Home » Php » Storing dates and times in UTC and converting them local time in PHP/MySQL

Storing dates and times in UTC and converting them local time in PHP/MySQL

Posted by: admin July 12, 2020 Leave a comment

Questions:

I wanted to ask if this was going to work, before I went on a full fledged refactor of how i handle dates and times.

To frame my question, here’s my problem…
I store “actions” taken by the user in a history table. These actions have a timestamp on them. Users can be from all over the world, and hence have different timezones. I want to display the items in the history and show the timestamps in one’s local timezone.

Also, I know I can use datetime fields and simply store UTC time formats, but I’m opting to use timestamp so i can set a default to current time.

Will this work for my problem?

  1. My server time zone will be Los Angeles

  2. Store timestamps as a timestamp in MySQL. My understanding is that timestamp is always stored as UTC. Records will be stored by default as creation_date OR i will explicitly set UTC_TIMESTAMP(). Effictively, all records in the db will be UTC.

  3. When a user logs in I will grab their timezone (I store this in the db as a user setting).
    For this example, lets say this person is in New York.

Here’s where my question is. Will either of these work?

  1. a) Grab the history data. All timestamps will automatically be converted from UTC to Los Angeles time. Foreach history item, convert the Los Angeles timestamp to New York timestamp and echo.

OR

  1. b) Set the php timezone “date_default_timezone_set” to New York. Grab the history data. All timestamps are STILL in Los Angeles time by server is still Los Angeles time. Foreach history item, just echo the timestamp because the “date_default_timezone_set” will automatically convert the Los Angeles timestamp to New York.

Will option 4b work? Is there a better way to convert from the Los Angeles time to the New York time?

Is there a better way to do this in general?

How to&Answers:

You are correct, Unix timestamps are always in UTC. If you store the timestamps in your database in UTC, all you need to do to output it in local time is change the timezone in PHP to the timezone local to the user. You don’t need to do any conversion on the timestamps.

<?php

$timeStampFromDatabase = 1325448000;  // 01 Jan 2012 20:00:00 GMT

date_default_timezone_set('America/Los_Angeles');
echo date('r', $timeStampFromDatabase); // Sun, 01 Jan 2012 12:00:00 -0800

date_default_timezone_set('Asia/Hong_Kong');
echo date('r', $timeStampFromDatabase); // Mon, 02 Jan 2012 04:00:00 +0800

You can change your timezone on the fly and continue to output timestamps in a date format and they will be “converted” based on the set timezone in PHP. It is very easy, you don’t need to do any special handling, and it doesn’t matter where you set the timezone, as long as you do it before you output dates, but you can read them prior to setting the timezone.

Answer:

Unfortunately, “date_default_timezone_set” was not working the way I thought it would. As per the previous example, it would work if the dates I was working with were already in unix timestamp format. However, they were formatted in “Y-m-d H:i:s” and the only thing that would change was the GMT offset, which obviously doesnt work.

After a few hours of fidgeting, here’s how I was able to handle time conversions.

$datetime = new DateTime($date_to_convert);
$usertimezone = new DateTimeZone($_SESSION['timezone']); //each user has their own timezone i store in a session (i.e. - "Americas/Los_Angeles")
$datetime->setTimezone($usertimezone);
echo $datetime->format("Y-m-d H:i:s");

I suppose that I could have done the following as well:

Pseudo code
strtotime($datetime)
date_default_timezone_set($user_timezone)
echo date(format, $datetime)

the above, i think, would force the date function to handle it’s logic in the given $user_timezone. in hindsight, i would have to translate every $datetime -> unix_timestamp -> $datetime_converted, which doesnt sound to be much better than what i chose to do.

Answer:

Always store your timestamps in the database as UTC. This is a timezone and daylight savings independent point in time time. To display this back to the user in their timezone, simply do:

$users_timezone = 'Europe/London'; // See PHP documentation for names that can be used.
$date = new DateTime();
$date->setTimestamp($timestamp_from_database);
$date->setTimezone(new DateTimeZone($users_timezone));   
echo $date->format("H:ia jS F Y");

Answer:

By default, Unix timestamps are always in UTC. If we store the timestamps in our database in UTC, we just need to use the following PHP script:

<?php

$TZ_UTC = new DateTimeZone('UTC'); //-->Database Timezone;
$TZ_LOCAL = new DateTimeZone('America/New_York'); //-->Expected Local Timezone from user settings;

//--Example Database Query--
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
    //---If we want to show UTC timezone directy----
    echo $row['action_timestamp'];

    //---If we want to show LOCAL timezone from user settings----
    $dateObj = new DateTime($row['action_timestamp'], $TZ_UTC);
    $dateObj->setTimezone($TZ_LOCAL); //--> Here is the conversion!
    echo $dateObj->format("Y-m-d H:i:s T");
}
?>