I want to generate all the dates of a particular month starting from the 1st of that month to the 30 or 31st of that month with out using a trivial for loop:
for i in 1..Time.days_in_month(Date.today.month, Date.today.year)
date = Date.new(y, m, i)
end
I was getting dates like this but I'm not supposed to use this trivial for loop.
Although there are quite a few ways you could accomplish this, one way would be to use a Ruby Range combined with the Time#beginning_of_month and Time#end_of_month methods to generate an object that contains all of the days of the month and then convert it into an array:
(Date.today.beginning_of_month..Date.today.end_of_month).to_a
=> [Fri, 01 Nov 2019, Sat, 02 Nov 2019, Sun, 03 Nov 2019, Mon, 04 Nov 2019, Tue, 05 Nov 2019, Wed, 06 Nov 2019, ...., Fri, 29 Nov 2019, Sat, 30 Nov 2019]
Another option would be to use the Time#all_month helper which is as simple as:
Date.today.all_month.to_a
=> [Fri, 01 Nov 2019, Sat, 02 Nov 2019, Sun, 03 Nov 2019, Mon, 04 Nov 2019, Tue, 05 Nov 2019, Wed, 06 Nov 2019, ...., Fri, 29 Nov 2019, Sat, 30 Nov 2019]
(Plain Ruby) The Date class uses negative numbers as a way of counting from the end (like in Arrays):
require "date"
today = Date.today
m, y = today.month, today.year
p (Date.new(y,m,1) .. Date.new(y,m,-1)).to_a
Related
I have a range with a start_date, end_date and I want to get the same day of each month for the whole range, so here starting on the 30th of January I should get the 30th of each month:
start_date = Date.new(2019, 1, 30)
end_date = Date.new(2019, 12, 30)
range = (start_date...end_date)
dates = range.step(30).map(&:to_date)
dates
#=> [Wed, 30 Jan 2019,
# Fri, 01 Mar 2019,
# Sun, 31 Mar 2019,
# Tue, 30 Apr 2019,
# Thu, 30 May 2019,
# Sat, 29 Jun 2019,
# Mon, 29 Jul 2019,
# Wed, 28 Aug 2019,
# Fri, 27 Sep 2019,
# Sun, 27 Oct 2019,
# Tue, 26 Nov 2019,
# Thu, 26 Dec 2019]
I was using something like this for weeks but with months when you get to February for example it of course fails, so I would have to adjust to 28th.
I know I could loop and look at the month and do adjustments based on the start_date but it feels like a bad idea.
I think you can use either active support:
require 'active_support/time'
start_date = Date.parse('2019-10-31')
12.times.map { |i| start_date + i.month }
=> [
Thu, 31 Oct 2019,
Sat, 30 Nov 2019,
Tue, 31 Dec 2019,
Fri, 31 Jan 2020,
Sat, 29 Feb 2020,
Tue, 31 Mar 2020,
Thu, 30 Apr 2020,
Sun, 31 May 2020,
Tue, 30 Jun 2020,
Fri, 31 Jul 2020,
Mon, 31 Aug 2020,
Wed, 30 Sep 2020
]
or adjust: #next_month:
require 'date'
Date.parse('2019-10-31').next_month # => Sat, 30 Nov 2019
Event model which has start and end datetime attributes in the database. I want to seed some random events but the event time should be proper.
For example:
6.times { date_range << DateTime.now + (rand * 21) }
generates
[Thu, 03 Aug 2017 21:22:48 +0530,
Tue, 08 Aug 2017 17:36:29 +0530,
Sat, 29 Jul 2017 06:19:51 +0530,
Sat, 29 Jul 2017 13:36:21 +0530,
Thu, 27 Jul 2017 15:08:55 +0530,
Fri, 04 Aug 2017 13:53:03 +0530]
which is the correct behaviour.
But how to generate random datetime like this:
[Thu, 03 Aug 2017 21:00:00 +0530,
Tue, 08 Aug 2017 17:30:00 +0530,
Sat, 29 Jul 2017 06:00:00 +0530,
Sat, 29 Jul 2017 13:00:00 +0530,
Thu, 27 Jul 2017 15:30:00 +0530,
Fri, 04 Aug 2017 13:00:00 +0530]
So in order to display these events properly on a calendar.
Could try separating out each segment and adding them onto the date individually
date_range = 6.times.collect do
DateTime.now.beginning_of_day + # starting from today
rand(21).days + # pick a random day, no further than 3 weeks out
rand(24).hours + # move forward to a random hour on that day
(rand(2) * 30).minutes # and then decide whether to add 30 minutes
end
or, could combine the hours + minutes
date_range = 6.times.collect do
DateTime.now.beginning_of_day + # starting from today
rand(21).days + # pick a random day, no further than 3 weeks out
(rand(48) * 30).minutes # pick a random interval of 30 minutes to add in
end
Found the working solution but not complete:
6.times { date_range << DateTime.parse((DateTime.now + (rand * 21)).beginning_of_hour.to_s) }
[Mon, 31 Jul 2017 06:00:00 +0530,
Thu, 03 Aug 2017 15:00:00 +0530,
Fri, 11 Aug 2017 14:00:00 +0530,
Mon, 31 Jul 2017 09:00:00 +0530,
Wed, 09 Aug 2017 16:00:00 +0530,
Sat, 12 Aug 2017 13:00:00 +0530]
This can work for now but need some datetime with 30 minutes as well.
The user inputs the starting date and the end date. I want to get the dates between these two input dates.
I tried this:
(datestart..dateend).to_a
but it returns the whole month, and when I choose from the previous year, it gives an error ArgumentError (invalid date):.
This is the example return when I choose Jan. 1 2017 and Jan. 2 2017 - the result was whole month and an inaccurate dates.
[Tue, 12 Jan 2016, Wed, 13 Jan 2016, Thu, 14 Jan 2016, Fri, 15 Jan 2016, Sat, 16 Jan 2016, Sun, 17 Jan 2016, Mon, 18 Jan 2016, Tue, 19 Jan 2016, Wed, 20 Jan 2016, Thu, 21 Jan 2016, Fri, 22 Jan 2016, Sat, 23 Jan 2016, Sun, 24 Jan 2016, Mon, 25 Jan 2016, Tue, 26 Jan 2016, Wed, 27 Jan 2016, Thu, 28 Jan 2016, Fri, 29 Jan 2016, Sat, 30 Jan 2016, Sun, 31 Jan 2016, Mon, 01 Feb 2016, Tue, 02 Feb 2016, Wed, 03 Feb 2016, Thu, 04 Feb 2016, Fri, 05 Feb 2016, Sat, 06 Feb 2016, Sun, 07 Feb 2016, Mon, 08 Feb 2016, Tue, 09 Feb 2016, Wed, 10 Feb 2016, Thu, 11 Feb 2016, Fri, 12 Feb 2016]
Update! I Fix it by using
Date.strptime(params[:datestart_stat], '%m/%d/%Y')
start_date = Date.parse('date start')
end_date = Date.parse('date end')
(start..endd).to_a
Update! I was able to fix my mistake now. I just change the
Date.parse(params[:datestart_stat])
# to
Date.strptime(params[:datestart_stat], '%m/%d/%Y')
thank you guys.
how can I get a variable which is holding always Today midnight in my timezone?
The hosting server is several hours behind me, both Time.now.midnight and Date.today are on yesterday date for good part of the day.
Thanks
Found the solution.
now=DateTime.now
=> Fri, 03 Feb 2012 21:57:21 EST -05:00
now.in_time_zone('London').midnight
=> Sat, 04 Feb 2012 00:00:00 GMT +00:00
now.in_time_zone('Hawaii').midnight
=> Fri, 03 Feb 2012 00:00:00 HST -10:00
So I'm using activerecord to get the count of items for a certain day:
Item.group("date(created_at)").count.values
But this doesn't give me 0 if there are no records for a given day, how can I fix this? Or is there are more "Rails" way do to something like this?
Any help is hugely appreciated, thanks again!
Using a GROUP BY query, you are going to get groups based on the records that exist, so if there are no records with a given value in the grouping column, there will be no groups for that value. The database does not psychically know to add in other date values that you might be interested in.
What I would do to get what you want is create a new Hash with a default value of 0 and then merge the result of your query into that. When you subsequently try to retrieve any value from that Hash for which there is no entry, you'll get 0 as the result.
Edit: Remove .values
date_counts = Hash.new(0)
date_counts.merge! Item.group("date(created_at)").count
Alternatively, if you want to make sure there are entries in the Hash for every date in a range, so you can iterate over those, ...
date_counts = {}
(Date.civil(2010,1,1)...Date.civil(2010,2,1)).each do |date|
date_counts[date]=0
end
date_counts.merge! Item.group("date(created_at)").count
Update
Here is some output when I pass my date range and model into here, oddly enough it gets different length hashes:
{Sun, 01 May 2011=>0, Mon, 02 May 2011=>0, Tue, 03 May 2011=>0, Wed, 04 May 2011=>0, Thu, 05 May 2011=>0, Fri, 06 May 2011=>0, Sat, 07 May 2011=>0, Sun, 08 May 2011=>0, Mon, 09 May 2011=>0, Tue, 10 May 2011=>0, Wed, 11 May 2011=>0, Thu, 31 Mar 2011=>2, Sun, 03 Apr 2011=>1, Fri, 08 Apr 2011=>643, Sat, 09 Apr 2011=>2360, Sun, 10 Apr 2011=>705, Mon, 11 Apr 2011=>34}
{Sun, 01 May 2011=>0, Mon, 02 May 2011=>0, Tue, 03 May 2011=>0, Wed, 04 May 2011=>0, Thu, 05 May 2011=>0, Fri, 06 May 2011=>0, Sat, 07 May 2011=>0, Sun, 08 May 2011=>0, Mon, 09 May 2011=>0, Tue, 10 May 2011=>0, Wed, 11 May 2011=>0, Sat, 02 Apr 2011=>1, Fri, 08 Apr 2011=>4158, Sat, 09 Apr 2011=>12206, Sun, 10 Apr 2011=>4279, Mon, 11 Apr 2011=>169}
{Sun, 01 May 2011=>0, Mon, 02 May 2011=>0, Tue, 03 May 2011=>0, Wed, 04 May 2011=>0, Thu, 05 May 2011=>0, Fri, 06 May 2011=>0, Sat, 07 May 2011=>0, Sun, 08 May 2011=>0, Mon, 09 May 2011=>0, Tue, 10 May 2011=>0, Wed, 11 May 2011=>0}
Not sure whats causing it... hmm.