MySQL CONVERT_TZ()
I am trying to set up a database that stores daily alert times as specified by users. For example, the user wants to receive an alert if some criterion is met each day between 7:00 AM and 7:30 AM. In trying to implement this, I need to accommodate daylight saving time. Here's my attempted solution:
- Store the users l开发者_如何学Cocal time zone (in long form, e.g. "US/Eastern") information in one table (say userInfo), and the alarm times in another table (say userAlarms).
- When querying the userAlarms table, convert UTC time into the users local time as specified by the tz column stored in the userInfo table via
CONVERT_TZ(UTC_TIME(), 'UTC', userInfo.tz)
.
Question 1. From my understanding, specifying the time zone name (like US/Eastern) should take daylight saving time into account. For example, calling CONVERT_TZ('00:00:00', 'UTC', 'US/EASTERN')
on January 1 should yield '19:00:00', but on July 1 the call should yield '20:00:00'. Am I correct?
Question 2. If Q1 is correct, do I need to constantly update MySQL's time zone table to keep the time zone UTC offsets up to date?
Question 3. The sample given in the MySQL documentation SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')
yields "NULL
" when run on my server. Could this be caused by not having the time zone tables set-up?
How can I check this?
If this yields null then the TZ tables have not been set up:
SELECT CONVERT_TZ(now(),'US/Eastern','US/Central');
If you do not have the time zone tables set up you could update the hour offset in the user table and then do:
select utc_timezone() - interval user_timezone_offset_in_hours hour
from userinfo a
where user_id = 999;
You'd still need a way to update the user's time zone however.
If you are writing this for a web application you can get the time zone via javascript, here's an article that describes how (haven't tried this but it looks like it'll work).
A bit of an explanation with respect to 'interval' above...
One of the more trick constructs in MySQL is the use of the INTERVAL
keyword, best shown by example the (numeric value can be an expression or the field value)
select now() today, now() - interval 1 day yesterday;
+---------------------+---------------------+
| today | yesterday |
+---------------------+---------------------+
| 2011-05-26 13:20:55 | 2011-05-25 13:20:55 |
+---------------------+---------------------+
You can add them and subtract them anyway you like, this is why I never bother with the date/time add/subtract/convert functions
select now() a, now() - interval 1 day + interval 4 hour + interval 8 minute b;
+---------------------+---------------------+
| a | b |
+---------------------+---------------------+
| 2011-05-26 13:24:16 | 2011-05-25 17:32:16 |
+---------------------+---------------------+
You can use negative numbers (should be good for negative time zone offsets) these are the same:
select now() - interval 1 month a, now() + interval -1 month b;
+---------------------+---------------------+
| a | b |
+---------------------+---------------------+
| 2011-04-26 13:38:05 | 2011-04-26 13:38:05 |
+---------------------+---------------------+
I found this thread helpful and decided to share the doc page for importing this information. I did exactly as instructed below in CentOS and in RHEL and it worked flawlessly. I am now able to use the CONVERT_TZ function with arguments like "GMT" and "US/Eastern".
From the MySQL documentation this is how to import the MySQL time zone table information:
http://dev.mysql.com/tech-resources/articles/4.1/time.html
For all users running MySQL 4.1.3 or later on a Unix-based system (recall this doesn't work on Windows systems yet):
Populate the time zone tables.
To do so, run the mysql_tzinfo_to_sql
program, provided with the MySQL distribution. mysql_tzinfo_to_sql
reads the operating system time zone files and generates SQL statements from them. The SQL statements are then processed by mysql, to load the time zone tables.
To run mysql_tzinfo_to_sql
successfully, one needs to know where the server machine's operating system time zone files are stored; check for a directory with a name similar to /usr/share/zoneinfo
. Pass the directory name on the command line to mysql_tzinfo_to_sql
, and send the output into the mysql program. Here's an example.
shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
Note: The above command assumes that "mysql_tzinfo_to_sql" and "mysql" are in your path. If they're not, you'll need to supply the full path to both when running the command, or switch into the mysql bin folder and use a command like so:
shell> ./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -u root mysql
Q1: Yes, the CONVERT_TZ takes daylight savings time into account for you. This information and the time that DST starts/ends for each time zone is stored in the time_zone_* tables.
Q2: Yes, as stated in the mysql docs, the time zone information changes per the politics of each area. You'll have to update the time_zone_* tables every time a change occurs. Sucks to be IT sometimes, this is one of them.
Q3: These are the 5 timezone tables, query them to see if they have anything in them:
select * from mysql.time_zone_transition_type;
select * from mysql.time_zone_transition;
select * from mysql.time_zone_name;
select * from mysql.time_zone_leap_second;
select * from mysql.time_zone;
精彩评论