Rails 4 ActiveRecord在时间之间查询

时间:2016-12-27 06:46:20

标签: ruby ruby-on-rails-4

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

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

类似的东西:

Order.where('time(order_date) BETWEEN ? AND ?', '7am', '9am')

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

4 个答案:

答案 0 :(得分:1)

试试这个

Order.where(order_date: Time.parse("7am")..Time.parse("9am"))

答案 1 :(得分:1)

使用MySql HOUR功能:

Order.where("HOUR(order_date) between 7 and 9")

在查询时注意您正在使用的时区!

答案 2 :(得分:1)

例如,这将在现在和1个月之前搜索订单:

Order.where('order_date < ?', Time.now).where('order_date > ?', Time.now - 1.month)

如果您需要将Time#parse之类的字符串转换为对象,请使用"9am"

irb(main):006:0> Time.parse('9 AM')
=> 2016-12-27 09:00:00 -0700

最终代码可能如下所示:

morning = Time.parse('9 AM')
# 2016-12-27 09:00:00 -0700

night = Time.parse('10 PM')
# 2016-12-27 22:00:00 -0700

Order.where('order_date > ?', morning).where('order_date < ?', night)


Order Load (0.2ms)  SELECT `orders`.* FROM `orders ` WHERE (order_date > '2016-12-27 16:00:00.000000') AND (order_date < '2016-12-28 05:00:00.000000')

答案 3 :(得分:1)

方法1:EXTRACT

您可以使用EXTRACTorder_date获取小时:

Order.where('EXTRACT(hour FROM order_date) BETWEEN ? AND ?', 7, 20)

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

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

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

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

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

方法2:显式转换为time

Ruby中的

Time存储了日期时间。例如:

Time.parse('15:30:45') # => 2017-01-02 15:30:45 +0100

您可以将Time传递给PostgreSQL并明确地将其转换为Postgres time类型:

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

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