Store UTC date time in database - php

I will convert all date & time input by user (local time) to UTC and store it in database. When display back I will convert UTC time to their time zone which is set in their profile. Is it good?

I think it's good enough. Besides storing user timezone in profile, you can also let client (for example, javascript) convert UTC time according to user computer time zone.

As long as you can convert to/from any time zone from your stored DB records, that's all you need.
What you've described will work.

Note some MySQL documentation in regards to timezone & server/client workings:
Per-connection time zones.
Each client that connects has its own time zone setting, given by the session time_zone variable. Initially, the session variable takes its value from the global time_zone variable, but the client can change its own time zone with this statement:
mysql> SET time_zone = timezone;
So, normally, in your proposed solution, all is right, but don't let the actual server or client timezone changing catch you of guard.

Related

Setting UTC as time zone in PHP and MySQL

I'm working on an application and I ran into a little problem...
How do I work with time zones and will there be conflicts between PHP and MySQL? What I was thinking of doing is setting the time zone to UTC in PHP like this date_default_timezone_set('UTC'); and storing it in MySQL using DATETIME.
Will MySQL change the time I provide via PHP to whatever time zone it has set or will it just store the value provided? If it will change it, how can I set the time zone in MySQL to UTC as well.
I would like to set the time zone to UTC so if I ever do need to worry about changing time for different time zones, I can just add/subtract whatever the offset is.
P.S. I'm new to web development.
Use below code to extract TimeZone Offset value. Then add it to your actual date time value. It will convert your Date Time value to UTC time.
set #TimeZoneOffSet := TIMEDIFF(NOW(),UTC_TIMESTAMP);
select ADDTIME(date_time_column,#TimeZoneOffSet) from table_name;;

Setting MySQL timezone for session

I know that using this query I can set time per session in mysql server
SET SESSION time_zone = '+04:00'
Question is how to detect this +04:00 (it can vary during year because of daylight saving time) part in PHP for my country?
Try using the timezone name (like America/Chicago) instead of +/- a set of hours. This should take into account daylight savings time.
You will need to load zoneinfo into your mysql database if you haven't already.
I will take a guess that perhaps you are in Azerbaijan? If so, you should use the IANA time zone id of Asia/Baku. This time zone alternates between a standard offset of +4:00 and a daylight offset of +5:00.
See "Time Zone != Offset" and "Time Zone Databases" in the timezone tag wiki.
If you need to do this in MySQL, you will need to load the IANA time zone database (aka "zoneinfo") into MySQL using mysql_tzinfo_to_sql. Thanks to datasage and kordirko for this tip.
But often the better approach is to only store UTC times in your database. You can do timezone translations directly in PHP using the DateTime and DateTimeZone classes. PHP also implements the same IANA time zone database, and you can find Asia/Baku on PHP's list of supported time zones.
Open your my.ini file. For windows it is in /mysql/bin/my.ini
Search for the section mysqld.
in this section enter -
default-time-zone = '+00:00'
+00:00 is the offset from GMT. Check out the time-zone-support page for better reference.

Using time zones in a PHP web application

I've been looking around for a few hours now about what's the best way to use timezones in a PHP/MySQL web application, finding a definitive answer is hard. From what I've learnt so far it is best to store everyones stuff in the database in UTC (correct me if I am wrong).
When a user registers I will ask them for there timezone and then store that against there user. This would be in this format as a dropdown menu:
<option value="Europe/London">(GMT) Greenwich Mean Time : London</option>
The app I am building will allow users to set arrangements in the future with people (meetings), much like a calendar. Obviously over the course of a year different timezones have different daylight savings periods, any idea how I would cater for this?
Say a user from the UK sets a meeting for 3:00PM on January 24th 2013 and invites someone who lives in California to this meeting, how do I get it so that the American sees that meeting in his/her timezone and the UK user sees it in his/her timezone? (Note that both users are signed up and have set their timezone).
Does anyone have a clear explanation and maybe some examples for this? Or can point me to where I can find that?
Thanks
I dealt with this situation extensively in a PHP/MySQL application I wrote for a private jet operator a little over a year ago. There are different strategies to handle timezones in these two platforms, but I will explain how I did it. I set the MySQL server to UTC and run each PHP script in the timezone that the user specifies during the signup process for the user profile.
MySQL and PHP (PHP 5.2 and above) both have native datetime datatypes. MySQL's datetime is a primitive data type, while PHP 5.2 and above offers the built-in DateTime class. The MySQL datetime datatype does not include metadata for the timezone, but a PHP DateTime object always includes a timezone. If the PHP datetime constructor does not specify the optional timezone in the second argument, then the PHP datetime constructor uses the php environment variable.
Both MySQL and PHP have default timezone set in the configuration files. MySQL uses the datetime set in the config file for each db connection unless the user specifies a different timezone after connection is started with the command SET time_zone = [timezone];. PHP also sets a timezone environment variable for each script using the timezone set in the server config file, and this environment variable can be overriden using the PHP function date_default_timezone_set() after the script starts.
The PHP DateTime class has a property called timezone, which is a PHP DateTimeZone object. The DateTimeZone object is specified using a string for the exact time zone. The list of timezones is comprehensive, having hundreds of individual time zones across the world. The PHP time zones will account for daylight savings time automatically.
When the user generates a datetime in the web app, construct a PHP datetime object in the timezone of the user's profile. Then use the setTimezone method to modify the DateTime object to the UTC timezone. Now you have the user's datetime in UTC, and you can store the value in the database. Use the DateTime format method to express the data as a string in the format accepted by MySQL.
So the user generates a datetime, and you make a PHP datetime object in the user's specified timezone:
// set using an include file for user profile
$user_timezone = new DateTimeZone('America/New_York');
// 1st arg in format accepted by PHP strtotime
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone);
$date_object1->setTimezone(new DateTimeZone('UTC'));
$formated_string = $date_object1->format('Y-m-d H:i:s');
$query_string = "INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')";
When you retrieve the value from the database, construct in UTC and then convert to the user's time zone.
$query_string = "SELECT `datetime1` FROM `t_table1`";
$date_object1 = new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'));
$date_object1->setTimezone($user_timezone);
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a');
Using this method, your datetime values are always stored in UTC inside the db, and the user always experiences the values in his/her profile's time zone. PHP will correct for Daylight Savings Time if necessary for each time zone.
One gotcha: This explanation does not cover the MySQL timestamp datatype. I recommend using the MySQL datetime datetype to store datetime values, not the timestamp datatype. The timestamp datatype is covered in the manual here.
Edit:
You can produce an array containing every PHP timezone string using listIdentifiers, which is a static method of the DateTimeZone class.
In MySQL, what you need to do is:
Store each user's chosen timezone someplace you can retrieve it when you're doing database queries on behalf of that user. You can store it as a string.
Right before you do work on behalf of a particular user (for example, storing or retrieving appointment times and dates) do SET time_zone = (stored time zone setting)
This will cause time zones to be converted appropriately to each person's local time.
Edit:
This works because
MySQL tries to use UTC (universal time, formerly known as Greenwich Mean Time) to store DATETIME and TIMESTAMP data items in tables.
It can only do this correctly if it knows the correct local time zone for each data item it is given by applications.
In applications that don't care about different time zones, it does this in a MySQL-server-wide way. See https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html . Most people who run multi-national and multi-time-zone applications set their server time zones to UTC, not to local time, because it makes it much easier to keep things sorted out.
It makes very little sense to try to convert a time from UTC to local time unless you also know the date and the timezone, because local time switches on and off at various times of year. Just try to get this right for all three of Israel, Arizona, and New York, I dare you! Israel switches between daylight and standard time on Passover and Rosh Hashanah; Arizona doesn't switch, and New York switches at the whim of the US federal legislature.
There's a session-scope time_zone setting (SET time_zone = something). If you don't set it, it uses the timezone representation in item 3 above. If you set it, the server will use this as the timezone to convert its internal representation to the representation it sends back in queries.
You can get a list of the names of the available time zones in your MySQL server by issuing SELECT Name from mysql.time_zone_name. This can populate the pulldown menu from which your user can select her time zone. If this query returns no items, take a look at bottom of https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html .
So, that means you can set your session time_zone setting to a particular user's time zone, and then get back all times in that user's time zone. Also, any DATETIME or TIMESTAMP items you INSERT or UPDATE will be converted from that user's time zone to MySQL's internal representation as they are placed in your tables.
Be careful: in web applications with persistent MySQL connections, the work for a new user request will inherit the connection's time_zone setting. Don't forget to reset it for the new user.
If you're running a query returning local time data for more than one user, and those users happen to be in different time zones, you can't take advantage of this MySQL per-session feature set. You can work around this by running different queries for different users and changing the time_zone setting between them.
Or, you can use the MySQL function
CONVERT_TZ(datetime,'UTC','user_time_zone')
or similar on each item.
Alternatively, Java and DotNET have their own high-quality time zone manipulation systems. So, you can make the choice of running your MySQL server with the time_zone setting of UTC, and do all your timezone conversions in your application.

