사이의 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'"

답변:


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
이것이 거대한 범위의 객체를 생성하지 않습니까?
카스퍼 그루브

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
매우 깨끗한 접근 ... 완벽한 !!
Joseph N.

이 문제를 검색했기 때문에이 답변을지지하십시오. 구문에서 잘못 추측 #between?하여 범위를 승인 한 것으로 가정 합니다.
Tass

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'당신은 모든 설정입니다!
Masters Ducks

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이되어야한다고 생각한다면, 이것을 생각해보십시오.


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

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

하루 만 받고 싶다면 다음과 같이하면 더 쉬울 것입니다.

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은 사용하기 쉽고 더 명확합니다 . 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.