If you need your web application to translate between timezones on a per-user basis, why not use TIMESTAMP across the board for all date/time fields? Consider that TIMESTAMP values are stored in UTC and converted to the timezone set for the connection when retrieved.
I have asked this question on IRC, read the MySQL documentation, searched Google extensively, and asked my co-workers, and I have yet to find a compelling reason to not use TIMESTAMP.
Note: I understand TIMESTAMP has a limited range of 1970 - 2038; that is not going to be an issue in my case. Also, I am using PHP with MySQL.
DATETIME is for arbitrary dates and times that you utilize in your data.
TIMESTAMP is for when you want the time to be automatically updated. If you want to know when the row was inserted/updated, use a TIMESTAMP.
Also, keep in mind that a TIMESTAMP is only stored in UTC -- it is converted to the local timezone of the server before it is transmitted back as part of a query.
In your case, you're better off using a DATETIME. If you're worried about UTC, that's fine -- just create your dates in UTC rather than using the local time. Use UTC_TIMESTAMP.
I think your answer is here:
I understand TIMESTAMP has a limited range of 1970 - 2038; that is not going to be an issue in my case.
I would be careful making assumptions about the longevity of projects especially when it comes to database schemas. Databases have a tendency to remain in place and in use long after the applications that used them have gone away.
Randalpho's answer is wrong on many facts!
Timestamps do not need to be automatically updated on creation OR updates.
Also, timestamps are translated to the CLIENT's local time, not the serever's.
Just look at the MySQL docs for datetime.
Related
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).
I plan to capture the start and end of user initiated activities on my website using time() in php. I'm not sure if this is the best way to capture start/end times. Anyway, the data will be stored in MySQL, but again I'm not sure what datatype I should use.
Based on the answers I've read on stackoverflow, the datatype used depends on the purpose of the application.
Purpose of the application
At it's simplest, I want to record start, stop (and duration) of an
activity. Probably using time().
At it's most complicated I'd like to plot statistics based on when
the user did a certain activity, how much time they spent doing the
activity (in total), and when they were the most successful/least
successful etc, etc. (all based on the start/end times) Something to
keep in mind. The users will be from all over the world.
MORE INFO
If an activity is repeated a new record will be made for it. Records will not be updated.
At first, I had planned on storing unix timestamps in MySQL (as an integer datatype?), but from what I understand this is a bad idea, because I will lose a lot of MySQLs ability to process the information. If I store the information as DATETIME, but then move the server, all the times will change based on the local time of the server. Something I found confusing was that TIMESTAMP in MySQL is not the same as a unix timestamp- which is what I would be getting if I used time().
I'm aware that the unix timestamp can only hold dates up to 2038 for some systems, but that isn't a concern (at the moment).
Question: Should I use time() to capture start and end times for user initiated activities? Based on the purpose of the application, what datatype should I use to store the start and stop of user initiated activities?
THANKS
Thanks for the answers everyone. TBH I'm not convinced either way yet, so I'm still doing some research. I chose the TIMESTAMPS option because I really would like to store my information using UTC (GMT). It's a pity though that I will lose out on some of MySQLs inbuilt time functions. Anyway thanks again for your answers.
If you're going worldwide, MySQL's TIMESTAMP is almost universally a good choice over DATETIME, since it stores the time as UTC instead of local time so DST changes won't cause you problems if analyzing in multiple time zones.
Having a non DST changing time zone as a base can be a life saver, converting between multiple time zones with different DST changeover dates can really cause problems, consider for example having a timestamp during the hour that happens twice in a change from summer- to winter time.
Use DATETIME to store the time and use date('Y-m-d H:i:s') to get the current time to store it. When you fetch this value, you will get the time in this format.
To convert it to a timestamp, use $timestamp=strtotime($fetchedValue) To display this in another format use date('H:i',$timestamp). Read about formats from date manual of php
TIMESTAMP can only store values after Jan 1 1970, since it stores timezone data.
So if you are trying to store a date before Jan 1 1970, its better to use DATETIME.
Frankly, TIMESTAMP is useful only if you are actively syncing raw data between two machines with different timezone
When building PHP applications I always end up having trouble trying to get everything to play right with server times and timezones.
I generally have a simple timestamp-like field on most of my records that isn't updated - just static for reference purposes. I use it to track when events happened, when users registered, when comments were created etc.
I have been trying to follow the best practices of using a Datetime field to store this value. The problem is that when using different servers they often have different timezones so the datetime's don't match up even close unless I add more code to offset the differences. This can also be a problem when using MySQL replication and NOW() queries since their is often a lag.
I'm wondering if I should go back to using ints since they don't seem to care anything about timezones and only require the server clock is set. The downfall is that all those MySQL date/time functions (I never use) can't be used which might be a problem in the future. The upside is that I can cut the storage space in half by moving back to 4byte ints instead of datetimes.
People also mention that ints will only work until 2037 - why is that a problem? Who expects to be using PHP + MySQL in 2037?
Is there anything I am missing? Is it better to store reference times in an agnostic way like Unix timestamps?
I use date/time fields in all my database work but store everything in GMT. Pretty much the first opportunity my code gets it converts something into GMT, and does all its internal math in gmt, etc. The only time I convert it back out of GMT into local time is when displaying to the user. PHP has unixtime() which is GMT, plus gmstrftime and gmdate, pretty much anything you'll ever need.
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!
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