我有一个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')
提前致谢。
答案 0 :(得分:2)
这可能是使用存储函数解析并将时间戳从存储格式转换为MySQL本机格式的最佳解决方案,使用内置日期时间数学函数来进行时区转换。
下面的函数将正确处理两种格式YYYY-MM-DDTHH:MM:SSZ
和YYYY-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');