Rails ActiveRecordの日付


171

1日のコメントを照会する必要があります。フィールドは、標準のタイムスタンプの一部です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'"

回答:


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

4
これは巨大な範囲オブジェクトを作成しませんか?
Kasper Grubbe 2013年

3
@KasperGrubbe単独で範囲を使用した場合、Railsは最初と最後の値を使用するだけ
Dex

4
@KasperGrubbe @Dexそれを行うのはRailsではありません。RubyのRangeクラスは、上限と下限のみを保存します。これはirbで正常に実行1..1000000000000されます。「範囲を単独で使用する」という意味がわかりません
Connor Clark、

11
+1スコープにすることもできます: scope :between, -> (a, b) { where(created_at: a..b) }
rebagliatte

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.

この問題を検索したので、この回答に賛成投票してください。構文を誤って推測し#between?、範囲を受け入れたと仮定しました。
Tass

28

Rails 5.1では、新しい日付ヘルパーメソッドが導入されました。httpsall_day//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を使用している場合は、回答のコードを使用してください


わかりましたが、次の形式で取得します:{"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を使用するオブジェクトを構築するにはどうすればよいですか?
rtacconi

これは私が必要なものである:purab.wordpress.com/2009/06/16/...
rtacconi

2
この方法は、dbレベルのdate()関数に依存しないため、受け入れられた回答よりも気に入っています。潜在的には、よりdbに依存しません。
Craig Walker

10

私はこのコードを実行して、チェックされた答えが機能するかどうかを確認しました。日付を入れ替えて、正しい結果を得なければなりませんでした。これはうまくいった

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

出力が36である必要があると考えている場合は、これを考慮してください、サー、3日は3人で何日ですか?



5

私は2ではなく3つのドットを使用しています。3つのドットは、最初は開いていて、最後は閉じている範囲を提供します。そのため、後続の範囲に対して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

1日だけ取得したい場合は、この方法のほうが簡単です。

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は非常に使いやすく、より明確です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)

ドキュメントを参照して試してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.