【发布时间】:2013-10-27 10:30:17
【问题描述】:
我有一个存储“快照”数据的表 - 每 10 分钟捕获一次工作人员的数量并存储在其中。我想生成一份报告,以显示一天中特定工作日(例如过去四个星期日)的工作人员数量。
在 Rails 中,我的查询如下所示:
<model>.where("EXTRACT(dow FROM (time + interval '#{time_zone_offset} hours')) = ?", Time.zone.now.wday)
.where('time BETWEEN ? AND ?', 5.weeks.ago.end_of_week, 1.week.ago.end_of_week)
.select("organisation_id, date_trunc('hour', time) as grouped_time, avg(staff) as staff")
.group("grouped_time").order("grouped_time")
这转化为这条 SQL:
SELECT date_trunc('hour', time) as grouped_time, avg(staff) as staff
FROM <model>
WHERE (EXTRACT(dow FROM (time + interval '10 hours')) = 0)
AND (time BETWEEN '2013-09-22 13:59:59.999999' AND '2013-10-20 13:59:59.999999')
GROUP BY grouped_time
ORDER BY grouped_time
在这种情况下,time_zone_offset 会因我正在查找的用户而异:
def time_zone_offset
@tzoffset ||= ActiveSupport::TimeZone[current_user.organisation.time_zone].utc_offset / 60 / 60
end
(当前时区也在around_filter中设置,这样1.week.ago等就在正确的时区。)
我的数据库的时区是 UTC (set TIME ZONE 'UTC')。
这可行,但我确信有更好的方法可以在一周中的特定日期查找记录,然后手动操作interval。我也不认为这适用于适用的时区的 DST。我知道 PostgreSQL 可以使用converting a time with time zone to a particular time zone,但它不包括日期,所以我无法确定星期几!我尝试过的其他 WHERE 子句:
EXTRACT (dow from time') = 0- 这给了我周日上午 10 点到周一上午 10 点之间的快照EXTRACT (dow from time at time zone 'Brisbane/Australia') = 0- 这给了我周日晚上 8 点到周一晚上 8 点之间的操作。我的理解是,这是因为 Postgres 将time字段视为布里斯班时间,而不是将它从 UTC 转换为布里斯班时间。
所以我很想知道我是否应该做些什么来让这个查询正常工作。
【问题讨论】:
-
time列的数据类型是什么?插入行时 SQL 会话的时区 (show time zone) 是什么?是不是也被逼UTC? -
time是timestamp without time zone。 SQL 会话时区是“UTC”。 -
始终提供(相关部分)您的表定义,如 psql 中的
\d tbl为您提供。还有你的 Postgres 版本。添加一些示例数据,可选择在 SQLfiddle 中。
标签: sql ruby-on-rails postgresql timezone