What's the best way to manage dates across PHP, MySQL, etc? - php

My server is in Dallas. I'm in New York City.. and both PHP and MySQL have configuration variables for setting the timezone.
How do I get them all to work together? What dates should I store in MySQL? How do I get PHP to handle changing the date based on the user's preference?
Bear in mind: I don't think I'm ever having PHP explicitly set the date, it's always using "NOW()" in queries.. however I foresee the need to do this. How would this be done?
I'm hoping SO's experience can help me out here.

Use Unix Time everywhere. It's using UTC so it's the same for every timezone. Methods for dates usually convert to it and back from it using timezone information they have, so you would have yourself a correct time.
Alternatively you could use Unix Time only to transfer time from one computer to another (like from DB to your server running PHP, or to JavaScript client). There's functions to convert to it and from it in every language. For MySQL it is:
UNIX_TIMESTAMP(date)
FROM_UNIXTIME(unix_timestamp)
That way you could have your time properly formatted on the DB and in logs but still have correct local time everywhere.

I prefer using dates and times in the native form with respect to the environment, that is, Unix timestamps in PHP and DATE/TIME/DATETIME/TIMESTAMP fields in MySQL. I translate both values into another using FROM_UNIXTIME() and UNIX_TIMESTAMP(). I prefer this instead of Unix timestamps, because native dates/times are much easier to read.

Record your dates in GMT (zero offset) and then calculate the offset based on the local timezone (EST is +6, for example, so you'd add 6 hours to the GMT).
Check the Date docs for the date_default_timezone_set() function.
Just remember, when writing to the database, you'll have to change time zones, store the date, then change back. Likewise, when you're retrieving the date, don't forget to add the timezone offset.

The mysql-server stores dates in a timezone independent format (UTC).
But before it stores the date it will be converted using its timezone.
U can change the mysql timezone per connection *1:
mysql_query('SET time_zone = "'.$timezone.'"');
You can also change the timezone per script.
date_default_timezone_set($timezone);
If you set them to the same timezone "2009-01-10 13:30:00" will mean the same thing to both mysql and php.
But keep in mind that the 2 servers have different internal clock values, so if you want to generate timestamps based on current time. Do that in mysql OR php.
*1)
MySQL timezone support may require additional configuration. check the manual

Related

Best way to store date into Mysql for codeigniter application which have different time zone users

I am working on codeigniter application which have users from different time zones. Each user has some notifications based on some dates calculation.
So what should be best way to store date into Mysql? Either timestamp or datetime?
First off, you need to be aware of the locale setting for your mysql server. You want the server to be set to use UTC as a neutral setting. Any data that is stored in the mysql server will be relative to the server's timezone setting.
Unless you are dealing with future data (beyond the year 2032) or conversely really old data, the most efficient mysql datatype is the timestamp datatype. Just be careful to turn off the automatic mysql timestamp functionality when you don't want or need it.
Internally to PHP you want to utilize the DateTime class which includes ways to convert from any one timezone to another.
The missing ingredient that has not been mentioned, is that in order for this to work for end users, you need to store their timezone, or utilize functions in the browser to read from the operating system the current timezone of their workstation.
Timezone strings can be stored, and then used after you fetch data from the server, to then convert it and show it to them relative to their timezone.
But again to be clear, all data should be stored as UTC, and this requires that the server be configured to utilize UTC. Well it's a bit more complicated than that, but you can save yourself a lot of trouble when you insure there isn't a mismatch. By the same token your web/application servers (and in fact all servers) ought to be set to UTC, and of course to sync their time using NTP. Most cloud based servers are going to do this by default.
Format doesn't matter as long as you keep your date as DataTime Object. Using PHP you can easily manipulate dates. My personal choice is using UTC offset because is easier for debug purpose. You can easier figure out if your time difference calculation is correct looking on the offset then on time zone name.
More information you will find under DataTime class.
Implementation is basically the same regardless format as long as you are using DataTime Object. This is the best way to calculate time differences in different time zones.
With datetime you get a rich set of tools for interacting with the data (including converting between timezones) and the opportunity to handle dates prior to 1st Jan 1970 and after 19th Jan 2038.
Although the same tools are also applicable to TIMESTAMP, the automatic timezone conversion can get messy.
A further consideration is that TIMESTAMP also acquires some subtle timezone conversions which get rather messed up if you move to maxdb mode or back. Indeed, datetime data will be more portable across different systems.
It does not matter as long as you are using UTC value. However, timestamps are better way to store data from different timezones as it always represents and stored as the standard time(UTC) irrespective of the timezone of client/server.
But, as you are taking the data from user's input it does not make a difference.
For the accurate standard time(UTC), you just need to convert it right according to the user's timezone.
You can retrieve user's timezone either from browser headers(which is a less accurate method) or you can ask the user himself(using a input).

