Timestamps / Time Zones / PHP / MySQL - php

I have my Apache server and PHP set to date_default_timezone_set("America/Los_Angeles").
In MySQL I save TIMESTAMP fields with CURRENT_TIMESTAMP and some of them EXTRA as "on update CURRENT_TIMESTAMP".
Am I doing this the right way or am I loosing the whole point of TIMESTAMPS? I want the user to be able to choose their own timezone but it seems like it's saving the local timezone to the MySQL instead of a universal reference point.
Should I instead set the server timezone to UTC and in PHP date_default_timezone_set("America/Los_Angeles") or whatever the user timezone is and then save the values to the MySQL fields with something else than CURRENT_TIMESTAMP (which seems to vary depending on the php setting)?
Thank you!

Ideally you want your database to store data in UTC so that way it's not anchored to any particular geography. Incoming data from users is converted according to the user's time-zone, and anything you display can likewise be converted back to the user's preferred time-zone.
Some systems even go so far as to send UTC time over to the client in the HTML, but tag the element with something that JavaScript hooks on to and re-renders, client-side, with the appropriate local time.
It's best to have a user-specified setting that's persisted in their user record and/or session that defines what conversion, if any, should be done to the dates and times they're specifying or being shown.
It's also worth noting that TIMESTAMP fields are limited to the year 2038, so they're already living on borrowed time. It's best to use a more standard DATETIME field which has a much wider range of acceptable values.

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).

Web and Database server settings to get UTC timezone "right"

I'm overwhelmed trying to get this right: We've got servers located across a dozen time zones, with Apache and MySQL running on all or some of them, as well as MySQL hosted on Amazon RDS.
I want to know "Best Practices", or how to otherwise configure each MySQL and PHP installation so that when a row is added to the database from PHP I'm certain that the value there is actually the UTC time when the event happened, regardless of where the server is located when it happened. Presenting it to the user in any given timezone is not an issue - I just want to know that the datetime columns are actually storing the actual moment in time when something occurred.
As it is now, the Web Servers are set to whatever the local timezone is due to scheduled events, etc., and I'm not sure which parts of the puzzle use which settings from where to come up with whatever is written to the database.
I apologize if the question seems unclear, at this point I don't know what I don't know, so getting a precise question is even challenging. Also, all our dates are in the database as DateTime fields, so storing timestamps isn't possible.
If you restrict yourself to MySQLs DATE and DATETIME types, you can largely ignore time zone issues in MySQL itself. You want to avoid MySQL's TIMESTAMP type because:
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time.
https://dev.mysql.com/doc/refman/5.7/en/datetime.html
As far as reading/writing DATETIME values, you'll get back exactly what you put in, which is good.
That leaves you with the problem of always ensuring you are writing UTC values to the database.
The best way to ensure that PHP is using UTC is to explicitly set it in your application using date_default_timezone_set(). That will ensure that calls like date('Y-m-d H:i:s') will give you the UTC value. It will also ensure that something like (new \DateTime('now'))->getTimezone() will return a UTC \DateTimeZone instance.
You should note, of course, that things get significantly more difficult when you're storing date/time values that you take from users. In those cases, you'll need to somehow determine what timezone the user is in, and handle conversion to UTC before persisting the values. Assuming your users have some per-user timezone setting, you basically do something like:
/** #var \DateTimeZone $userTZ */
$userTz = getUserTimezone();
$dateTime = new \DateTime($user_submitted_date_string, $userTz);
$dateTime->setTimezone(new \DateTime('UTC'));
$dateTimeStr = $dateTime->format('Y-m-d H:i:s');
Quite simple, always store unix time in the database (or if you want microsecond accuracy with microtime ). Then regardless of the timezone of each of your webservers, if two of them recieve a request at the same time, it would be the same integer value that is saved in the database (the database field shoudl obviously be an int (or big int for micro time))
And how to display? Easy with javascript.
new Date(unix_timestamp);
This produces a date and time in the user's timezone.

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']);.

PHP/MySQL - confusion about storing timestamps

I need to store a timestamp for form submissions in a PHP/MySQL form. I would like to be able to query this field with the most flexibility for displaying the data in PHP. What MySQL datatype is best practice, and which PHP function should I use to store/retrieve the data?
I would store this data as TIMESTAMP data type provided by MySQL. This has lots of advantages over other storage options such as DATETIME or INT listed below
It is especially meant to store a particular time instant. No matter which time zone your server is in, and which time zone your mysql client is in, the value of constant CURRENT_TIMESTAMP stored in a TIMESTAMP field will always point to the same instant in the absolute time line.
Internally it uses 4 bytes of space for storage, same as that of an INT data type
It will give you pretty looking, human understandable values in regular queries.
Moreover, these pretty looking values are converted to the timezone of the client connecting to it. This might be good or bad for you. You can always change it to a desired one, including UTC, with set timezone='timezone' if the mysql time zone table is populated or similar to SET time_zone='+5:30'. The latter would work only if there are no daylight saving adjustments in the desired timezone.
Your queries can take the benefit of the fact that MySQL understands this field represents a date. So you could run query like: Get all the registrations happened on month of may for last 3 years.
Use inbuilt functions to change the display format to show unix timestamp or any other valid form.
Use DATETIME or DATE in your database: http://dev.mysql.com/doc/refman/5.6/en/datetime.html
What MySQL datatype is best practice, and which PHP function should I use to store/retrieve the data?
http://ch2.php.net/mysqli
dunno what timestamp you're talking about but for the unix timestamp you'll need INT type field.

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!

Categories