我有一个名为'Sessions'的表,其中包含starts_at字段(datetime)。我想应用一个名为'starts_after'的过滤器,它返回在一天中某个时间后开始的所有会话(忽略日期,只查看会话时间)。所有时间都以UTC格式存储在数据库中。容易吗?但随后是时区。每个会话都属于一个事件,该事件具有与之关联的时区。现在我有:
time = Time.new('1','1','1','14','00,'00','-07:00)
Schedulables.where("DATE_FORMAT(CONVERT_TZ(schedulables.starts_at,'-07:00'), '%H,%i') >
DATE_FORMAT('#{time}', '%H,%i')")
然而,我只让Sessions回到我身边,他的开始时间是17:00或更高。还值得注意的是服务器时间在EST中,17:00到14:00之间的差异等于我服务器的时区(-4:00)和我在这里处理的时区之间的差异(-7: 00)。
答案 0 :(得分:0)
CONVERT_TZ()
需要三个参数。我只看到两个,所以它不清楚这个查询是如何工作的。
您的服务器时区应无关紧要。但是我猜测你的环境,知道时间值的时区和服务器的时区可能会隐含地将其转换为服务器时间,典型的"有用的" (阅读:通常无益)ORM风格。
在SQL中,您想要的查询比您正在构建的查询更简单,如下所示:
WHERE TIME(CONVERT_TZ(schedulables.starts_at,'UTC','-07:00')) >= TIME('14:00:00')
...假设你想要在14:00:00或之后开始的事情"本地"时间。 14:00:00只是TIME()
函数转换为时间字面值的字符串。
最好将两个值都转换为与DATE_FORMAT()
的输出进行词汇比较,尽管后者可能仍然是正确的。
如果你的环境是"修复"也可能是时间价值然后你可以" unfix"通过在服务器时间内声明它,例如Time.new('1','1','1','14','00,'00','-04:00)
,允许两个不正确的操作相互抵消......或者使用CONVERT_TZ()
转换为服务器时间而不是本地时间(因为您的时间值可能也被转换为服务器时间,静默)但这两个都是可怕的计划,因为日期时间的双重转换不是无损的。
请注意,如果没有其他因素限制要评估的行数,则您的方法无法扩展。通常,使用列值作为WHERE
子句中的函数的参数可能表现不佳,因为使用该列上的索引无法解析此类表达式,并且可能是全表扫描必需的。