What is the best way to handle timezone on PHP & MySQL?

I am currently studying the best way to handle timezones on my website. People from many different countries will access it simultaneously, and I have to show them time-based information, so I thought:
Store every time on database according to my server (same timezone, defined by PHP)
Then, the user has the option to choose his timezone, and I do the needed conversions by using mysql function DATEADD.
This seems to work fine, but my questions are:
Is this the best way?
Is DATEADD the most efficient function to handle the hour difference?
Thanks.
As described in MySQL Server Time Zone Support:
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.
Therefore, if you use TIMESTAMP type columns, MySQL will handle timezone conversion for you automatically: just set the appropriate timezone for the session in its time_zone variable.
You are thinking in the right direction.
I would not use the server's timezone. Instead, use Coordinated Universal Time (UTC) time. It is the World Time Standard. This is pretty much the same as Greenwich Mean Time (GMT). Note that UTC does not change with Daylight Savings Time.
TO use in PHP see: http://php.net/manual/en/function.gmdate.php
From here, you can either add hours via: http://www.php.net/manual/en/datetime.add.php
Or set the timezone based on the users preference: http://www.php.net/manual/en/datetime.settimezone.php
The one you use is based on how you get the user's timezone. If you ask them for it (most accurate) you can set the timezone in PHP with the user selecting from a combo box. If you get it from the header with JavaScript using getTimezoneOffset(); then it is best to add hours based on the timezone offset.
I personally set all the times in my DB according to the GMT +0.00 timezone. So I use UTC_TIMESTAMP() (or UTC_DATE(),UTC_TIME() - whichever applies) when I want to add the current time, for example. This is server independent so I'm confident that even if I change my server I will not need to worry about this issue in the future.
Then the options are, if your visitors have a chance to pick their own timezones, you can use the DATE_ADD() and DATE_SUB() functions to format the result before providing results.
Otherwise if you have the chance (this is my favorite solution) you can use Javascript to format that date/time, which you can make it handle easily by something like
function getLocalDate(dt) {
var d = new Date(0);
d.setUTCSeconds(dt);
return d.toLocaleDateString();
// or in some format that you choose
}
which gets the date echoed by PHP using strtotime($row['some_date']);.

Managing timezones