Changing MySQL server timing for one website

I have one website which does not use US timings. Is it possible to change PHP and MySQL timings for one website? If so what do I need to do?
you can do it per connection , when you start connection to this website set it,
look at :
http://dev.mysql.com/doc/refman/5.6/en/time-zone-support.html
#
Per-connection time zones. Each client
that connects has its own time zone
setting, given by the session
time_zone variable. Initially, the
session variable takes its value from
the global time_zone variable, but the
client can change its own time zone
with this statement:
mysql> SET time_zone = timezone;
but be aware that :
The current session time zone setting affects display and storage of
time values that are zone-sensitive.
This includes the values displayed by
functions such as NOW() or CURTIME(),
and values stored in and retrieved
from TIMESTAMP columns. Values for
TIMESTAMP columns are converted from
the current time zone to UTC for
storage, and from UTC to the current
time zone for retrieval.
The current time zone setting does not
affect values displayed by functions
such as UTC_TIMESTAMP() or values in
DATE, TIME, or DATETIME columns. Nor
are values in those data types stored
in UTC; the time zone applies for them
only when converting from TIMESTAMP
values. If you want locale-specific
arithmetic for DATE, TIME, or DATETIME
values, convert them to UTC, perform
the arithmetic, and then convert back.
an example how to set is in :
http://www.electrictoolbox.com/mysql-set-timezone-per-connection
For PHP:
<?php
date_default_timezone_set('Europe/London');
?>
See the list of PHP supported timezones here: http://www.php.net/manual/en/timezones.php
For MySQL you'll need to execute query like this:
SET time_zone = timezone;
See detailed information in the MySQL documentation: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html
Yes, you should do all time zone conversions inside PHP, not mysql.
For each column in your database which stores a date/time, either
a) Store it in GMT and do the necessary conversion OR
b) Store it in local time always
In neither case does MySQL need to know, but your developers do so be sure that you document this in your schema if you have a mixture.
It is often necessary to store local time date/time values. MySQL does not remember a time zone in a datetime column (nor could it easily; other DBs attempt to in some cases).
If you are storing a precise point in time which has already happened (e.g. now) then you should always store it in UTC to avoid confusion about when exactly it happened. Some apps use epoch / unix time for this purpose.
A future time you may have to store in local time because you can't tell (yet) exactly what time it will have to happen, that may depend on the decision of politicans who might not have been elected yet.
Time zones are tricky things because politicians control them. They tend to change with little warning (typically only a few years)

