Hi I'm using Rails 3 and want to get all rows that is updated in the last 30 minutes.
This is my current code:
Post.find(:all, condition: { updated_at: Time.now..Time.now-30.minutes })
But it returns every single rows, I also have tried this:
Post.find(:all, condition: [
"updated_at between ? AND ?", Time.now, Time.now - 30.minutes
])
It still return all rows.
I think the problem lies in the format difference.
updated_at format is like 2014-01-26T17:22:52+08:00
While Time.now format is like 2014-02-10 14:39:40 +0800
Any solution? Thanks
Post.where('updated_at > ?', 30.minutes.ago)
You can also try this:
Post.where('updated_at > ?', Time.now - 30.minutes )
Related
I need to query comments made in one day. The field is part of the standard timestamps, is created_at. The selected date is coming from a date_select.
How can I use ActiveRecord to do that?
I need something like:
"SELECT * FROM comments WHERE created_at BETWEEN '2010-02-03 00:00:00' AND '2010-02-03 23:59:59'"
Just a note that the currently accepted answer is deprecated in Rails 3. You should do this instead:
Comment.where(:created_at => #selected_date.beginning_of_day..#selected_date.end_of_day)
Or, if you want to or have to use pure string conditions, you can do:
Comment.where('created_at BETWEEN ? AND ?', #selected_date.beginning_of_day, #selected_date.end_of_day)
I would personally created a scope to make it more readable and re-usable:
In you Comment.rb, you can define a scope:
scope :created_between, lambda {|start_date, end_date| where("created_at >= ? AND created_at <= ?", start_date, end_date )}
Then to query created between:
#comment.created_between(1.year.ago, Time.now)
Hope it helps.
Rails 5.1 introduced a new date helper method all_day, see: 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
If you are using Rails 5.1, the query would look like:
Comment.where(created_at: #selected_date.all_day)
This code should work for you:
Comment.find(:all, :conditions => {:created_at => #selected_date.beginning_of_day..#selected_date.end_of_day})
For more info have a look at Time calculations
Note: This code is deprecated. Use the code from the answer if you are using Rails 3.1/3.2
I ran this code to see if the checked answer worked, and had to try swapping around the dates to get it right. This worked--
Day.where(:reference_date => 3.months.ago..Time.now).count
#=> 721
If you're thinking the output should have been 36, consider this, Sir, how many days is 3 days to 3 people?
Comment.find(:all, :conditions =>["date(created_at) BETWEEN ? AND ? ", '2011-11-01','2011-11-15'])
I have been using the 3 dots, instead of 2. Three dots gives you a range that is open at the beginning and closed at the end, so if you do 2 queries for subsequent ranges, you can't get the same row back in both.
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 []>
And, yes, always nice to use a scope!
If you only want to get one day it would be easier this way:
Comment.all(:conditions => ["date(created_at) = ?", some_date])
there are several ways. You can use this method:
start = #selected_date.beginning_of_day
end = #selected_date.end_of_day
#comments = Comment.where("DATE(created_at) BETWEEN ? AND ?", start, end)
Or this:
#comments = Comment.where(:created_at => #selected_date.beginning_of_day..#selected_date.end_of_day)
There should be a default active record behavior on this I reckon. Querying dates is hard, especially when timezones are involved.
Anyway, I use:
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
}
You could use below gem to find the records between dates,
This gem quite easy to use and more clear By star am using this gem and the API more clear and documentation also well explained.
Post.between_times(Time.zone.now - 3.hours, # all posts in last 3 hours
Time.zone.now)
Here you could pass our field also Post.by_month("January", field: :updated_at)
Please see the documentation and try it.
I'm trying to count all my policies that are'n expired >= that today
date_end >= TODAY
Here is my table
|policies|
|id| |num| |date_ini| |date_end|
1 12484 2013-04-01 2014-05-01
2 41511 2012-04-01 2013-05-01
3 14441 2013-05-01 2014-06-01
There are 2 values that aren't expired
Here is my controller
#policies =Policy.count(:conditions =>['date_end >= Date.now'])
I tried
#policies =Policy.count(:conditions =>['date_end >= Date.today'])
And also
#policies =Policy.count(:conditions =>['date_end >= curtime()'])
Please somebody can help me?
I will really appreciate help
It's not working because Date.today is inside a String, so it isn't being evaluated as an actual Date. You probably also want to use Date.current instead, to take the configured time zone into account.
Try this instead:
#policies = Policy.count( :conditions => ['date_end >= ?', Date.current] )
If date_end is stored as a DATE type of attribute, you can do this:
Policy.where("date_end >= ?", Date.today).count
or if it's stored as a string, just convert the Date.today to a string:
Policy.where("date_end >= ?", Date.today.to_s).count
The problem is that when you call out Date.today, you are returning the format "Fri, 15 Nov 2013" which will not compare to "2014-04-02". To get them in the same format, use
Date.today.to_s
I'm trying to create a created_at query range that will capture all records created from midnight UTC (db default) to now. In the past I've been able to query for time ranges with:
created_at => (24.hours.ago..Time.now)
But adjusting the above for the new use case does not work:
created_at => (Date.today..Time.now)
Any suggestions on how I can update the created_at range to be all records today / not in the last 24 hours?
Thanks
created_at => (DateTime.now.at_beginning_of_day.utc..Time.now.utc)
I think, you can try for below line as well.
ModelName.all :condition => ["DATE(created_at) = DATE(?)", Time.now]
OR In Rails 3
Model.where "DATE(created_at) = DATE(?)", Time.now
Cheers!
I think time zone should be considered.
where(:created_at => Time.zone.now.beginning_of_day.utc..Time.zone.now.end_of_day.utc)
And Rails will change time to utc time automatically, so the following is also ok.
where(:created_at => Time.now.beginning_of_day..Time.now.end_of_day)
Since Rails5.1, A new method Date#all_day was introduced, which returns a range of a day.
Instead of:
where(created_at: Date.today.beginning_of_day..Date.today.end_of_day)
An elegant way is:
where(created_at: Date.today.all_day)
Date.today.beginning_of_day.utc..Date.today.end_of_day.utc
I'm trying to query for records in the TimeSlot table by the field start_date which has type datetime. Here's what I've tried so far that's failed:
TimeSlot.where(:start_date => DateTime.new(2010, 9, 1))
TimeSlot.where(:start_date => DateTime.new(2010, 9, 1).to_s)
TimeSlot.where(:start_date => "2010-09-08")
TimeSlot.where(:start_date => "2010-09-08 00:00:00")
I'd appreciate any help.
Your queries look good to me.
Are you sure that you have a matching row in the db?
To debug, look in your logs/development.log file.
Added:
Problem could be timezones. Your query is using your server's timezone. Your data could be stored in a different timezone.
I'm betting it is a timezone thing as well. Everything in the DB is automatically converted to UTC by rails. Queries 1 and 4 should work if there isn't an offset.
Answer from rubyonrails.org
Client.where("created_at >= :start_date AND created_at <= :end_date",
{:start_date => params[:start_date], :end_date => params[:end_date]})
or
Client.where("created_at IN (?)",
(params[:start_date].to_date)..(params[:end_date].to_date))
Here is what I have for query all the TimeSlot start at "2010-09-08", if your start_date is a date field.
TimeSlot.where("start_date >= ? AND start_date <= ?", "2010-09-08", "2010-09-08")
If you start_date is a datetime field.
TimeSlot.where("start_date >= ? AND start_date <= ?", "2010-09-08", "2010-09-09")
Because the datetime start at 00:00:00
Have a model called contact_email.date_sent
I want to be able to run a report which displays all those where the date_sent range is between date.today and date.today 5 days ago.
I assume I use something like
#send_emails = Contact_Email.find(:conditions=> ???)
But not clear what exactly is the best way. Thanks!
Try this:
ContactEmail.all(:conditions => ["date_sent >= ?", 5.days.ago.to_date])
This approach is faster than using BETWEEN clause( assuming date_sent is indexed)
Caveat:
Value of date_sent column should be less than current date.
Edit 1
To add an index in migration:
add_index :contact_emails, :date_sent
ContactEmail.find(:conditions => ['date_sent BETWEEN ? AND ?', Date.today, 5.day.ago.to_date])
If it's something you will use regularly, why not put a named_scope in the model:
named_scope :recent, lambda { |*args| {:conditions => ["date_sent > ?", (args.first || 5.days.ago)]} }
which will let you write:
ContactEmail.recent
for the last 5 days worth, or use the arg to specify your own time frame e.g. the last two weeks:
ContactEmail.recent(2.weeks.ago)