mysql HOUR()占用时区

时间:2015-12-18 20:17:12

标签: mysql sql timezone

我有一个查询返回按小时分组的结果,就像这样。

SELECT COUNT(*) FROM (`shipped_products`) WHERE HOUR(timestamp) = 8

问题是,我在localhost上获得的结果与在实时服务器上的结果不同。两者的数据完全相同(UTC)。我相信我的localhost数据库是纽约,而实时数据库是UTC,因此,HOUR()在这两种环境中的工作方式不同。我无权更改实时服务器时区,并且希望避免更改本地数据库时区。在查询中是否有一种方法可以确保HOUR()函数返回相同的结果而不管数据库时区?

3 个答案:

答案 0 :(得分:3)

试试CONVERT_TZ() function

SELECT COUNT(*) FROM (`shipped_products`)
WHERE HOUR(CONVERT_TZ(timestamp, 'UTC', 'America/New York')) = 8

手册警告:

  

注意

     

要使用'MET''Europe/Moscow'等命名时区,必须正确设置时区表。 See Section 10.6, “MySQL Server Time Zone Support”,有关说明。

您也可以使用小时值,但会丢失任何时区知识,例如历史时区更改,DST等。

SELECT COUNT(*) FROM (`shipped_products`)
WHERE HOUR(CONVERT_TZ(timestamp, '+00:00', '-05:00')) = 8

答案 1 :(得分:2)

您可以将会话时区(或全球时区)设置为UTC as described in the docs

set time_zone = '+00:00';

然后HOUR和其他函数将解释UTC中的timestamp类型。另请参阅timestampdatetime in this part of the docs之间的差异。

然而,另一个问题是WHERE HOUR(timestamp) = 8会使您的查询non-sargable,因此它必须扫描整个表格,并且无法利用任何索引你可能有。表中的记录越多,得到的速度就越慢。 (特别是如果你有数千或数百万条记录)。

更好的方法是将其重写为范围查询。获取您想要过滤的开始和停止时间,并使用半开间隔。

WHERE timestamp >= @start AND timestamp < @end

当然,在计算起始值和结束值时,您会将值锁定到特定日期。如果你确实想要每天每天的8:00 UTC小时,那么你应该在表上创建一个包含该信息的单独整数列,这样你就可以在一个可搜索的查询中使用它。

WHERE your_utc_hour_column = 8

这可能是某些数据库中的计算列,但我不认为MySQL支持这些列,因此您必须手动创建并填充它。

答案 2 :(得分:0)

虽然Matt Johnson有正确的答案,并且miken32在大多数情况下都有正确的答案,如果您发现自己无法更改数据库权限,无法上传时区表,无法执行SET语句,并且需要获得某些赢得的内容;在夏令时变化期间休息,以下情况将有效。

$corrected_hour = $hour;
if ($_SERVER['HTTP_HOST'] != 'localhost') 
{
    $dateTimeZoneNY = new DateTimeZone('America/New_York');
    $dateTimeZoneUTC = new DateTimeZone('UTC');
    $dateTimeUTC = new DateTime('now', $dateTimeZoneUTC);
    $timeOffset = $dateTimeZoneNY->getOffset($dateTimeUTC);
    $corrected_hour = $hour + abs($timeOffset) / 60 / 60;
}

只要两个数据库都保持其当前时区设置,就不会中断。