MySQL and PHP working with user timezones - php

I store time in UTC timezone in MySQL DATETIME field.
I want to convert all these (when using them in PHP) to user defined timezone.
I know I can do it with php DateTime::setTimezone, but it would require to do it each for each one of them.
Is there some global way to tell php that all datetimes from mysql are UTC and convert them automatically to the user timezone?

When you store them into the database, store the table column as a unix timestamp. These are all UTC. Then just apply whatever user specified offset you want.
Here is an interesting StackOverflow question which is likely to help you with it.
You can also use the MySQL Unix_Timestamp function to query data easily by generating the right int when doing comparisons.
Edit:
If you are certain that you want to convert all the datetimes from the database each time you use them, just write a simple function that gets the datetime and adds the correct offset for the user, then simply call that function each time you pluck a datetime from the database. like the code below:
<?php
// Assuming that $_SESSION['UserOffset'] is storing the user's timezone eg
// $_SESSION['UserOffset'] = new DateTimeZone("Europe/Prague");
function convert_time_zone($timeFromDatabase_time)
{
$userTime = new DateTime($timeFromDatabase, new DateTimeZone('UTC'));
$userTime->setTimezone(new DateTimeZone($_SESSION['UserOffset']));
return $userTime->format('Y-m-d H:i:s');
// or return $userTime; // if you want to return a DateTime object.
}
?>

Related

how to get date and time respecting user's timezone

