选择TIMESTAMP字段时绕过MySQL自动GMT转换

时间:2016-06-28 18:06:54

标签: mysql datetime timezone timestamp utc

互联网上有很多关于转换MySQL时间戳,它是如何工作的东西等等。但我需要的是相反的:知道MySQL在TIMESTAMP字段中将每个日期时间数据存储为UTC,我想要的只是直接检索存储的没有MySQL的UTC值使用系统/服务器/连接时区弄乱日期时间。

你知道,我们已经构建了一个简单的node.js接收器,它从几个第三方MySQL数据库中读取(因此我无法更改其时区设置)并将收集的数据保存到Elasticsearch,作为“非规范化过程” ”。由于原始数据来自不同的时区,我需要将它们存储在UTC中,因此我可以轻松地协调进一步的GET和聚合。

我知道我可以动态设置连接时区,我知道我可以更改在我的节点应用程序中获取的每个时间戳字段,但由于MySQL引擎已经存储了UTC的时间戳,如果我可以简单地添加任何其他步骤直接获取它,而无需转换功能或昂贵的数据处理?

简而言之,我想知道:有没有办法绕过MySQL自动GMT转换?

2 个答案:

答案 0 :(得分:2)

MySQL提供了一个Cells(Range("C1000000").End(xlUp).Row + 1, 3).PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _ False, Transpose:=False 函数,它返回一个原始整数值。而且根本不受时区转换的影响。

UNIX_TIMESTAMP

但是返回一个原始整数,而不是日期时间。客户需要转换为" datetime"类型对象,如果需要的话。

另一种选择是使用SELECT UNIX_TIMESTAMP( timestamp_col ) ... 函数从会话time_zone设置转换为UTC。

CONVERT_TZ

但是,这并没有真正绕过"时区转换。这种方法的一个缺点是,如果会话time_zone受到夏令时变化的影响,那么当时钟"退回时,每年有一个小时的时间存在歧义。一小时。例如2015年11月1日星期日 2AM CDT 过渡到2015年11月1日星期日凌晨1点CST 。 (从UTC转换回来,如果我们在会话time_zone中凌晨1:30 ,我们就不会知道"如果是CDT或CST。转换回UTC并不知道它是哪一个。)

另一个选项(我认为您已经提到过)将会话 SELECT CONVERT_TZ( timestamp_col, @@session.time_zone,'+00:00') 更改为UTC。然后你可以只返回timestamp_col值作为UTC。您可以保存当前的time_zone设置,并在完成后将其设置回来,例如

time_zone

但是,当MySQL数据库会话的time_zone与客户端的time_zone不匹配时,您的客户端连接器可能会执行一些不太有用的转换,就像JDBC驱动程序(MySQL Connector / J)的时髦恶作剧一样。 。 (这种关注并不仅限于返回UTC;只要客户端的time_zone与数据库会话的time_zone不匹配,这就是一个问题。)

答案 1 :(得分:0)

看起来似乎无法从MySQL字段中获取原始UTC值;每个功能都使用时区设置,即SYSTEM或您配置的任何其他功能。

MySQL强迫您使用日期转换的方式至少是非常有限的。例如,假设您将MySQL服务器设置为GMT -03:00和GMT / DST -02:00的时区,并且您存储的日期时间类似于2016-07-01 10:00:00' 。如果您在夏令时结束后选择此值,您将获得2016-07-01 09:00:00'。

除非您单独存储GMT偏移量,或者您之前知道服务器存储时的时区,否则您无法确定确切的时间。

我们使用了第二种方法。我们保存了服务器时区并用它来计算偏移并返回ISO日期时间,因此可以很容易地进行未来的计算。

DROP FUNCTION IF EXISTS `iso_datetime`;;

CREATE FUNCTION `iso_datetime` (
    p_datetime TIMESTAMP
) RETURNS VARCHAR(25)

READS SQL DATA

BEGIN

    DECLARE _timezone VARCHAR(255) DEFAULT NULL;
    DECLARE _offset VARCHAR(6) DEFAULT NULL;

    SET _timezone = (SELECT timezone FROM network);
    SET _offset = (SELECT SUBSTRING(TIMEDIFF(p_datetime,CONVERT_TZ(p_datetime, _timezone,'UTC')), 1,6));

    RETURN CONCAT(DATE_FORMAT(p_datetime, '%Y-%m-%dT%H:%i:%S'), _offset);

END;

为了做到这一点,你必须将时区信息加载到MySQL中,这样服务器就可以为你计算日期的tz偏移量。