Rails 4 ActiveRecord 时间间隔查询

Ari*_*rif 6 ruby ruby-on-rails-4

我有一个带有order_date日期时间列的订单表。需要一个查询来获取特定时间范围内所有日期的记录。

示例:获取东部时间早上 7 点到东部时间上午 9 点之间所有日期的订单。

就像是:

Order.where('time(order_date) BETWEEN ? AND ?', '7am', '9am')
Run Code Online (Sandbox Code Playgroud)

开始和结束时间来自文本字段,用户可以在其中输入凌晨 2 点、下午 3 点、上午 6 点等字符串值

Gre*_*vis 5

方法一:EXTRACT

您可以使用EXTRACT以下方式获取小时order_date

Order.where('EXTRACT(hour FROM order_date) BETWEEN ? AND ?', 7, 20)
Run Code Online (Sandbox Code Playgroud)

请注意,我指定20(晚上 8 点)作为上限。如果我使用21thenorder_date与 21:30 的时间部分将匹配,这不是我们想要的。

您可以将上面的查询包装在一个范围内:

class Order < ActiveRecord::Base
  scope :between, -> (start_hour, end_hour) {
    where('EXTRACT(hour FROM order_date) BETWEEN ? AND ?', start_hour, end_hour - 1)
  }
end
Run Code Online (Sandbox Code Playgroud)

您可能还想解决一些其他问题,例如检查start_hourend_hour是否有效值(例如,一小时 -1 是无效的)。

此方法很简单,但仅限于完整的小时(您可以添加分钟和秒,但该方法会变得复杂)。

方法 2:显式转换为time

Time在 Ruby 中同时存储日期时间。例如:

Time.parse('15:30:45') # => 2017-01-02 15:30:45 +0100
Run Code Online (Sandbox Code Playgroud)

您可以传递Time给 PostgreSQL 并将其显式转换为 Postgrestime类型:

class Order < ActiveRecord::Base
  scope :between, -> (start_time, end_time) {
    where('order_date::time BETWEEN ?::time AND ?::time', start_time, end_time)
  }
end
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是灵活性。缺点是在 UI 中处理时间有点复杂。该范围需要一对Time对象。获得它们的方法有很多,例如:Time.parse('12:17')


Aja*_*rot 1

尝试这个

Order.where(order_date: Time.parse("7am")..Time.parse("9am"))
Run Code Online (Sandbox Code Playgroud)