Get start date and end date of month - ruby-on-rails

I want to get start and end date of month in ruby on rails. User enter integer value from 1..12.
If user enter 1 then JAN start_date,end_date
If user enter 2 then FEB start_date,end_date
If user enter 3 then MARCH start_date,end_date
and so on

There are built-in methods in active_support (part of Rails):
month_number = 5 # user-provided month number
month_beginning = Date.new(Date.today.year, month_number)
# => Sun, 01 May 2016
month_ending = month_beginning.end_of_month
# => Tue, 31 May 2016

Related

Ruby(/Rails) dates - bi-weekly and quarterly DateTime ranges

I am trying to do reporting for a specific period, those periods supported being:
"today": start = DateTime.now.beginning_of_day; end = start.end_of_day
"this week": start = DateTime.now.beginning_of_week; end = start.end_of_week
"this bi-week" (first half or second half of the month, relative to the current date of DateTime.now)
it is very important to be sure that the month is evenly divided, and cweek is not used; the start of the first bi-week should be the first of the month, and the end of the second bi-week should be the last of the month. The dividing date between the two should be the total number of days in the month divided by 2, rounded up (i.e. if there are 31 days, the second bi-week would start on the 15th, and not the 14th of the month).
"this month": start = DateTime.now.beginning_of_month; end = start.end_of_month
"last month": start = (DateTime.now - 1.month).beginning_of_month; end = start.end_of_month
"this quarter": one of each of the four 3-month periods in the year, ie quarters. Ex: from 1/1/1999 to 3/31/1999 or from 10/1/2000 to 12/31/2000.
"this year" = start = DateTime.now.beginning_of_year --> end = start.end_of_year
I'm having trouble calculating the bold date ranges based on the current date (assume DateTime.now).
How can I calculate the bi-weekly and quarterly period relative to the current date, DateTime.now?
Expected output
For the date May 7th, 2018 (5/7/2018):
"this bi-week" should be the period of 5/1/2018 to 5/15/2018
"this quarter" should be the period of 4/1/2018 to 6/30/2018
For the date February 29th, 2020 (2/29/2020), a leap year:
"this bi-week" should be the period of 2/15/2018 to 2/29/2018
"this quarter" should be the period of 1/1/2018 to 3/31/2018
What about this:
This bi-week:
def bi_week_limits_for(date)
days_in_month = Time.days_in_month(date.month, date.year)
# this will round down. 30/31-day months will output 15. 28 / 29-day will output 14. Adjust as per your requirements
middle_day = days_in_month / 2
if date.day <= middle_day
[date.beginning_of_month, date.change(day: middle_day)]
else
[date.change(day: middle_day + 1), date.end_of_month]
end
end
In my console:
pry(main)> bi_week_limits_for Date.parse('29/2/2020')
=> [Sat, 15 Feb 2020, Sat, 29 Feb 2020]
pry(main)> bi_week_limits_for Date.parse('7/5/2018')
=> [Tue, 01 May 2018, Tue, 15 May 2018]
This quarter:
def bi_week_limits_for(date)
[date.beginning_of_quarter, date.end_of_quarter]
end
In my console
pry(main)> date = Date.parse('7/5/2018')
=> Mon, 07 May 2018
pry(main)> quarter_limits_for date
=> [Sun, 01 Apr 2018, Sat, 30 Jun 2018]
pry(main)> date = Date.parse '29/2/2020'
=> Sat, 29 Feb 2020
pry(main)> quarter_limits_for date
=> [Wed, 01 Jan 2020, Tue, 31 Mar 2020]
Reference: https://apidock.com/rails/DateAndTime/Calculations/beginning_of_quarter

Finding days between 2 days in Ruby on Rails

