【问题标题】:Rails ActiveRecord date betweenRails ActiveRecord 日期之间
【发布时间】:2011-01-23 19:32:50
【问题描述】:

我需要查询一天内制作的 cmets。该字段是标准时间戳的一部分,为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'"

【问题讨论】:

    标签: ruby-on-rails rails-activerecord ruby-on-rails-2


    【解决方案1】:

    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)
    

    【讨论】:

    • 光荣。这实际上是 ActiveSupport gem 的一部分(以及随后的整个 ActiveRecord 生态系统),所以它也可以在 Rails 之外工作!只需require 'active_record',一切就绪!
    【解决方案2】:

    请注意,当前接受的答案在 Rails 3 中已弃用。您应该这样做:

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

    或者,如果您想或必须使用pure string conditions,您可以这样做:

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

    【讨论】:

    • Day.where(:reference_date => 6.months.ago..Time.now) 有效,谢谢
    • 这不会创建一个巨大的范围对象吗?
    • @KasperGrubbe 如果你单独使用范围,它会,但 Rails 只使用第一个和最后一个值
    • @KasperGrubbe @Dex 这不是 Rails 做的。 Ruby 中的 Range 类只保存下限和上限。这在 irb 中运行良好:1..1000000000000 我不清楚你所说的“单独使用范围”是什么意思
    • +1 我们也可以将其设为范围:scope :between, -> (a, b) { where(created_at: a..b) }
    【解决方案3】:

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

    无论如何,我使用:

      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
      }
    

    【讨论】:

      【解决方案4】:

      我一直使用 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 []> 
      

      而且,是的,使用范围总是很好的!

      【讨论】:

        【解决方案5】:

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

        这个 gem 很容易使用和更清晰By star 我正在使用这个 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)

        请查看文档并尝试一下。

        【讨论】:

          【解决方案6】:

          有几种方法。你可以使用这个方法:

          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)
          

          【讨论】:

            【解决方案7】:

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

            在你的 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)
            

            希望对你有帮助。

            【讨论】:

            • 非常干净的方法...完美!!
            • 返回支持这个答案,因为我搜索了这个问题。猜错语法,假设 #between? 接受了一个范围。
            【解决方案8】:

            这段代码应该适合你:

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

            欲了解更多信息,请查看Time calculations

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

            【讨论】:

            • 好的,但从表格中我得到这个:{"written_at(4i)"=>"18", "written_at(5i)"=>"56", "content"=>"rrrrrr" , "written_at(1i)"=>"2010", "written_at(2i)"=>"5", "written_at(3i)"=>"4"} 如何构建一个对象来使用 begin_of_day?
            • 这是我需要的:purab.wordpress.com/2009/06/16/…
            • 我喜欢这种方法而不是接受的答案,因为它不依赖于 db 级别的 date() 函数;它可能更独立于数据库。
            【解决方案9】:

            我运行此代码以查看检查的答案是否有效,并且不得不尝试交换日期以使其正确。这行得通--

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

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

            【讨论】:

              【解决方案10】:
              Comment.find(:all, :conditions =>["date(created_at) BETWEEN ? AND ? ", '2011-11-01','2011-11-15'])
              

              【讨论】:

                【解决方案11】:

                如果你只想得到一天,这样会更容易:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-03-20
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-03-15
                  相关资源
                  最近更新 更多