mySQL 需要以 EST 显示时区,但无法更改全局时间设置

问题描述 投票:0回答:3

我面临一个奇怪的问题。 mySQL 中的全局时区设置采用 UTC。 mySQL的单个实例中有多个表(子数据库)(我使用database.NET作为管理器);所以我无法更改全球时区。

以下是我的询问。 我需要的只是显示东部时间的时间。我见过一些带有

@@sessionTimeZone
的解决方案,但它们不起作用。 此外,我还遇到了在美国东部时间晚上 9 点之前收集数据的问题,但在 UTC 中则为第二天凌晨 1 点

我的主要困惑是数据已经以UTC存储在表中;但是,我希望看到这些

datetime
字段显示在 EST 中。

cartId
是一个数值域
createDate
是日期时间字段

我只是使用 http://fishcodelib.com/database.htm 并连接到 mySQL 数据库。

SELECT   DATE(createDate)
    ,DATE_FORMAT(createDate, '%l%p') as HourOfDay
    ,count(cartId) as numCarts_ALL

FROM carts
WHERE createDate >= '2014-09-24' 
      AND createDate < '2014-10-01'
      AND HOUR(createDate) >= 10 AND HOUR(createDate) <21   
GROUP by DATE(createDate),HOUR(createDate)
;

我将非常感谢任何帮助。 再次感谢

mysql datetime timezone timezone-offset
3个回答
2
投票

DATETIME
数据类型不受全局或连接本地时区设置的影响。这只适用于
TIMESTAMP
数据类型。这就解释了为什么您尝试使用 @@session.TimeZone 进行修改没有任何效果。不过,
NOW()
CURDATE()
受到影响。

您说您的

DATETIME
数据存储在UTC中。那太好了。当您以这种方式存储数据时,生活会变得更加轻松。

在使用我即将给您的建议之前,请确保您的 MySQL 服务器已正确加载时区表。 执行此命令并确保您不会得到 NULL 结果。

SELECT CONVERT_TZ(NOW(), 'America/New_York', 'UTC')

如果这不起作用 - 如果您收到

NULL

 或错误 - 您需要让服务器人员加载时区表。他们应该这样做。他们知道怎么做。 (如果他们不这样做,您应该寻找新的服务提供商。)

我们需要使用名为“America/New_York”的时区,因为您可能希望在每年的适当日期在 EDT 和 EST 之间自动切换。

现在,要从表中检索正确转换的 UTC

DATETIME

 值,请执行以下操作:

SELECT CONVERT_TZ(createDate, 'UTC', 'America/New_York') AS createDate FROM yourTable

这很酷,因为如果您有位于不同时区的用户,您可以将时区设置设为用户首选项。

要将本地时间值存储为 UTC,只需相反操作即可。 例如。

INSERT INTO yourTable (createDate) VALUES (CONVERT_TZ(?, 'America/New_York', 'UTC'))

现在做

SELECT NOW()

并查看 NOW() 是当地时间还是 UTC。 如果是 UTC,那么您应该通过执行

SET TIME_ZONE='America/New_York'

 来开始会话。这将使您的时区设置正确,以便 
NOW()
CURDATE()
 做您想做的事。

然后,要从表中获取昨天(当地时间)的行,请执行以下操作:

WHERE createDate >= CONVERT_TZ(CURDATE(),'America/New_York','UTC') - INTERVAL 1 DAY AND createDate < CONVERT_TZ(CURDATE(),'America/New_York','UTC')

这会将当地时间午夜转换为 UTC 并获取项目范围。

要获取今天下午 4 点到明天凌晨 2 点的所有数据,您可以这样做:

今天下午 4 点(当地时间)是

CURDATE() + INTERVAL 16 HOUR

。明天凌晨 2 点是

CURDATE() + INTERVAL 26 HOUR
或者你可以写它
CURDATE() + INTERVAL 1 DAY + INTERVAL 2 HOUR

因此获取该范围需要这样:

WHERE createDate >= CONVERT_TZ(CURDATE() + INTERVAL 16 HOUR,'America/New_York','UTC') AND createDate < CONVERT_TZ(CURDATE() + INTERVAL 26 HOUR,'America/New_York','UTC')

如果您愿意组合普通日期对象和普通时间对象,还可以使用 
ADDTIME(CURDATE(),'16:00')

获取今天下午 4 点的

DATETIME
值。同样,你可以像这样得到明天凌晨 2 点:

ADDTIME(CURDATE(),'02:00') + INTERVAL 1 DAY

请注意,这种形式的 WHERE 子句允许对 
createDate

列上的索引进行范围扫描。这对于性能非常有好处。

    


0
投票

SELECT DATE(CONVERT_TZ(createDate, '+00:00', '-04:00')) createdDate, HOUR(CONVERT_TZ(createDate, '+00:00', '-04:00')) hourOfDay FROM carts WHERE createDate BETWEEN CURRENT_DATE + INTERVAL 16 HOUR AND CURRENT_DATE + INTERVAL 26 HOUR GROUP BY createdDate, hourOfDay

针对不同日期

SELECT DATE(CONVERT_TZ(createDate, '+00:00', '-04:00')) createdDate, HOUR(CONVERT_TZ(createDate, '+00:00', '-04:00')) hourOfDay FROM carts WHERE createDate BETWEEN '2014-09-24' AND '2014-10-01' GROUP BY createdDate, hourOfDay HAVING hourOfDay <= 2 OR hourOfDay >= 20

您可能会想“为什么不在 WHERE 子句中?”

如果where子句中使用了函数,则不能使用索引(会导致全表扫描)。所以只需过滤掉日期范围内的记录,以及 HAVING 子句中的小时即可

仅供参考

CURRENT_DATE + INTERVAL 16 HOUR

的缩写

DATE_ADD(CURRENT_DATE, INTERVAL 16 HOUR)



0
投票

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

然后添加文档底部

默认时区=“UTC+N” (就我而言,住在韩国: 默认时区=“+9:00”)

然后重新启动

© www.soinside.com 2019 - 2024. All rights reserved.