2010-10-25 126 views
1

我继承了一个遗留应用程序,其中所有日期和时间都存储在本地时区(英国)中。我无法改变这些存储方式。检测日期是否在MySql的夏令时中

但是,要求是在应用程序中显示GMT中的所有日期。因此,当我从数据库中检索事件列表时,我需要它以全部时间格式显示它们,同时观察是否正在对每个特定事件日期进行夏令时操作。使用下面的逻辑,我可以决定是否实行夏令时的查询中活跃:

IF(CAST(TIMEDIFF(NOW(), UTC_TIMESTAMP()) AS SIGNED) >0, 
DATE_FORMAT(CONVERT_TZ(ADDTIME(`event_date`, IFNULL(`event_time`, '00:00')), '+01:00', '+00:00'), '%H:%i'), `event_time`) AS event_time 

不过,这显然只是检查其在被执行的日期。因此,任何跨越夏令时边界的事件都不起作用。

有没有一种方法可以检测给定日期是否在mysql查询本身的DST中?

任何帮助,非常感谢。

+1

你能不能使用CONVERT_TZ功能在MySQL?或者它没有给你正确的结果? http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_convert -tz – Dave 2010-10-25 10:43:16

+0

我在做。关键是我需要知道是否应用它。由于它存储在本地时间,其中一些是格林威治标准时间+ 1其他格林威治标准时间+0。我不能不加选择地将它应用于所有人。因此,我需要知道日期是否为+1 – 2010-10-25 11:13:14

+1

我的印象是,CONVERT_TZ基于time_zone_blah表的内容自动奇迹地考虑了夏令时,所以如果这些内容设置正确,您应该能够简单地做'CONVERT_TZ(event_time,“美国/东部”,“GMT”)'并让它在格林威治标准时间给出正确的时间 – Dave 2010-10-25 12:01:58

回答

1

时区未存储在DATETIME值中。有趣的是,它们是针对TIMESTAMP的。

给定一个存储日期,根据当地规则,你可以追溯到当时DST是否“开启”。由于您无法更改日期,因此我猜测您无法添加列来存储时区...

制作包含规则并将给定日期转换为GMT的存储过程。

请注意,只有居住在格林威治附近的人希望他们的时间以GMT显示。 :)

祝你好运。

+0

**不正确。**'TIMESTAMP'类型不*存储时区信息。恰恰相反:'TIMESTAMP'类型将输入值调整为UTC,然后丢弃原始时区信息。从[文档](https://dev.mysql.com/doc/refman/5.7/en/datetime.html)引用:* MySQL将TIMESTAMP值从当前时区转换为UTC存储,并从UTC返回到当前检索的时区。* – 2018-03-05 23:28:53

+0

对于凡人,UTC在功能上是一个时区。 – 2018-03-06 23:41:49

0

你在英国。所以,你的TZ应该是CET或CEST(中欧夏令时)。您可以通过这种方式获取信息:

mysql> SELECT @@system_time_zone; 
+--------------------+ 
| @@system_time_zone | 
+--------------------+ 
| CEST    | 
+--------------------+ 

我在许多存储过程中都使用了这个功能。注意:我需要两种形式的TZ信息,无论是否需要计算应用DST或不应用DST时的偏移量。

CASE @@system_time_zone 
    WHEN 'CET' THEN SET l_tz = 'Europe/Paris'; SET l_tzOff = '+1:00'; 
    WHEN 'CEST' THEN SET l_tz = 'Europe/Paris'; SET l_tzOff = '+1:00'; 
    WHEN 'SGT' THEN SET l_tz = 'Asia/Singapore'; SET l_tzOff = '+8:00'; 
    ELSE    SET l_tz = 'Europe/Paris'; SET l_tzOff = '+1:00'; 
END CASE; 

你可以从中得到一些启发。

0

发现了一个丑陋的复杂的方式,@DT输入日期&时间

Set @DT=20150329020304; # -> 0 

Set @DT=20150329030304; # -> 1(-0.0511) 

Set @DT=20150329040304; # -> 1(-1) 

Select 0!=(UNIX_TIMESTAMP(@DT)- UNIX_TIMESTAMP(Concat(Year(@DT),'0101',Time_Format(@DT,'%H%i%s')))-DateDiff(@DT,Concat(Year(@DT),'0101',Time_Format(@DT,'%H%i%s')))*86400)/3600 as DlsIsOn 
+0

我无法解释这是如何工作的......但它确实如此 – ChiMo 2016-03-23 05:35:31