Ruby group_by date every 7 days - ruby-on-rails

How can I sort a collection of records by week start and end date? After looking at the strf docs the closest I could get was to group by the week number
weeks = my_data.group_by{|x| x.created_at.strftime('%U %Y') }
{"34 2015"=>
[#<DoctorRecommendation:0x007fd663196ea0
created_at: Tue, 25 Aug 2015 22:29:44 UTC +00:00,
patient_profile_id: 104,],
"33 2015"=>
[#<DoctorRecommendation:0x007fd663194ce0
created_at: Thu, 20 Aug 2015 13:41:37 UTC +00:00,
patient_profile_id: 21,,
#<DoctorRecommendation:0x007fd66319f500
created_at: Tue, 18 Aug 2015 02:47:30 UTC +00:00,
patient_profile_id: 61,
#<DoctorRecommendation:0x007fd66319db38
created_at: Tue, 18 Aug 2015 02:47:29 UTC +00:00,
patient_profile_id: 85,
]
}
I'd rather have the keys be 8/10/2015 - 8/16/2015 and 8/17/2015 - 8/23/2015
There are a couple of issues with this approach. First is that I haven't been able to convert it back to a proper date (tried Date.parse("34 2015")) but received an ArgumentError: invalid date. The second issue with this approach is that certain weeks would be omitted if there were no records.

You can use Rails' date extension to get the beginning and ending of the week (configurable), and use
that to create your range:
weeks = my_data.group_by do |x|
date = x.created_at
left = date.beginning_of_week.strftime('%-m/%-d/%Y')
right = date.end_of_week.strftime('%-m/%-d/%Y')
"#{left} - #{right}"
end

Here's code that does what you want, but with a lot of date parsing. Someone better at Ruby could probably optimize this.
my_data.group_by do |x|
date = Date.parse(x.created_at.strftime("%F"))
monday = date - date.strftime("%u").to_i
sunday = monday + 7
"#{monday.strftime("%F")} - #{sunday.strftime("%F")}"
end
My other suggestion is to query the minimum created_at date and today, generate all of the weeks in between with ruby very quickly, and then do queries. This is slower if you're getting all the data, but much faster if you only need a few of the weeks.

Related

I dont get the expenses of the 31 of the previous months with Activerecord in rails

When I show the total expend of PUQ theres no problem
Expend.where(cc: "PUQ").sum(:total)
But when I want to show by month individually with this code, I Don't get the expenses of the 31, only show 1 to 30 of the month. Right now I dont get the expenses of 31-08-2020
Expend.where(cc: "PUQ").where(:created_at => ((Date.today.beginning_of_month)- 1.month)..((Date.today.end_of_month) - 1.month)).sum(:total)
Thanks in advance
You can use these handy Rails methods
range = Time.current.advance(months: -1).all_month
# => Sat, 01 Aug 2020 00:00:00 UTC +00:00..Mon, 31 Aug 2020 23:59:59 UTC +00:00
Expend.where(created_at: range)
More about all_month
and about advance

How to get the date of "this Wednesday", "this Thursday" etc. in Rails

I know that Rails has an elegant way of getting dates for a certain day of the week for next week, or for last week (docs).
today = Time.zone.today
=> Fri, 24 Jan 2020
today.next_week
=> Mon, 27 Jan 2020 # Gets Monday by default
today.next_week(:thursday)
=> Thu, 30 Jan 2020 # You can get a certain day of the week by passing it in as an argument
Is there a way to do the same for this week? For example, getting the date of this Thursday, Friday, etc.? Right now, my workaround is to get the date of beginning_of_week (Monday) and calculate from there. Ideally, I wanted to do something similar to above, like Time.zone.today.this_week(:thursday).
this_monday = Time.zone.today.beginning_of_week
=> Mon, 20 Jan 2020
this_friday = this_monday.since(4.days).to_date
=> Fri, 24 Jan 2020
You could use #next_occurring
pry(main)> Time.zone.today.beginning_of_week
Mon, 20 Jan 2020
pry(main)> Time.zone.today.beginning_of_week.next_occurring(:thursday)
Thu, 23 Jan 2020

Calculate how many days since creation

Let's say a record has a created_at timestamp of Fri, 16 Feb 2018 18:40:53 UTC +00:00 and I want to find out the amount of days that have passed from the current time. How could I achieve this?
Here is what I've tried:
(Fri, 16 Feb 2018 18:40:53 UTC +00:00 - Time.now).to_i
But that does not work.
Almost, but Ruby doesn't understand your way of writing a datetime.
require 'date'
(DateTime.now - DateTime.new(2018, 2, 16, 18, 40, 53, 0)).to_i
In rails
If you get the timestamp for the model User from the database (not a timestamp string to parse):
seconds_from_creation = Date.today.to_time - user.created_at.to_time
Or directly convert to days (to_i rounds to integer, check if is suitable for you or customise):
((Date.today.to_time - user.created_at.to_time)/(24*60*60)).to_i
In a view you could use the following, which returns a string :
time_ago_in_words user.created_at
# => 10 days (in my case)
You can use
require 'time'
created_at = 'Fri, 16 Feb 2018 18:40:53 UTC +00:00'
(Time.now - Time.parse(created_at)).to_i / 86400

How to get time x days ago from a specific date in Rails?

I am looking for a rails solution to calculate the time ago from a particulat time. For example , 2 days ago 15th May 2016 22:00 UTC should return 13th May 2016 22::00 UTC .
My requirement is something like this
2.days.ago.from(yesterday)
Which will be a more specific version of
2.days.from_now
Try this:
> DateTime.now-2.days
=> Wed, 18 May 2016 21:40:31 -0700
how about this:
# 2 days before a specific date
specific_date.days_ago(2)
Example:
specific_date = DateTime.now
two_days_ago_from_specific_date = specific_date.days_ago(2)
My personal favorite syntax for this with rails would be
x.days.ago
For example, if you wanted 10 days ago you would call
10.days.ago
=> Sat, 12 Feb 2022 01:36:58 UTC +00:00
Easy to read and defaults to UTC.
example:
Time.now.ago(10.year)
Time.now.ago(1.minutes)
Time.now.ago(10.day)

Iterating months using ruby

I have a very weird requirement where I need to deal with months. Here is what I am try to do actually. I have two object say
jan_start_date=Time.parse("2012-01-01 00:00:00")
jan_end_date=Time.parse("2012-01-31 23:59:59")
I take this two datetime objects and iterate over feb, mar, april and soon to get some data.
Then I will take feb start and end dates and iterate over march, april and soon.
Its like month on month data collection. Once I am done with say Jan data, I need to take Feb's data and so on and so forth. How do I achieve this. Since I need to iterate over months.
Kindly help me out
Thanks
ActiveSupport has beginning_of_month and end_of_month:
d = Date.today
#=> Fri, 13 Jul 2012
d.beginning_of_month
#=> Sun, 01 Jul 2012
d.end_of_month
#=> Tue, 31 Jul 2012
You can use Date#>> to shift dates forward monthwise:
(d>>2).end_of_month
#=> Sun, 30 Sep 2012
(d>>4).beginning_of_month
#=> Thu, 01 Nov 2012

Resources