我继承了遗留应用程序,其中所有日期和时间都存储在本地时区(英国)。我无法改变这些存储的方式。
但是,要求是在应用程序中显示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中?
任何帮助,非常感谢。
答案 0 :(得分:1)
时区不存储在DATETIME值中。有趣的是,它们适用于TIMESTAMPs。
鉴于存储日期,您可以根据当地规则追溯当时DST是否“开启”。由于您无法更改日期,我猜您无法添加列来存储时区......
制作包含规则的存储过程,并将给定日期转换为GMT。
请注意,只有居住在格林威治附近的人希望他们的时间显示在GMT中。 :)
祝你好运。答案 1 :(得分:1)
作为替代方案,这里有一些功能可以确定北美夏令时规则是否有效。
截至2007年*,北美的rule是夏令时(DST):
* (从1987年到2006年,was是4月的第一个星期日到10月的最后一个星期日。)
DELIMITER // CREATE FUNCTION DSTstart(dt DATETIME) RETURNS DATETIME DETERMINISTIC BEGIN
RETURN cast(concat(year(now()),'-3-',(14-WEEKDAY(concat(year(now()),'-3-1'))),' 2:00') as datetime);
END// DELIMITER ;
DELIMITER // CREATE FUNCTION DSTstop(dt DATETIME) RETURNS DATETIME DETERMINISTIC BEGIN
RETURN cast(concat(year(now()),'-11-',(7-WEEKDAY(concat(year(now()),'-11-1'))),' 2:00') as datetime);
END// DELIMITER ;
DELIMITER // CREATE FUNCTION isDST(dt DATETIME) RETURNS BIT DETERMINISTIC BEGIN
RETURN (dt>=cast(concat(year(now()),'-3-',(14-WEEKDAY(concat(year(now()),'-3-1'))),' 2:00') as datetime))
AND (dt<cast(concat(year(now()),'-11-',(7-WEEKDAY(concat(year(now()),'-11-1'))),' 2:00') as datetime));
END// DELIMITER ;
仅供参考,我将包括该功能的VBA和Excel Worksheet版本:
Function DSTstart(dt As Date) As Date
DSTstart = CDate(Year(dt) & "-3-" & (15 - Weekday(CDate(Year(dt) & "-3-1"), 2)) & " 2:00")
End Function
Function DSTstop(dt As Date) As Date
DSTstop = CDate(Year(dt) & "-11-" & (8 - Weekday(CDate(Year(dt) & "-11-1"), 2)) & " 2:00")
End Function
Function isDST(dt As Date) As Boolean
isDST = (dt >= CDate(Year(dt) & "-3-" & (15 - Weekday(CDate(Year(dt) & "-3-1"), 2)) & " 2:00") _
And dt < CDate(Year(dt) & "-11-" & (8 - Weekday(CDate(Year(dt) & "-11-1"), 2)) & " 2:00"))
End Function
DST开始: (返回DST在[A1]
中的日期年份开始的日期/时间)
=DATE(YEAR(A1),3,15-WEEKDAY(DATE(YEAR(A1),3,1),2))+TIMEVALUE("2:00")
DST结束: (返回DST在[A1]
中的日期年份开始的日期/时间)
=DATE(YEAR(A1),11,8-WEEKDAY(DATE(YEAR(A1),11,1),2))+TIMEVALUE("2:00")
是否是DST? (如果TRUE
中的日期的DST有效,则返回[A1]
)
=AND(A1>=DATE(YEAR(A1),3,15-WEEKDAY(DATE(YEAR(A1),3,1),2))+TIMEVALUE("2:00"),A1<DATE(YEAR(A1),11,8-WEEKDAY(DATE(YEAR(A1),11,1),2))+TIMEVALUE("2:00"))
答案 2 :(得分:0)
你在英国。所以,你的TZ应该是CET或CEST(中欧夏令时)。您可以通过这种方式获取信息:
mysql> SELECT @@system_time_zone;
+--------------------+
| @@system_time_zone |
+--------------------+
| CEST |
+--------------------+
我在许多存储过程中使用它。注意:我需要两种形式的TZ信息,无论是否需要使用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;
你可以从中获得灵感。
答案 3 :(得分: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