I have gone through many timezone/PHP posts, and most suggest storing your datetime fields in UTC, then using the application users timezone offset when storing and displaying datetime information.
The problem i have I've inherited an application that wasn't timezone aware, and now I need to cater for this.
The server is already set to "EST +11:00 Australia/Melbourne", and there are already applications running from that server. So i can't change this.
Fortunately, I do know a users timezone offset, ie -05:00, etc,.
The application takes Javascript Dates and parses them using PHP's strtotime() function and stores in a MySQL database, like this:
$event_starts = date('Y-m-d H:i:s',
strtotime('Thu Dec 02 2010 11:15:00 GMT+1100 (AUS Eastern Daylight Time)');
So does anyone have any suggestions for the best way on how I can make this application timezone aware considering the server isn't set to UTC?
Many thanks, J.
This is not going to be very easy.
First of all, consider that existing stored dates are in local time of your server, which observes daylight saving time. Any code that has to do anything with these dates except just printing them, now or in the future, will need to convert them to UTC first. If the daylight saving rules are not exactly the same at the point in time where the date was stored and the current time (when the conversion is taking place), your server will use the "current" rules and therefore produce a wrong result. Granted, this scenario may be far-fetched in your specific case (or then again it might not), but it's a very strong warning against storing anything other than UTC.
Assuming that the DST rules remain constant, and that you have PHP >= 5.3.0, you can do this:
Read "original" database date with DateTime::createFromFormat, explicitly specifying the timezone (server's TZ)
Convert to user local time with DateTime::setTimezone (specifying user's TZ)
Display to the user
When receiving user input, you will need to do the reverse:
Create user local time date with with DateTime::createFromFormat, explicitly specifying the timezone (user's TZ)
Convert to server local time with DateTime::setTimezone (specifying server's TZ)
Store in database
Apart from the above, I would suggest taking your application offline at some point and convert all dates in the database to UTC. You would then be rid of the problem discussed earlier (at least in the future, as the past cannot be undone). The "server's TZ" I mention above would then be UTC (regardless of the fact that the actual server may be set to AUS EDT or not, your "working" timezone will be UTC).
You could make use of
1) date_default_timezone_set - Sets the default timezone used by all date/time functions in a script
2) Instead of using this function to set the default timezone in your script, you can also use the INI setting date.timezone to set the default timezone.
The important thing to keep in mind is not UTC, but that all times stored must be standardized to one timezone. So, if your PHP server and your database server both use the same timezone, the only issue that arises is when you need to display a location-aware time to the user or when you allow a user to enter a datetime from another timezone.
PHP has a nice, though somewhat scantly documented class, called DateTime. And some ancillary classes like DateTimeZone, DateInterval, etc. These make converting from db time to user time pretty simple.
So does anyone have any suggestions for the best way on how I can make this application timezone aware considering the server isn't set to UTC?
If you manage to come with any scheme for remapping the timezones its going to be horribly complicated and even more impossible to ever fix properly. Do yourself a favour and get the server timezone to UTC and fix your existing data.
First of allyou have to convert the date time selected by user to timestamp.
You have to use Server time zone offset and save the time to server in GMT.
This is the best way because while displaying the date just add the offset of the user
and convert and show.
I have implemented this for my client as it was an auction site and user may add item from AUS in his time and bidder will be from US. Time zone issues was there and we implemented after a lots of rerence.
You know one thing best and easy way is , do like ebay . just save the user time zone and show time with the time zone. No conversion nothing. Simple and better . 10:35 EST :)
If you wannabe perfect in time zone conversion, think about daylight saving time also. start date and end date on each year will change slightly. If you want to be accurate you have to save the daylight starting and ending date in db and add that difference too .:)
For working with datetime in different timezones and formats you can try to use PHP library Dater (https://github.com/barbushin/dater). Cheers!

What's the best way to adjust for local timezones?

Maye I am wrong to use now() to get timestamps when storing data?
When I display date/time to the user, of course he wants to see a local time, and if he inputs time related data, rather than me using now() then he will be inputting local date/time.
Why code is getting muddled with conversations - what's the best practice for handling timestamps? UTC/locla time? How & when to adjust?
Just store all the dates in timestamp mysql column type, which can handle all timezone issues, and mysql will do all work for you.
So in the begin of your application startup all you need is to specify what timezone you need the dates belongs towith query:
SET time_zone='Asia/Vladivostok'
For example.
Also, in this case you should not get any timestamps from php, if you need to insert current time - you have to use mysql's NOW().
That's all.
Store all the dates in one time zone so they're consistent. UTC/GMT+0 is good for this.
Then use CONVERT_TZ to convert input to UTC/GMT+0 or from UTC/GMT+0 to a user's time zone.
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
Since all you've asked about are SQL functions, you should tag the question with the RDBMS you're using (MySQL?) instead of PHP.

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