2010-03-26 71 views
32

問候所有(從MySQL初學者)MySQL的CONVERT_TZ()

我想設置爲用戶指定存儲日常警戒次的數據庫。例如,如果在上午7:00到上午7:30之間每天都滿足一些標準,則用戶希望收到警報。爲了實現這一點,我需要適應夏令時。下面是我嘗試的解決方案:

  1. 存儲用戶本地時區(以長格式,例如「美國/東航」)在一個表(比如用戶信息)的信息,而在另一臺報警時間(說userAlarms)。
  2. 當查詢userAlarms表時,將UTC時間轉換爲用戶本地時間,如通過CONVERT_TZ(UTC_TIME(), 'UTC', userInfo.tz)存儲在userInfo表中的tz列所指定的那樣。

問題1.從我的理解,並指定時區名稱(如美國/東方)採取夏令時考慮在內。例如,1月1日呼叫CONVERT_TZ('00:00:00', 'UTC', 'US/EASTERN')應該產生'19:00:00',但7月1日該呼叫應該產生'20:00:00'。我對麼?

問題2.如果Q1是正確的,我是否需要不斷更新MySQL的時區表以保持時區UTC偏移量最新?

問題3.在我的服務器上運行時,MySQL文檔SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')中給出的示例產生「NULL」。這可能是由於沒有設置時區表引起的嗎?我怎樣才能檢查這個?

回答

17

問題1:是的,CONVERT_TZ會爲您考慮夏令時。此信息以及DST開始/結束時間的時間都存儲在time_zone_ *表中。問題2:是的,正如mysql文檔中所述,時區信息根據每個區域的政治變化而變化。每次發生更改時,您都必須更新time_zone_ *表。有時候吮吸IT,這是其中之一。

Q3:這是5個時區表,查詢他們看他們是否有其中的任何東西:

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; 
+1

它給我的「錯誤1046(3d000):沒有選擇數據庫」 – 2012-08-02 05:12:18

+1

您需要將輸出管道輸出爲字面意義上的「mysql -uroot mysql」 - mysql是二進制可執行文件,第二個mysql是數據庫名稱。 – philwinkle 2013-01-15 00:13:14

+0

或者'使用mysql;'首先在所有命令上使用這個db。或者直接:'SELECT * FROM mysql.time_zone;' – Razor 2015-07-30 08:00:14

20

我發現這個線程有幫助,並決定共享的文檔頁面導入此信息。我完全按照CentOS和RHEL中的指示進行操作,並且工作完美無瑕。我現在可以使用帶有「GMT」和「US/Eastern」參數的CONVERT_TZ函數。

從MySQL的文檔,這是如何導入MySQL的時區表信息:

http://dev.mysql.com/tech-resources/articles/4.1/time.html


對於基於Unix的系統上運行MySQL 4.1.3或更高版本的所有用戶(召回這在Windows系統上不起作用):

填入時區表。

爲此,請運行隨MySQL發行版提供的mysql_tzinfo_to_sql程序。 mysql_tzinfo_to_sql讀取操作系統時區文件並從中生成SQL語句。 SQL語句然後由mysql處理,以加載時區表。

要成功運行mysql_tzinfo_to_sql,一個需要知道服務器機器的操作系統時區的文件存儲;檢查名稱類似於/usr/share/zoneinfo的目錄。將命令行中的目錄名稱傳遞給mysql_tzinfo_to_sql,並將輸出發送到mysql程序。這是一個例子。

shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql 

注意:以上命令假定「mysql_tzinfo_to_sql」和「mysql」在您的路徑中。如果他們沒有,你需要像這樣提供完整的路徑到兩個命令運行時,或者切換到mysql的bin文件夾並使用命令:

shell> ./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -u root mysql 
+0

我需要重啓MySQL守護進程才能生效(在Debian上)。 – Ekster 2014-07-17 08:51:30

24

如果這會產生null,則TZ表尚未建立:

SELECT CONVERT_TZ(now(),'US/Eastern','US/Central'); 

如果沒有時區表設置,你可以更新用戶表中的偏移小時 然後要這麼做:

select utc_timezone() - interval user_timezone_offset_in_hours hour 
from userinfo a 
where user_id = 999; 

呦但是,我仍然需要一種方法來更新用戶的時區。

如果你正在爲一個web應用程序編寫這個程序,你可以通過javascript獲取時區,這裏是一個article,它描述瞭如何(沒有嘗試過,但它看起來會工作)。

相對於「間隔」上面的解釋的位...

一個在MySQL越特技構建體是利用INTERVAL 關鍵字的,作爲示例的(數字值可以是最佳地示出表達式或字段值)

select now() today, now() - interval 1 day yesterday; 
+---------------------+---------------------+ 
| today    | yesterday   | 
+---------------------+---------------------+ 
| 2011-05-26 13:20:55 | 2011-05-25 13:20:55 | 
+---------------------+---------------------+ 

您可以添加他們,反正你喜歡減去他們,這就是爲什麼我從來沒有 的日期/時間理會加/減/轉換功能,

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 | 
+---------------------+---------------------+ 

您可以使用負數(應該是不錯的負時區偏移) 這些是相同的:

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 | 
+---------------------+---------------------+ 
+0

非常感謝!這是非常有用的〜 – Scarlett 2012-05-09 07:36:16

+0

不錯的答案!間隔+ convert_tz岩石! – 2012-06-23 19:52:50

+0

'user_timezone_offset_in_hours'是什麼? – 2017-10-11 14:22:25