Rails Console - Find where created at = certain day - ruby-on-rails

With Ruby on Rails console, is it possible to query the database for all records created on a certain day?
something like
date = "january 5 2013"
users = User.find(:all, :conditions => {:created_at => date})

You can do it like this:
date = Date.parse('january 5 2013')
users = User.where(created_at: date.midnight..date.end_of_day)

Try this,
User.where("Date(updated_at) = ?", "2018-02-9")

You can also do it like
User.where("created_at::date = ?", "january 5 2013".to_date)

Yes, It is possible like:
date = Date.parse("january 5 2013")
users = User.where(created_at: date)
but created_at is type of date-time like 2014-01-28 08:35:00.9608
and I think All user have different created_at
So you may used like this
User.where("created_at = ?", "2014-01-23 16:19:48.199086")

If you see the follow link Don't use BETWEEN (especially with timestamps)
You will note that you can have problems.
Instead you can use
users = User.where('created_at >= ? and created_at <=?', date.midnight, date.end_of_day)
"SELECT \"users\".* FROM \"users\" WHERE (created_at >= '2018-05-17 07:00:00' and created_at <='2018-05-18 06:59:59.999999')"

Related

Using scope, How would I limit my Task model to only Tasks that are due today? I'm building a Tasks manager using Rails [duplicate]

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.

In Rails while using the `where` method, how to match only the year and month?

Normally, to select all the records with the same date we use something like this :
Bronze.where(regdate: Date.new(2014,03,03))
How can we use where to select only from the year and month?
For month it would be:
date = # set your date here
Bronze.where(regdate: date.beginning_of_month...date.beginning_of_month + 1.month)
Analogically for year.
Or simply
Bronze.where(regdate: Date.new(2014,03,03)).select("YEAR(d) as year, MONTH(d) as month")
Where d is the column you want to extract year and month.
If you are using mysql then try extract function of SQL
Bronze.where('extract(year from regdate) = ? AND extract(month from regdate) = ?', year_parameter, month_parameter)
But if you are using sqlite then try this
Bronze.where("strftime('%Y', regdate) = ? AND strftime('%m', regdate) + 0 = ?", year_parameter, month_parameter)

Querying active record objects from database based on created_at filters

I know that Ruby on rails stores all times in UTC (for created_at and updated_at fields) and when you fetch an active-record object from database, and ask RoR for it's date, it will convert it your configured (in environment.rb) Timezone and show you.
But my case is different. I am building a custom query. And I am adding a where clause manually to it. Where clause is such that: select * where created_at > [user entered date].
Now the problem that's arising is that the user entered date is in UTC - 7 and created_at is in UTC. So I can't really make it work. I could hardcode it like select * where created_at > [user-entered-date] 07:00:00 - but this created problem because of daylight savings, and also doesn't seem like a good solution.
This is not the only problem, the second problem is that when I print out the record.created_at, I am getting UTC date (perhaps because I build a custom query?), which also I don't want to manually (hardcode) convert to local time.
Here's my code for the query:
cond = EZ::Where::Condition.new
if !start_date.empty?
start_date = params[:filter][:start_date].to_date.to_s(:db)
cond.append "(registrations.created_at) >= '#{start_date} 07:00:00'" #Here!
end
if !end_date.empty?
end_date = params[:filter][:end_date].to_date
end_date = end_date + 1.day;
end_date = end_date.to_s(:db)
cond.append "(registrations.created_at) <= '#{end_date} 07:00:00'" #Here!
end
registrations = Registration.all(
:joins => [:event],
:select => 'registrations.id, registrations.first_name, registrations.last_name, registrations.company_name,
(registrations.created_at) AS reg_date, events.name AS evt_name, sum(fees) AS fees, code, events.id AS event_id',
:group => 'registrations.id',
:order => 'evt_name, events.id',
:conditions=> cond.to_sql
)
unless registrations.empty?
registrations.each_with_index do |registration, i|
sheet[ i, 3 ] = (DateTime.strptime(registration.reg_date, "%Y-%m-%d %H:%M:%S") - 7.hours).to_date #Here!
end
end
Try to use TimeWithZone and TimeZone
tz = ActiveSupport::TimeZone.new("Mountain Time (US & Canada)")
...
start_date = tz.local_to_utc(params[:filter][:start_date].to_time).to_s(:db)
...
sheet[ i, 3 ] = registration.reg_date.in_time_zone("Mountain Time (US & Canada)").to_date

Use active record to find a record by month and day, ignoring year and time

I have a model (Entries) with five years worth of records (one record per day). I need a method that, when passed a date object such as 2011-12-25 00:00:00, will show me ALL the records that have happened on 12/25 (querying against the :created_at column), regardless of the year or time that's passed.
RoR 3.0.9 / Ruby 1.9.2p290
You can use the MONTH and DAY values of mysql. Maybe something like:
Model.where("MONTH(created_at) = ? and DAY(created_at) = ?", somedate.month, somedate.day)
A general solution that should work with most SQL databases (include MySQL and PostgreSQL):
Entry.where('extract(month from created_at) = ? AND extract(day from created_at) = ?', d.month, d.day)
SQLite doesn't understand extract though so you'd have to use:
Entry.where("strftime('%m/%d', created_at) = ?", d.strftime('%m/%d'))
Assuming that you are using mysql:
User.where(["DAY(created_at) = ? AND MONTH(created_at) = ?", date.day, date.month])
Assume RDBMS is MySQL and you have form with combobox to select month and/or date_of_months, may be you could make a named_scope, for example :
scope :by_date_or_month, lambda { |date, month| {:conditions => ["DAYOFMONTH(created_at) = ? or MONTH(created_at) = ?", date, month]}}
Test from IRB :
Model.by_date_or_month(31,8)
Model.by_date_or_month(nil,8)

Rails Date compared to Date.today

I have a birth_date variable in the Date format. I want to compare it to Date.today as shown below. The problem is it is coming back false because it wants to compare the year as well. It is a birthday so I don't care about the year just trying to see if birth_date (month and day) is equal to Date.today.day.month.
Any ideas?
bdays = Soldier.find(:all, :conditions => ["birth_date LIKE ?", Date.today] )
You will need to break up your date, because you want to ignore the year. You will need to use some of the functions given by your SQL provider (the example below uses MySQL):
bdays = Soldier.find(:all, :conditions => ["DAY(birth_date) = ? AND MONTH(birth_date) = ?", Date.today.day, Date.today.month])
if you're using SQLite (rails' default database), it will be a bit more complicated because they don't have a real date type:
bdays = Soldier.find(:all, :conditions => ["STRFTIME('%d', birth_date) = ? AND STRFTIME('%m', birth_date) = ?", Date.today.day, Date.today.month])
Figured I would add postgres:
Soldier.where("EXTRACT(DAY FROM birth_date) = ? AND EXTRACT(MONTH FROM birth_date) = ?", Date.today.day, Date.today.month)

Resources