I'm totally confused about php/mysql date/time functions.
My date column is timestamp - defalult value - current_timestamp.
date_default_timezone_set("Europe/Belgrade"); //my timezone
$stmt = $db->query("SELECT * FROM cinema order by date desc");
while($row = $stmt->fetch()){
$date = strtotime($row['date']);
$datea = date("d-m-y", $date);
$time = date("H:i", $date);
...
I'm getting the difference of -2 hours comparing to my local time.
How can I get the correct time (respecting my timezone), and if possible each user, whereever he is located on the globe, to get this data respecting his own timezone?
MySQL does not saves time zones at all. Depending for what you'd use the data stored, you should either always store the date-time value in "UTC" (this is like GMT, with no TZ offset at all) or in some cases you would like to store it with the offset already set. But for the second option, you should also store the TZ or the offset somewhere else (again MySQL date-time is unable to store this) in order to properly reconstruct the object from the DB.
For example, I usually add a created_at, updated_at fields in my db records and I store this in UTC, for this task I use PHP's gmdate('Y-m-d H:i:s')
Now, if you have to show this date-time in the user's TZ, you just have to create a DateTime object like so and change the TZ:
$createdAt = new DateTimeImmutable(
$row->created_at,
new DateTimeZone('UTC')
);
For the second case, where you could store the date-time with additional piece of data where you also save the TZ, you have to make sure to instantiate the DateTime object using the timezone constructor second argument to move the offset properly. So for a person from Argentina that will travel to Madrid, you might want to store the checkin date in the TZ of the destination (e.g. Madrid), but for displaying purposes, (e.g. want to know if might be able call in a normal time and let the family know that he/she arrived Ok) you later convert it to the origin tz:
$checkinAt = new DateTimeImmutable(
$row->checkin_at,
new DateTimeZone('Europe/Madrid')
);
$checkinAt->setTimezone('America/Argentina/Buenos_Aires');
To sum up:
You need to know how the date was stored, if you store all of it in UTC (e.g. no offset) then is simpler, but you might have issues when querying data if you need to access data assuming that have offset already.
MySQL does not stores TZ with its date-time value.
Make sure to instantiate the DateTime object using the proper timezone, PHP will use the default TZ if you don't pass any in the constructor. This is set on the php.ini and you can change it with this function date_default_timezone_set in your scripts.
you can do it pretty sweetly just in the sql query
CONVERT_TZ (dt, from_tz,to_tz)
http://www.w3resource.com/mysql/date-and-time-functions/mysql-convert_tz-function.php
$stmt = $db->query("SELECT *, CONVERT_TZ(date, "+00:00", "+01:00") FROM cinema order by date desc");
^ Assuming your database is UTC time and the time you are trying to convert to is "Europe/Belgrade".
First parameter is your datetime stamp, second is your database timezone and the third is your time you want it to convert to. If the timezone change is for the where/conditional part of the query you would put your from and to the other way around.
To get user or browser time. You must have their timezone, which you can get from Link.
Follow these steps:
download code and call it by function call
In first output you will see browser/user datetime, which you need to change accordingly(Ex: mm-dd-YY), using js bulit-in functions.
Put outputted value into one js variable, and pass that value to form hidden input fields
After form submission, capture that value as GET/POST to your database.
If you still fine hard time then, please let me know.

PHP & MySQL Timezones whilst supporting user-defined timezones

I'm working on something where the user can select their own timezone and the software will be able to be used by others on their sites as well but I want to make sure that the timezone within the database is always set to UTC.
Now I know how you set the default timezone for PHP, such as:
date_default_timezone_set('Australia/Sydney');
...but I'm not sure how to make sure MySQL is using UTC? ...and even once you have made sure it is using UTC I guess you would have to convert your PHP dates/times into UTC before passing it to the database?
I guess I am wondering about many different date formats such as TIMESTAMP, DATETIME & even UNIX EPOCH integer timestamps which would simply be stored as a int datatype for example.
Then there is the whole retrieving dates/times from the DB and converting it to the respective timezone and lastly how does DST come into all of this?
I know there is a lot of similar questions out there, but I guess none really answered all my questions.
MySQL's data type timestamp stores the dates in UTC. For this to work properly, MySQL uses server's time zone and does the date conversion. It converts the date from servers's current time zone to UTC for storage. This implies that the database server should never change its time zone for this feature to work properly.
When you send the data to such a database, you send the UTC time as well. The easiest way to do this is to format a result of time() according to what MySQL wants (m-d-Y H:i:s).
In PHP, when you format the date for insertion to MySQL, it's the best to use DateTime class. It lets you offset the date with the time zone information, meaning that you don't have to use date_default_timezone_set function - that can lead to mistakes.
An example of DateTime in action:
$date = '1.12.2015 13:37:37'; // Format is day.month.year hour:minute:second
// We create DateTime from custom date format, for the person who resides in Australia/Sydney time zone
$dt = DateTime::createFromFormat('d.m.Y H:i:s', $date, new DateTimeZone('Australia/Sydney');
// Now we change the date's time zone into UTC, and we can insert it into MySQL
$dt->setTimeZone(new DateTimeZone('UTC'));
// This is the formatted date-string that can be safely inserted into MySQL
$date_string_for_mysql = $dt->format('m-d-Y H:i:s');
Alternatively, you can use int type in MySQL for timestamp storage and insert result of time() but this has a huge disadvantage of not being able to use date-related functions.
for current session of mysql you can try something like
SET time_zone = timezonename;
for more details you can also look into this answer https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp

Storing timestamp in MySQL

I'm grabbing data from a webpage that returns a timestamp in the following form (which is a string):
2013-11-09T15:14:48.957604
How can I interpret this in PHP, and what is the best way to store this in a MySQL database?
The best way to store it is to use the MySQL DATETIME data type. It is specifically meant to handle date/time values, and it works beyond the year 2037, which is the approximate limit using unix timestamps. MySQL and PHP both handle these values with ease using built in functions/libraries (for PHP, see the DateTime class as mentioned by another commenter).
http://dev.mysql.com/doc/refman/5.5/en/datetime.html
http://php.net/manual/en/class.datetime.php
I just want to expand on the information given here.
This will convert the string into a DateTime object.
$dtObject = new DateTime("2013-11-09T15:14:48.957604");
But, in order to store the timestamp in the database there are several requirements.
Needs to be in Y-m-d H:i:s format.
MYSQL column type must be datetime/timestamp
Needs to be a string.
Now in order to get this timestamp into a MYSQL friendly format we need to use the format function.
$timestamp = $dtObject->format('Y-m-d H:i:s');
You can now INSERT this into the database. You can also output the same way following these date formats.

Can someone please clarify how MySQL's TIMESTAMP is used in conjunction with PHP's DateTime class?

I've been studying the differences in usage between MySQL's DATETIME and TIMESTAMP. It seems that it's pretty straight forward with DATETIME. I would use the following procedure:
Choose the default timezone for all dates, such as UTC.
Let user select a date from drop-down.
Create new PHP DateTime object with the chosen date, using the user's timezone settings, such as EST.
Convert the object to UTC, and insert into database.
On another page, retrieve datetime value and make a new DateTime object with it, using UTC timezone.
Convert object to user's local time (EST), and display to him.
Now, it seems that mysql's TIMESTAMP column type can help eliminate all of these conversions.
What would the above steps look like with the TIMESTAMP column type?
Would I need to do "SET time_zone = timezone;" in the beginning of each pageload to set the timezone to the location of the user?
Would it be easier to ONLY use one type of date column type per database? If not, it may require two different sets of functions to produce the right date.
Should TIMESTAMP only be used in columns not intended to be shown to the public (so as not to deal with formatting)? Like when a row was created, last edited, etc.
I have not tested any of this approach, but it seems pretty straightforward =)
You shouldn't need to convert dates, just set the time zone when you
read/write from dB to get everything right.
Yes, you will have to set right time zone after connection to dB is made.
You mean to only use datetime or timestamp? It really depends on how you intend to
use the columns. But there isn't a clear have to do.
Same as above, it isn't wrong formatting your data from the dB, with a timestamp you can return date style strings from the dB so no worries
Traditionally timestamp is associated like you mention, and datetime for other dates.
more on locale/time zone:
MYSQL set timezone in PHP code

PHP displaying stored time data, and storing time data while accounting for different timezones

I am creating this post, to get confirmation that i am understanding the process correctly, and also to get feedback on a few minor details on solving the issue of post times being displayed and stored correctly for users in various time-zones.
Storing the time
First step is getting the users timezone as a GMT offset format using a javascript function, and storing it in a session variable. For example, the $timezone variable will store GMT -4
$timezone=$_SESSION['time'];
Next, Once i have my users timezone. When the user makes a post, I store the post time in mysql database, I will need to store it as a UTC format. How do i do this? Currently when I store the time data. it is in the following way. My stamp field is datetime format, and i would like to leave it as such if possible.
INSERT INTO posts (stamp) VALUES (now())
What function do i use instead of now() to get the UTC format which will then be inserted into my database? I assume that I need to use a php function which will use the $timezone to produce the UTC date.
Displaying the time
Next, Once the UTC date is stored in the db. I need to display the data to the user based on the $timezone variable we set.
So when I display the time, I currently do
echo date('F d', strtotime($list1['stamp']));
Once i have stored the data as UTC time, this will display the UTC time, but i need to show the user the UTC offset for their timezone, so I will need to convert $list['stamp'] in UTC time to a the users timezone using $timezone. What function do i user for this?
tl:dr
This should be all I need to make this work. let me know if you see any suggestions, or items that i have not accounted for, and if you know what functions I need to use to convert the time to UTC to store in the database, and what function to use to convert the UTC time to display user, using the $timezone variable.
For inserting UTC time into the database:
INSERT INTO posts (stamp) VALUES (UTC_DATE())
UPDATE: This will only insert the YYYY-MM-DD into your database. If you need time as well, then use:
INSERT INTO posts (stamp) VALUES (UTC_TIMESTAMP())
Then for printing the date according to timezone:
$date = date_create($list1['stamp'], timezone_open($timezone)); //$timezone='Pacific/Nauru';
echo date_format($date, 'F d');
That should help get you started. Learn more about PHP's DateTime Class for Object Oriented Methods, and cleaner programming in general.

Categories