How do I determine if a date was within a week range? - ruby-on-rails

I have a record with a created_at field populated. What I want to do is know if that created_at was created 1-2 weeks ago, meaning, days 8, 9, 10, 11, 12, 13, 14, not 1-7 or 15+.
Given that I can't query for this in SQL, what's the best Rails way to do this?

((2.weeks.ago)..(1.week.ago)).cover?(record.created_at)
Assuming 2 weeks ago was the 13th of August, 1 week ago is the 20th of August and the record's created_at attribute lies somewhere in the middle, this will return true.

This works for me on Ruby 2.0.0, Rails 4.0
Record.created_at.between?(((Date.today - 14.days).beginning_of_day),(Date.today.end_of_day))

You could use a range
Range.new((Date.today-14.days),
(Date.today-7.days)) === record.created_at
Adjust the range arugments depending on your meaning of two weeks ago.
EDIT:
The one liner is a bit terse. To break it down.
start_date = (Date.today - 14.days)
end_date = (Date.today - 7.days)
# Now start_date is 2 weeks ago, and end_date is 1 week ago.
# Test if created_at falls within this range
Range.new(start_date.to_date, end_date.to_date) === record.created_at

Updated answer for rails 7.0
Release Notes - Active Support Removals
Remove deprecated support to use Range#include? to check the inclusion of a value in a date time range is deprecated.
It's now recommended to use the cover? method.
For example:
((2.weeks.ago)..(1.week.ago)).cover?(record.created_at)

Related

Show objects based on selected week

I have an active relation Bar object with an attribute shift_date. shift_date represents each day between March and June. March and June comes from Foo which has attributes start_month and end_month:
f = Foo.find(1)
days = (f.end_month - f.start_month).to_i
weeks = (days * 0.142857).round(2)
f.bars will give me days objects. Where days is the total amount of objetcs.
My trouble is to get Bars objects, objects for week 1, 2 or 3 etc:
f.bars.where('shift_date >= ?', (weeks/7.days)).group_by{ |result| result }
operator does not exist: timestamp without time zone >= numeric
So what am I saying? Give me all objects on week 1 or week 5, if any. How do I go about this, please?
Im on to something but not right:
f.bars.where('shift_date >= ?', Date.today).group_by{ |result| result}
Edit:
Im almost there. I could splat out the days with:
days_array = *(f.start_month..f.end_month)
then
f.bars.where(shift_date: days_array[0]..days_array[7])
That would be the answer! But...not really. For my views, I need to group the splatted days in a 7 days interval as week, so days_array[0] to days_array[7] would be week 1 and days_array[8] to days_array[14] would be week 2 etc. How to show that in the view? This will give me everything I need.

.change function is not working for Dates for even number of months in ruby

Hi I have define this method
def change_date
date = Date.today
start_date = date.change(year: 2015, month: (2 * 3)).at_beginning_of_quarter
p 'aaaaaa'
p start_date
end
give me invalid date error .change is not working or am I doing it in a wrong way please guide me how to solve this. Thanx in advance.
This is because the month you are specifying doesn't have the current day.
I mean the current month (July) has 31 days but the month you're setting (June) has only 30 days. You can change your code like so:
# in Rails:
date = Date.today.beginning_of_month # or Date.today.change(day: 1)
Then chain your 'change' in front of the date variable.
This actually happens, because today is the 31 of July, and not all months have 31 days in it, for example June, the 6th month, has only 30 days in it.

created_at date syntax problems

I have the following piece of code:
humans = user.humans.joins(:human_logins).where(human_logins_count: 10).group('humans.id').having('MAX(human_logins.created_at) >= ?', Date.today() - schedule.value.day)
The problem with this is the created_at) >= ?segment as if my date is equal to 7 days ago, it will find the records that were made in the last 7 days, as opposed to finding the records that were created literally 7 days ago, not 6, not 9, exactly 7 days ago.
How can I make it so that its finding records created exactly 7 days ago? I was thinking of using something like ("? <= created_at AND created_at <= ?", schedule.value.days.ago.beginning_of_day, schedule.value.days.ago.end_of_day)but I'm not sure how I'd use it in this scenario.
How about this,
.group('human_logins.created_at').having('human_logins.created_at = ?', Date.today() - 7)
.having(created_at: schedule.value.days.ago.beginning_of_day.. schedule.value.days.ago.end_of_day )

Find all records that were created on a specific day of the week

I need to find all records that were created on a specific day of week.
I only have available to me the standard model datetime timestamps.
How would I go about doing this in activerecord?
To follow up on Justin's answer
where("extract(dow from created_at) = ?", Date.today.wday)
This is what I'm using in my application for postgres. This will find all records that were created on the same day-of-week as today. For example, if today was tuesday it would find all records created on tuesdays.
You can use the DAYOFWEEK function in MySQL and pass it to the :conditions option. Supposing you have a model called Item, this would return all of the items created on Sunday:
Item.all(:conditions => ['dayofweek(created_at) = ?', 1])
Using Postgres you could do something similar with to_char.
Note that using a function like this will probably make the database do a full table scan, since at least MySQL doesn't support adding an index to a function. You may want to consider extracting the day of week out to another column if this is something that you anticipate doing frequently.
Obtain the seconds since Unix Epoch. Time.to_i does this in Ruby.
Use modulus of 7 to obtain the day of the week (0 to 6).
dayOfWeek = (epochseconds / 86400 ) % 7;
If you're not opposed to using ruby you could try this.
array.select { |arr| ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"].include?(arr.created_at.strftime('%A'))
I originally tried using dayofweek that was suggested in another answer.
The issue I ran in to was that it seems like my sql server was using UTC time and my rails server was using Eastern US. Records created after 8pm would be picked up while those that happened before would be considered the previous day.
Here is another related question:
How to filter by day of week in Rails 4.2 and sqlite?

Rails: find by day of week with timestamp

I need to grab the records for same day of the week for the preceeding X days of the week. There must be a better way to do it than this:
Transaction.find_by_sql "select * from transactions where EXTRACT(DOW from date) = 1 and organisation_id = 4 order by date desc limit 7"
It gets me what I need but is Postgres specific and not very "Rails-y". Date is a timestamp.
Anyone got suggestions?
How many days do you want to go back?
I have written a gem called by_star that has a dynamic finder suited for finding up to a certain number of days in the past. If the number of days was always a number you could use this finder:
Transaction.as_of_3_days_ago
If it was dynamic then I would recommend using something such as future or between, depending on if you have transactions in the future (i.e. time travel):
Transaction.future(params[:start_date].to_time)
Transaction.between(params[:start_date].to_time, Time.now)
AFAIK Rails has no any methods to do this by other way. So best, and faster, solution - build DOW index on date column and use your query.

Resources