【问题标题】:MySQL; SELECT all records from yesterday (midnight to midnight) using a location's timezone [duplicate]MySQL;使用位置的时区选择昨天(午夜到午夜)的所有记录[重复]
【发布时间】:2016-08-08 20:30:21
【问题描述】:

如何为特定位置的时区选择昨天(从午夜到午夜)的所有记录(时间戳均以 UTC 和位置命名的时区 - 例如美国/温哥华)?

请注意,我不是在询问如何将日期和时间转换为另一个时区。我要问的是如何 [best] 本地化日期范围比较。

【问题讨论】:

  • 您可能需要查询。请告诉我们您尝试了什么以及出了什么问题。
  • 我还没有查询;我不太确定从哪里开始。
  • 我不认为它是重复的。我需要一个考虑时区的 INTERVAL 过滤器。我不只是将时间从一个时区转换到另一个时区。
  • 您正在从 UTC 转换为时区和一个简单的时区。我想,你知道如何使用 between。
  • 如果您给我一个工作示例查询,我会将其标记为正确答案。

标签: mysql timezone


【解决方案1】:

假设您的 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

【讨论】:

  • 如果表中每一行的时区转换不一致,或者至少查询返回的每一行不一致,则需要进行重大修改。 (在裸表列上保留 where 子句谓词使 MySQL 可以对合适的索引使用范围扫描操作。)如果 MySQL 数据库会话的 time_zone 未设置为 UTC 或 +00:00,则使用相同的方法可能会起作用,用@@session.time_zone 代替文字'UTC'......不保证......需要进行测试。 (不确定将 time_zone 设置为 SYSTEM 时会发生什么。)
猜你喜欢
  • 1970-01-01
  • 2020-09-30
  • 2021-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
相关资源
最近更新 更多