我有一个带有order_date
日期时间列的订单表。需要一个查询来获取特定时间范围内所有日期的记录。
示例:在东部时间早上7点到东部时间早上9点之间的所有日期获取订单。
类似的东西:
Order.where('time(order_date) BETWEEN ? AND ?', '7am', '9am')
开始和结束时间来自文本字段,用户可以在其中输入凌晨2点,下午3点,早上6点等字符串值
答案 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)
EXTRACT
您可以使用EXTRACT
从order_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_hour
和end_hour
是否有效值(例如-1小时无效)。
此方法很简单,但仅限于完整时间(您可以添加分钟和秒数,但方法会变得复杂)。
time
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')
。