假设您的 MySQL 数据库会话的时区是 UTC(即 time_zone='+00:00')...
并假设您想对所有行使用相同的时区(即,不是基于行内容的不同时区...
获取用户指定时区中“午夜”的值,并将其转换为 UTC。例如2016-04-16 00:00 CST6CDT(即美国/芝加哥)转换为 2016-04-16 05:00 UTC。
假设您的表列名为 utc_timestamp_col,并且是 TIMESTAMP 数据类型,您的查询将如下所示:
SELECT ...
FROM mytable t
WHERE t.utc_timestamp_col >= '2016-04-16 05:00' + INTERVAL -1 DAY
AND t.utc_timestamp_col < '2016-04-16 05:00' + INTERVAL 0 DAY
如果您已填充 MySQL 时区表,则可以利用 MySQL 对命名时区的支持。 http://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html
您可以构建一个表达式,让您在指定的时区中获得之前的“午夜”。
下面是一个示范查询:
- 验证会话 time_zone 是 UTC
- 以 UTC 格式返回当前日期和时间
- 转换为本地时区 CST6CDT
- 截断到午夜
- 转换回 UTC
例如
SELECT @@session.time_zone AS `time_zone`
, NOW() AS `now_utc`
, CONVERT_TZ(NOW(),'UTC','CST6CDT') AS `now_CST6CDT`
, DATE(CONVERT_TZ(NOW(),'UTC','CST6CDT')) AS `midnight_CST6CDT`
, CONVERT_TZ(DATE(CONVERT_TZ(NOW(),'UTC','CST6CDT')),'CST6CDT','UTC')
AS midnight_CST6CDT_utc
返回:
time_zone now_utc now_CST6CDT midnight_CST6CDT midnight_CST6CDT_utc
--------- ------------------- ------------------- ---------------- --------------------
UTC 2016-04-17 01:53:31 2016-04-16 20:53:31 2016-04-16 2016-04-16 05:00:00
使用名为“美国/芝加哥”的时区演示相同的内容
SELECT @@session.time_zone AS `time_zone`
, NOW() AS now_utc
, CONVERT_TZ(NOW(),'UTC','America/Chicago') AS `now_America/Chicago`
, DATE(CONVERT_TZ(NOW(),'UTC','America/Chicago')) AS `midnight_America/Chicago`
, CONVERT_TZ(DATE(CONVERT_TZ(NOW(),'UTC','America/Chicago')),'America/Chicago','UTC')
AS `midnight_America/Chicago_utc`
返回相同的结果:
time_zone now_utc now_America/Chicago midnight_America/Chicago midnight_America/Chicago_utc
--------- ------------------- ------------------- ------------------------ ----------------------------
UTC 2016-04-17 01:57:19 2016-04-16 20:57:19 2016-04-16 2016-04-16 05:00:00
跟进
如果我需要在查询中进行这种时区转换,我会使用内联视图从那个相当复杂的表达式中返回值,以使外部语句更简单。例如,别名为“d”的内联视图返回值作为名为“dt”的列,可以在外部查询中引用。
由于内联视图只返回一行,我们可以在 mytable 中使用JOIN 而不复制任何行。我们可以将谓词从 WHERE 子句移动到 ON 子句。例如
SELECT ...
FROM ( SELECT CONVERT_TZ(DATE(CONVERT_TZ(NOW(),'UTC','CST6CDT')),'CST6CDT','UTC') AS dt
) d
JOIN mytable t
ON t.utc_timestamp_col >= d.dt + INTERVAL -1 DAY
AND t.utc_timestamp_col < d.dt + INTERVAL 0 DAY