Dealing with PHP server and MySQL server in different time zones

For those of us who use standard shared hosting packages, such as GoDaddy or Network Solutions, how do you handle datetime conversions when your hosting server (PHP) and MySQL server are in different time zones?
Also, does anybody have some best practice advice for determining what time zone a visitor to your site is in and manipulating a datetime variable appropriately?
As of PHP 5.1.0 you can use date_default_timezone_set() function to set the default timezone used by all date/time functions in a script.
For MySql (quoted from MySQL Server Time Zone Support page)
Before MySQL 4.1.3, the server operates only in the system time zone set at startup. Beginning with MySQL 4.1.3, the server maintains several time zone settings, some of which can be modified at runtime.
Of interest to you is per-connection setting of the time zones, which you would use at the beginning of your scripts
SET timezone = 'Europe/London';
As for detecting the client timezone setting, you could use a bit of JavaScript to get and save that information to a cookie, and use it on subsequent page reads, to calculate the proper timezone.
//Returns the offset (time difference) between Greenwich Mean Time (GMT)
//and local time of Date object, in minutes.
var offset = new Date().getTimezoneOffset();
document.cookie = 'timezoneOffset=' + escape(offset);
Or you could offer users the chioce to set their time zones themselves.
Store everything as UTC. You can do conversions at the client level, or on the server side using client settings.
php - date
mysql - utc-timestamp
RE the answer from Željko Živković, timezone descriptors like 'Europe/London' only work if the mySQL admin has added the timezone tables to the system, and keeps them updated.
Otherwise you are limited to numeric offsets like '-4:00'. Fortunately the php date('P') format provides it (as of 5.1.3)
So in say an app config file you might have
define('TZ', 'US/Pacific');
....
if (defined('TZ') && function_exists('date_default_timezone_set')) {
date_default_timezone_set(TZ);
$mdb2->exec("SET SESSION time_zone = " . $mdb2->quote(date('P')));
}
This means PHP and mySQL will agree on what timezone offset to use.
Always use TIMESTAMP for storing time values. The column is actually stored as UNIX_TIME (epoch) but implicitly converted from current time_zone offset when written, and back when read.
If you want to display times for users in other time zones, then instead of a global define(), set their given timezone in the above. TIMESTAMP values will be automatically converted by mySQL by the time your app sees the result set (which sometimes can be a problem, if you need to actually know the original timezone of the event too then it needs to be in another column)
and as far as, "why not just store all times as int's", that does lose you the ability to compare and validate dates, and means you always have to convert to date representation at the app level (and is hard on the eyes when you are looking at the data directly - quick, what happened at 1254369600?)
I save all my dates as a bigint due to having had issues with the dateTime type before. I save the result of the time() PHP function into it, now they count as being in the same timezone :)
In php set timezone by in the php.ini file:
ini_set("date.timezone", "America/Los_Angeles");
or in particular page you can do like:
date_default_timezone_set("America/Los_Angeles");
In mysql you can do like:
SET GLOBAL time_zone = 'America/Los_Angeles';

Categories