Rails ActiveRecord Datum zwischen


171

Ich muss Kommentare abfragen, die an einem Tag abgegeben wurden. Das Feld ist Teil der Standardzeitstempel, ist created_at. Das ausgewählte Datum stammt von adate_select .

Wie kann ich ActiveRecorddas machen?

Ich brauche so etwas wie:

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

Antworten:


401

Nur ein Hinweis, dass die aktuell akzeptierte Antwort in Rails 3 veraltet ist. Sie sollten dies stattdessen tun:

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

Wenn Sie reine Zeichenfolgenbedingungen verwenden möchten oder müssen , können Sie Folgendes tun:

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) funktioniert, danke
boulder_ruby

4
Würde dies nicht ein Objekt mit großer Reichweite erzeugen?
Kasper Grubbe

3
@ KasperGrubbe, wenn Sie den Bereich alleine verwenden würden, würde es, aber Rails verwendet nur den ersten und letzten Wert
Dex

4
@KasperGrubbe @Dex Das macht nicht Rails. Die Range-Klasse in Ruby speichert nur die unteren und oberen Grenzen. Dies läuft in irb gut: 1..1000000000000Ich bin mir nicht
Connor Clark,

11
+1 Wir können es auch zu einem Anwendungsbereich machen: scope :between, -> (a, b) { where(created_at: a..b) }
Rebagliatte

48

Ich würde persönlich einen Bereich erstellen, um ihn lesbarer und wiederverwendbarer zu machen:

In Ihrer Comment.rb können Sie einen Bereich definieren:

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

Dann zur Abfrage erstellt zwischen:

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

Ich hoffe es hilft.


4
Sehr sauberer Ansatz ... perfekt !!
Joseph N.

Zurück, um diese Antwort zu verbessern, da ich genau nach diesem Problem gesucht habe. Bei der Syntax falsch erraten, angenommen #between?, einen Bereich akzeptiert.
Tass

28

Rails 5.1 führte eine neue Datumshilfemethode ein all_day, siehe: 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

Wenn Sie Rails 5.1 verwenden, sieht die Abfrage folgendermaßen aus:

Comment.where(created_at: @selected_date.all_day)

1
Herrlich. Dies ist tatsächlich Teil des ActiveSupport-Edelsteins (und anschließend des gesamten ActiveRecord-Ökosystems), sodass es auch außerhalb von Rails funktioniert! Nur require 'active_record'und du bist fertig!
Meister der Enten

24

Dieser Code sollte für Sie funktionieren:

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

Weitere Informationen finden Sie unter Zeitberechnungen

Hinweis: Dieser Code ist veraltet . Verwenden Sie den Code aus der Antwort, wenn Sie Rails 3.1 / 3.2 verwenden


Ok, aber aus dem Formular erhalte ich folgendes: {"geschrieben_at (4i)" => "18", "geschrieben_at (5i)" => "56", "Inhalt" => "rrrrrr", "geschrieben_at (1i)" = > "2010", "ritten_at (2i) "=>" 5 "," geschriebenes_at (3i) "=>" 4 "} Wie kann ich ein Objekt erstellen, um begin_of_day zu verwenden?
Rtacconi

Dies ist, was ich brauche: purab.wordpress.com/2009/06/16/…
rtacconi

2
Ich mag diese Methode gegenüber der akzeptierten Antwort, weil sie nicht auf einer date()Funktion auf DB-Ebene beruht . Es ist möglicherweise db unabhängiger.
Craig Walker

10

Ich habe diesen Code ausgeführt, um festzustellen, ob die überprüfte Antwort funktioniert, und musste versuchen, die Daten zu vertauschen, um sie richtig zu machen. Das hat funktioniert--

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

Wenn Sie der Meinung sind, dass die Ausgabe 36 hätte betragen sollen, denken Sie daran, Sir, wie viele Tage sind 3 Tage für 3 Personen?


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

5

Ich habe die 3 Punkte anstelle von 2 verwendet. Drei Punkte geben Ihnen einen Bereich, der am Anfang offen und am Ende geschlossen ist. Wenn Sie also zwei Abfragen für nachfolgende Bereiche durchführen, können Sie nicht dieselbe Zeile zurückbekommen beide.

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 []> 

Und ja, immer schön, ein Zielfernrohr zu benutzen!


4

Wenn Sie nur einen Tag haben möchten, ist dies einfacher:

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

4

Es gibt verschiedene Möglichkeiten. Sie können diese Methode verwenden:

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

Oder dieses:

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

4

Ich denke, es sollte ein standardmäßiges aktives Datensatzverhalten geben. Das Abfragen von Daten ist schwierig, insbesondere wenn Zeitzonen betroffen sind.

Wie auch immer, ich benutze:

  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

Sie können unten Edelstein verwenden, um die Datensätze zwischen Daten zu finden,

Dieses Juwel ist recht einfach zu bedienen und klarer. Von Star verwende ich dieses Juwel und die API klarer und die Dokumentation auch gut erklärt.

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

Hier könnten Sie auch unser Feld passieren Post.by_month("January", field: :updated_at)

Bitte lesen Sie die Dokumentation und probieren Sie es aus.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.