在我的应用程序中,我有一个 Person
模型。每个 Person
都有一个属性 time_zone
来指定他们的默认时区。我还有一个 Event
模型。每个 Event
都有一个 start_time
和 end_time
时间戳,以 UTC 时间保存在 Postgres 数据库中。
我需要创建一个查询,以查找某个人在一天午夜和下一天午夜之间发生的事件。 @todays_events
Controller 变量保存查询的结果。
我采用这种方法的部分原因是,我可能会让来自其他时区的人查看某个人的事件列表。我希望他们像普通人一样看待这一天,而不是基于他们作为观察者所在的时区。
无论出于何种原因,我在 @todays_events 的结果集中仍会收到前一天的一些事件。
我的猜测是我正在将 UTC 时间戳与非 UTC 参数进行比较, 或类似的规定。通常,只有前一天晚上开始或结束的事件才会出现在今天的查询结果列表中。
现在,我正在设置:
@today = Time.now.in_time_zone(@person.time_zone).midnight.to_date
@tomorrow = (@today + 1.day ).to_datetime
@today = @today.to_datetime
我的查询如下:
@todays_activities = @person.marks.where("(start_time >= ? AND start_time < ?) OR (end_time >= ? AND end_time < ?);", @today, @tomorrow, @today, @tomorrow ).order("start_time DESC")
我应该如何更改它以保证我只收到今天的结果(根据 @todays_activities
查询中的 @person.time_zone
?
最佳答案
当您调用 to_date
时,您会忘记您的时区所以不要那样做:
@today = Time.now.in_time_zone(@person.time_zone).midnight.utc
@tomorrow = @today + 1.day
当你some_date.to_datetime
,你得到一个 UTC 的 DateTime 实例,所以结果是这样的:
Time.now.in_time_zone(@person.time_zone).midnight.to_date.to_datetime
时间为 00:00:00,时区为 UTC; 00:00:00 是 @person.time_zone
中的正确时间但不适用于 UTC(当然,除非 @person
位于 +0 时区)。
您可以使用 overlaps
简化您的查询:
where(
'(start_time, end_time) overlaps (timestamp :today, timestamp :tomorrow)',
:today => @today, :tomorrow => @tomorrow
)
请注意 overlaps
works with half-open intervals :
Each time period is considered to represent the half-open interval
start <= time < end
, unless start and end are equal in which case it represents that single time instant.
关于ruby-on-rails - rails 3.1 : Querying Postgres for records within a time range,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8466903/