I am facing some problem in finding the days between 2 dates.
The scenario is as follow :
time = Time.new
enddate_timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
startdate = #logInfo.updated_at #here updated_at is the column in the db .
What is the best way to find the days ?
Post.where(["date(created_at) BETWEEN ? AND ?", Date.yesterday, Date.tomorrow]
More details: http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-where
There are several possible solutions. A possibility is to create a Range with the dates, then convert the range into an array
# set the boundaries
today = Time.current
past = 5.days.ago
Note that both boundaries are time instances. We should cast them into dates. I used time(s) because your column is a time.
range = past.to_date..today.to_date
# => Sun, 29 Dec 2013..Fri, 03 Jan 2014
Use to_a to expand the range getting all the days
range.to_a
# => [Sun, 29 Dec 2013, Mon, 30 Dec 2013, Tue, 31 Dec 2013, Wed, 01 Jan 2014, Thu, 02 Jan 2014, Fri, 03 Jan 2014]
range.count
# => 6
You can also enumerate them
range.each { |day| puts day.day }
29
30
31
1
2
3
now = Time.now
future = Time.now + 100 days
while now < future
now = now + 1.day
puts now
end
This will give you the dates, not the days count.
(startdate.beginning_of_day..enddate_timestamp.to_time.beginning_of_day).step(1.day) do |day|
puts day
end
P.S: Performance wise it's not good.

My testing database leaves two days into the past and doesn't care for rescue

There are two issues here:
I have this code to publish on users' facebook walls:
def publish_on_facebook
if user.last_published < 1.day.ago
#graph = Koala::Facebook::API.new(user.service.token)
begin
#graph.put_wall_post("some post")
user.last_published = Time.now
user.save
rescue
user.last_published = 1.week.from_now
user.save
end
end
end
It works perfectly:
if the user has authorized me, it publishes and updates the last_published (type datetime) field to now.
If the user has not authorized me to publish stuff in his wall, then it updates the last_published field to 1 week from now.
Now when I run in through my Cucumber, testing, it doesn't work:
When the user has authorized me, the last_published field updates to 1 minute from now, but 2 days ago
expected: > Sun, 03 Mar 2013 16:12:44 UTC +00:00
got: Fri, 01 Mar 2013 16:13:43 UTC +00:00
When the user hasn't authorized me, no change on the last_published field (i set the default value of the field to march 1st)
expected: > Sat, 09 Mar 2013 16:13:47 UTC +00:00
got: Fri, 01 Mar 2013 15:01:11 UTC +00:00
Any ideas?
When updating attributes, the variable #user must be reloaded:
#user.update_attributes(attribute: value)
#user = User.find(#user)
Cucumber was evaluating the values stored in #user, which were not up to date after the method ran.

How can I use a Date object and a string with a day name to create a new Date object?

I have a Date object
Mon, 03 Dec 2012
and I have a String that contains a day name
"Thursday"
How can I use those two objects to find a new Date object representing the day name in the same week as the original Date object? So for this example, it would be
Thu, 07 Dec 2012
In this scenario, a week goes from Monday to Sunday.
I'm using Rails 3.2.0 and Ruby 1.9.3.
If you can manage to convert "Thursday" to week day 4 -- I know you can --, you can get another date like this:
1.9.3p125 :014 > d = Date.parse "Mon, 03 Dec 2012"
=> Mon, 03 Dec 2012
1.9.3p125 :015 > Date.commercial d.cwyear, d.cweek, 4
=> Thu, 06 Dec 2012
1.9.3p125 :016 >
BTW, you can store the map from day name to number in an Array or an Hash, or use I18n.
I am sure there is a better way for doing this but you could do
def date_by_day(date, day_name)
beginning_of_week = date.beginning_of_week
7.times do |i|
_date = beginning_of_week + i.days
return _date if _date.strftime("%A") == day_name
end
end
This one will work nicely for you.
def date_by_day(date, day_name)
beginning_of_week = date.beginning_of_week
day_number = Time::DAYS_INTO_WEEK[day_name.to_sym]
return (beginnig_of_week + day_number.days)
end

Is it possible to create a list of months between two dates in Rails

I am trying to create a page to display a list of links for each month, grouped into years. The months need to be between two dates, Today, and The date of the first entry.
I am at a brick wall, I have no idea how to create this.
Any help would be massively appriciated
Regards
Adam
Just put what you want inside a range loop and use the Date::MONTHNAMES array like so
(date.year..laterdate.year).each do |y|
mo_start = (date.year == y) ? date.month : 1
mo_end = (laterdate.year == y) ? laterdate.month : 12
(mo_start..mo_end).each do |m|
puts Date::MONTHNAMES[m]
end
end
The following code will add a months_between instance method to the Date class
#!/usr/bin/ruby
require 'date'
class Date
def self.months_between(d1, d2)
months = []
start_date = Date.civil(d1.year, d1.month, 1)
end_date = Date.civil(d2.year, d2.month, 1)
raise ArgumentError unless d1 <= d2
while (start_date < end_date)
months << start_date
start_date = start_date >>1
end
months << end_date
end
end
This is VERY lightly tested, however it returns an Array of dates each date being the 1st day in each affected month.
I don't know if I've completely understood your problem, but some of the following might be useful. I've taken advantage of the extensions to Date provided in ActiveSupport:
d1 = Date.parse("20070617") # => Sun, 17 Jun 2007
d2 = Date.parse("20090529") #=> Fri, 29 May 2009
eom = d1.end_of_month #=> Sat, 30 Jun 2007
mth_ends = [eom] #=> [Sat, 30 Jun 2007]
while eom < d2
eom = eom.advance(:days => 1).end_of_month
mth_ends << eom
end
yrs = mth_ends.group_by{|me| me.year}
The final line uses another handy extension: Array#group_by, which does pretty much exactly what it promises.
d1.year.upto(d2.year) do |yr|
puts "#{yrs[yr].min}, #{yrs[yr].max}"
end
2007-06-30, 2007-12-31
2008-01-31, 2008-12-31
2009-01-31, 2009-05-31
I don't know if the start/end points are as desired, but you should be able to figure out what else you might need.
HTH
Use the date_helper gem which adds the months_between method to the Date class similar to Steve's answer.
xmas = Date.parse("2013-12-25")
hksar_establishment_day = Date.parse("2014-07-01")
Date.months_between(xmas,hksar_establishment_day)
=> [Sun, 01 Dec 2013, Wed, 01 Jan 2014, Sat, 01 Feb 2014, Sat, 01 Mar 2014, Tue, 01 Apr 2014, Thu, 01 May 2014, Sun, 01 Jun 2014, Tue, 01 Jul 2014]

Resources