I am developing a mobile application. From the application calls are made to a web service which runs different queries based on mode (?mode=xx)
In some of those queries
You ran this time-diagnostic query on your MySQL server.
select @@time_zone, now(), utc_timestamp()
It's clear from your local time and utc time that your server machine's system time zone setting is 'Canada/Mountain', and the MySQL server software doesn't have its own timezone setting.
If you pick up your tables and move them unchanged to a server in some nearby timezone, you can update your software always to issue the command
set time_zone = 'Canada/Mountain';
right after you connect from your software. This will make your new MySQL connection behave like your current one does time-zone-wise. If you own the MySQL server you can set its default time zone according to the directions on this page. http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html
Now, here's the story about time data types. DATE
, TIME
, and DATETIME
are all timezone-ignorant. Once you've stored a date/time value you'll get it back the same value even if you change your timezone settings.
The TIMESTAMP
data type is timezone-sensitive. Those data items are always stored in UTC, also known as Z, time, formerly known as Greenwich Mean Time. They're always converted to UTC upon being stored, and always converted back upon being retrieved.
The builtin functions for getting current date and time (NOW()
and friends) are timezone-sensitive. They'll yield values in local time. The exceptions are the three functions starting with UTC_
which yield values in UTC time.
Many MySQL multi-time-zone applications use the following operational discipline:
set time_zone
query like the one shown above. You should do this right after your connect
operation.TIMESTAMP
data types. They'll get converted to UTC as they're stored.The idea is that your user's timezone is part of her context. This works well, because if user A is in Vancouver and user B in Halifax, and for some reason user B views user A's time data, it will be shown to B in Atlantic time more-or-less automatically.
It's also good because it deals transparently with the global vagaries of daylight-to-standard time changing. A timestamp from last summer will be displayed in last summer's local time.
Many managers of servers for global use set their system server time, or their MySQL default time zone, to UTC. (Yours doesn't.)
Another way to handle all this is the way in which you've started. Pick a time zone and store your timestamps with respect to that time zone. It's best if you pick a timezone that doesn't alternate between daylight and standard time in that case. Then, when storing times into the database, convert explicity. You'd store times from users in Ottawa by doing something like this.
INSERT INTO tbl (appt) VALUES ( 'whatever-time' - INTERVAL 120 MINUTE)
and you'd get the values out the same way. This is error-prone but you can make it work.
Finally, you can do your conversions yourself. If you want to know how many minutes of offset there are between some arbitary timezone and UTC, try these two queries.
set time_zone = 'Canada/Atlantic';
select timestampdiff(minute, utc_timestamp(), now());
At this time of year that gives back -240, which is -4:00. You need to use minutes rather than hours because of half-hour or quarter-hour timezone offsets in some countries.
Finally, watch out. TIMESTAMP
data types don't represent times before 1970. And, on my MariaDB 10.0 instance it appears to go to hell in a bucket right after 2038-01-19T03:14:07 UTC when the time rolls over out of 32 bits.