STR_TO_DATE和ISO8601 Atomtime格式

时间:2014-06-13 16:32:06

标签: mysql datetime atom-feed timestamp-with-timezone str-to-date

我有一个MySQL数据库,我无法改变,我从哪里读取日期。问题是我有一个存储日期的varchar列。日期以atomtime格式存储,例如。 2014-06-01T00:00:00+02:00

我无法确定如何在STR_TO_DATE函数中指定格式。我尝试了STR_TO_DATE(Endtime, '%Y-%m-%dT%H:%i:%s+02:00'),但这不起作用。

有人有解决方案吗?

我正在尝试运行以下查询(无法正常工作):

SELECT *, COUNT(*) as antal 
 FROM ivocall_calls
WHERE Agentname LIKE 'Vinh Nguyen'
  AND Status1 = 'SALG'
  AND STR_TO_DATE(Endtime, '%Y-%m-%dT%H:%i:%s+02:00') 
        BETWEEN STR_TO_DATE('2014-06-01T00:00:00+02:00', '%Y-%m-%dT%H:%i:%s+02:00') 
            AND STR_TO_DATE('2014-06-30T00:00:00+02:00', '%Y-%m-%dT%H:%i:%s+02:00')

提前致谢。

2 个答案:

答案 0 :(得分:2)

这可能是使用存储函数解析并将时间戳从存储格式转换为MySQL本机格式的最佳解决方案,使用内置日期时间数学函数来进行时区转换。

下面的函数将正确处理两种格式YYYY-MM-DDTHH:MM:SSZYYYY-MM-DDTHH:MM:SS+/-HH:MM以及正确形成的MySQL日期时间文字,这些格式将通过未经修改的方式传递。

DELIMITER $$

DROP FUNCTION IF EXISTS `from_iso8601_subset` $$
CREATE FUNCTION `from_iso8601_subset`(in_ts TINYTEXT) RETURNS DATETIME
DETERMINISTIC
NO SQL
BEGIN

-- this function takes an input timestamp value in a suppported subset of iso8601 values, and
-- and converts it to the equivalent MySQL datetime value, expressed in the current session's
-- time zone.  Since this is also the timezone that columns in the TIMESTAMP data type expect,
-- this causes the input value to be stored correctly in the native TIMESTAMP format, which is.
-- UTC under the hood.

-- if you are taking the value here and stuffing it into a DATETIME column, you need to have your
-- session @@time_zone set to the same zone in which that column should be stored, or use
-- CONVERT(from_iso('input value'),'UTC','Your Desired Time Zone');

-- 2014-02-01T23:59:59Z --

IF (in_ts REGEXP '^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}[T ][[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}(Z|[+-][[:digit:]]{2}:[[:digit:]]{2})$') THEN

  SET in_ts = REPLACE(REPLACE(in_ts, 'T', ' '), 'Z', '+00:00');
  RETURN CONVERT_TZ(SUBSTRING(in_ts FROM 1 FOR 19), SUBSTRING(in_ts FROM 20 FOR 24), @@time_zone);

-- unexpected format -- let MySQL's built-in functions do the best they can; this will throw warnings
-- if the input is not a yyyy-mm-dd hh:mm:ss datetime literal; alternately this could return NULL.

ELSE

  RETURN CAST(in_ts AS DATETIME);

END IF;

END $$

DELIMITER ;

示例输出:

mysql> SET @@time_zone = 'America/New_York';
Query OK, 0 rows affected (0.08 sec)

mysql> SELECT from_iso8601_subset('2014-06-01T00:00:00+02:00');
+--------------------------------------------------+
| from_iso8601_subset('2014-06-01T00:00:00+02:00') |
+--------------------------------------------------+
| 2014-05-31 18:00:00                              |
+--------------------------------------------------+
1 row in set (0.08 sec)

mysql> set @@time_zone = 'UTC';
Query OK, 0 rows affected (0.08 sec)

mysql> SELECT from_iso8601_subset('2014-06-01T00:00:00+02:00');
+--------------------------------------------------+
| from_iso8601_subset('2014-06-01T00:00:00+02:00') |
+--------------------------------------------------+
| 2014-05-31 22:00:00                              |
+--------------------------------------------------+
1 row in set (0.08 sec)

我们假设如果输入数据与其中一个模式匹配,那么传入的值的内容也将是合理的;如果您给出无意义的输入值,您将获得一些无意义的输出,例如,如果您使用的时区为“+99:00”但它不会失败。此函数没有任何SQL注入漏洞。

代码可以进一步优化,但正如所写,这个函数足够高效,它可以在中等功率的机器上每秒评估几千个表达式。

答案 1 :(得分:0)

改为使用unix_timestamp():

SELECT something, COUNT() as antal FROM ivocall_calls 
WHERE Agentname LIKE 'Vinh Nguyen' 
AND Status1 = 'SALG' 
AND unix_timestamp(Endtime) BETWEEN 
    unix_timestamp('2014-06-01T00:00:00+02:00' and unix_timestamp('2014-06-30T00:00:00+02:00');