2

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 I use date functions like DATE(NOW()).

The data stored in the MySQL database is stored in GMT-7 (Mountain Time Canada).

I have yet to register a domain/host for this web service but when I do lets say it is hosted in a different city such as Toronto (which is GMT-5 - 2 hours ahead). Then at 10:05pm Mountain Time Canada a user uses the application to send a web request call which has a query like:

SELECT DATE(NOW()) 

Because the server is hosted in Toronto, that will return tomorrow's date, even though where the user is it is the day before and the application shows data based on the current day.

Anyone have any ideas on this?

Edit:

SYSTEM
2015-01-29 16:19:48
2015-01-29 23:19:48

is the result of running the query select @@time_zone, now(), utc_timestamp()

The queries deal with date (yyyy-mm-dd) and time (hh:mm:ss) column type.

O. Jones
  • 103,626
  • 17
  • 118
  • 172
andrewb
  • 2,995
  • 7
  • 54
  • 95
  • possible duplicate of [How to set time zone of mysql?](http://stackoverflow.com/questions/930900/how-to-set-time-zone-of-mysql) – baao Jan 29 '15 at 23:07
  • Use `timestamp` column data type to store date values. Since it's UTC, the actual time zone will never matter. All you will have to do is obtain the time zone of the user who is using your database so you can format the time according to their time zone. – N.B. Jan 29 '15 at 23:39
  • So I would have to pass the offset from the mobile app to the web service? – andrewb Jan 29 '15 at 23:42
  • 1
    @RyanVincent - you're wrong on, well, everything. However, feel free to post an answer if you think you're right. Also, I'm hoping you're a smart guy and you I'd just like to politely let you know I've got 0 intention or will to get into internet argue with you so let's save both of our times and stop talking to each other after my post. – N.B. Jan 29 '15 at 23:58
  • 1
    @andrewb - correct, you can pass the time zone of your user to the web service or "ask" the device for the time zone once you use the time on the client side app. I'm not into mobile developmet, but in JavaScript I know how to obtain current time zone of the person using the site without passing that info to server. Many things are possible, but what's important is to save the time in common time zone and format on the DB. It makes timezone offsetting easy. – N.B. Jan 30 '15 at 00:00
  • One last thing how do I convert the result of UTC_TIMESTAMP() to the users timezone (lets say -7)? – andrewb Jan 30 '15 at 00:03
  • @RyanVincent - I'm not sure if you're pulling my leg here or what, but here it is: `Unix time (a.k.a. POSIX time or Epoch time) is a system for describing instants in time, defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970`. Does that clear up the confusion somehow? The big idea is to be able to save dates posted from various time zones and to be able to format those dates based on the time zone person is in. To do that, easiest way is to save time in a common time zone (UTC) and shift offsets. – N.B. Jan 30 '15 at 00:28
  • @RyanVincent - you're making a problem from something that isn't a problem in the first place. If you are in GMT + 5 and I am in GMT - 5 and we both save something like "Appointment in 12 hours" to the server, the server will store the time we gave it in UTC, so both your and my record will have time zone info stripped out of it. Now, when you show that time back to the user, you ask for their time zone. How you ask for it is irrelevant, you assume you'll have it (browser can give it out, user can be geolocated etc) - therefore you can format that timestamp according to their time zone. – N.B. Jan 30 '15 at 00:36
  • 1
    @N.B Sorry for the confusion on my part - i have learned a lot from the useful comments provided by the comments directed at my self. Thanks to you all for sharing your knowledge. I appreciate it. Seriously, I was wrong and have learned a lot. – Ryan Vincent Jan 30 '15 at 00:58

1 Answers1

4

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:

  1. Ask each user for a user-preference time zone, or figure it out from some other bit of personal data about the user. (Telephones have this information provisioned into them from the network.) Store that as a zoneinfo-friendly time zone descriptor ('America/New_York', 'Canada/Mountain', 'Europe/Vienna', etc) on the user's behalf.
  2. Upon establishing a MySQL session on behalf of the user, set the user's time zone with a set time_zone query like the one shown above. You should do this right after your connect operation.
  3. Store dates and times for users into TIMESTAMP data types. They'll get converted to UTC as they're stored.
  4. Retrieve them as needed. They'll get converted back to local time.

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.

O. Jones
  • 103,626
  • 17
  • 118
  • 172
  • I worked on a health-care system that stored everything in Eastern Standard Time. US Medicare has this thing called the "three-midnight rule" which governs whether they will pay for inpatient rehab. We came very close to miscomputing that rule at the end of some October for patients in Arizona (which doesn't switch back and forth from daylight to standard). This time stuff is, in New England lingo, wicked hard to get right. If you can get somebody else to do timezones for you, do it! – O. Jones Jan 30 '15 at 00:45