Rails ActiveRecord日期之间


171

我需要查询一天内发表的评论。该字段是标准时间戳记的一部分created_at。所选日期来自date_select

ActiveRecord该怎么做呢?

我需要类似的东西:

"SELECT * FROM comments WHERE created_at BETWEEN '2010-02-03 00:00:00' AND '2010-02-03 23:59:59'"

Answers:


402

请注意,Rails 3中不赞成使用当前接受的答案。您应该这样做:

Comment.where(:created_at => @selected_date.beginning_of_day..@selected_date.end_of_day)

或者,如果您想要或必须使用纯字符串条件,则可以执行以下操作:

Comment.where('created_at BETWEEN ? AND ?', @selected_date.beginning_of_day, @selected_date.end_of_day)

9
Day.where(:reference_date => 6.months.ago..Time.now)正常工作,谢谢
boulder_ruby 2012年

4
这会不会创建一个范围广泛的对象?
卡斯珀·格鲁布

3
@KasperGrubbe如果您单独使用范围,则Rails仅使用第一个和最后一个值
Dex 2014年

4
@KasperGrubbe @Dex不是Rails那样做的。Ruby中的Range类仅保存上下限。这在irb中运行良好:1..1000000000000我不清楚您是“ 单独使用范围”的意思
Connor Clark

11
+1我们也可以将其scope :between, -> (a, b) { where(created_at: a..b) }
设为

48

我将亲自创建一个范围,使其更具可读性和可重用性:

在Comment.rb中,您可以定义范围:

scope :created_between, lambda {|start_date, end_date| where("created_at >= ? AND created_at <= ?", start_date, end_date )}

然后在查询之间创建:

@comment.created_between(1.year.ago, Time.now)

希望能帮助到你。


4
非常干净的方法...完美!
约瑟夫N.14年

返回投票支持此答案,因为我搜索了这个问题。错误地猜测了语法,假定#between?接受了范围。
塔斯(Tass)2016年

28

Rails 5.1引入了新的日期帮助器方法all_day,请参见:https : //github.com/rails/rails/pull/24930

>> Date.today.all_day
=> Wed, 26 Jul 2017 00:00:00 UTC +00:00..Wed, 26 Jul 2017 23:59:59 UTC +00:00

如果您使用的是Rails 5.1,查询将如下所示:

Comment.where(created_at: @selected_date.all_day)

1
辉煌。实际上,这是ActiveSupport gem(以及随后的整个ActiveRecord生态系统)的一部分,因此它也可以在Rails之外工作!正义require 'active_record',您已经准备就绪!
鸭子大师

24

此代码应为您工作:

Comment.find(:all, :conditions => {:created_at => @selected_date.beginning_of_day..@selected_date.end_of_day})

有关更多信息,请查看时间计算

注意:不建议使用此代码。如果您使用的是Rails 3.1 / 3.2,请使用答案中的代码


好的,但是从表单中我可以得到:{“ write_at(4i)” =>“ 18”,“ writing_at(5i)” =>“ 56”,“ content” =>“ rrrrrr”,“ write_at(1i)” = >“ 2010”,“ write_at(2i)” =>“ 5”,“ writing_at(3i)” =>“ 4”}}我如何构建一个对象来使用Beginning_of_day?
rtacconi 2010年


2
我喜欢这个方法,而不是接受的答案,因为它不依赖于数据库级别的date()函数;它可能更独立于数据库。
Craig Walker

10

我运行了这段代码,以查看检查后的答案是否有效,并且不得不尝试在日期周围进行交换以使其正确。这个工作-

Day.where(:reference_date => 3.months.ago..Time.now).count
#=> 721

主席先生,如果您认为输出应该是36,请考虑一下,3天到3个人需要多少天?


6
Comment.find(:all, :conditions =>["date(created_at) BETWEEN ? AND ? ", '2011-11-01','2011-11-15'])

5

我一直在使用3个点而不是2个点。三个点为您提供了一个范围,该范围在开始时是打开的,而在结束时是关闭的,因此,如果您对随后的范围进行2次查询,则无法返回相同的行都。

2.2.2 :003 > Comment.where(updated_at: 2.days.ago.beginning_of_day..1.day.ago.beginning_of_day)
Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE ("comments"."updated_at" BETWEEN '2015-07-12 00:00:00.000000' AND '2015-07-13 00:00:00.000000')
=> #<ActiveRecord::Relation []> 
2.2.2 :004 > Comment.where(updated_at: 2.days.ago.beginning_of_day...1.day.ago.beginning_of_day)
Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE ("comments"."updated_at" >= '2015-07-12 00:00:00.000000' AND "comments"."updated_at" < '2015-07-13 00:00:00.000000')
=> #<ActiveRecord::Relation []> 

而且,是的,总是很高兴使用示波器!


4

如果您只想获得一天,可以这样轻松一些:

Comment.all(:conditions => ["date(created_at) = ?", some_date])

4

有几种方法。您可以使用以下方法:

start = @selected_date.beginning_of_day
end = @selected_date.end_of_day
@comments = Comment.where("DATE(created_at) BETWEEN ? AND ?", start, end)

或这个:

@comments = Comment.where(:created_at => @selected_date.beginning_of_day..@selected_date.end_of_day)

4

我认为应该有一个默认的活动记录行为。查询日期非常困难,尤其是在涉及时区的情况下。

无论如何,我使用:

  scope :between, ->(start_date=nil, end_date=nil) {
    if start_date && end_date
      where("#{self.table_name}.created_at BETWEEN :start AND :end", start: start_date.beginning_of_day, end: end_date.end_of_day)
    elsif start_date
      where("#{self.table_name}.created_at >= ?", start_date.beginning_of_day)
    elsif end_date
      where("#{self.table_name}.created_at <= ?", end_date.end_of_day)
    else
      all
    end
  }

1

您可以使用下面的gem查找日期之间的记录,

这个gem易于使用且更清晰通过使用此gem和API更加清晰明了,并且文档也得到了很好的解释。

Post.between_times(Time.zone.now - 3.hours,  # all posts in last 3 hours
                  Time.zone.now)

在这里你也可以通过我们的领域 Post.by_month("January", field: :updated_at)

请参阅文档并尝试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.