In a Rails 3.2 app, I have a query defined to return all Event items with :due_date equal to today.
@due_today = Event.where(:due_date => Time.now.beginning_of_day..Time.now.end_of_day)
I want to modify this to return all events due today and tomorrow.
What is the best way to do this?
I know there are several options available to me:
Date.tomorrow
Date.current.tomorrow
Date.now.tomorrow
DateTime.now.tomorrow.to_date
Time.now.tomorrow.to_date
Date.current+1
I'm sure there are others. Are all of these interchangeable? Are there any differences in performance? Are there any issues associated with different approaches? I'd welcome any suggestions as to which is the best way to do this.
For extra kudos: I also want to display the :due_date as Today HH:MM or Tomorrow HH:MM, where HH:MM is the time. Is there a method baked in to Rails to display dates as Today or Tomorrow? Or will I need to define my own scope?
Many thanks!
Benchmarking these, I get:
N = 100000
Benchmark.bmbm do |test|
test.report("Date.tomorrow") do
N.times do
x = Date.tomorrow
end
end
test.report("Date.current.tomorrow") do
N.times do
x = Date.current.tomorrow
end
end
# test.report("Date.now.tomorrow") # => Coughs up an exception, Date.now doesn't exist!
test.report("DateTime.now.tomorrow.to_date") do
N.times do
x = DateTime.now.tomorrow.to_date
end
end
test.report("Time.now.tomorrow.to_date") do
N.times do
x = Time.now.tomorrow.to_date
end
end
test.report("Date.current+1") do
N.times do
x = Date.current+1
end
end
test.report("DateTime.tomorrow.to_date") do
N.times do
x = DateTime.tomorrow.to_date
end
end
end
Results:
Rehearsal -----------------------------------------------------------------
Date.tomorrow 1.640000 0.010000 1.650000 ( 1.662668)
Date.current.tomorrow 1.580000 0.000000 1.580000 ( 1.587714)
DateTime.now.tomorrow.to_date 0.360000 0.010000 0.370000 ( 0.363281)
Time.now.tomorrow.to_date 4.270000 0.010000 4.280000 ( 4.303273)
Date.current+1 1.580000 0.010000 1.590000 ( 1.590406)
DateTime.tomorrow 0.160000 0.000000 0.160000 ( 0.164075)
-------------------------------------------------------- total: 9.630000sec
user system total real
Date.tomorrow 1.590000 0.000000 1.590000 ( 1.601091)
Date.current.tomorrow 1.610000 0.010000 1.620000 ( 1.622415)
DateTime.now.tomorrow.to_date 0.310000 0.000000 0.310000 ( 0.319628)
Time.now.tomorrow.to_date 4.120000 0.010000 4.130000 ( 4.145556)
Date.current+1 1.590000 0.000000 1.590000 ( 1.596724)
DateTime.tomorrow 0.140000 0.000000 0.140000 ( 0.137487)
From your list of suggestions, DateTime.now.tomorrow.to_date
is faster.
Check out the last option I've added though, it returns a Date object and is the fastest of the bunch by a country mile. It's also one of the most human-readable from the list.
Assuming you're using MYSQL, your query might be faster if you use MySQL's BETWEEN() function:
@due_today = Event.where("due_date BETWEEN ? AND ?", DateTime.today, DateTime.tomorrow)
Although I'm not sure if you have indexes on events.due_date or if BETWEEN will still use these. You'll have to benchmark both to see which is quicker with a large DATA set.
Hope that helps?
How about this?
1.day.from_now
2.days.from_now
3.days.from_now
If you want to increment given time..
1.day.from_now(start_time) # gives a day after the start time
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With