Get the difference in days between two dates Rails "Date" - ruby-on-rails

What is the proper way to subtract or add dates in Rails?
I tried the intuitive way but got Rational:
irb(main):089:0> Date.today.increase_by("3 days")
=> Sun, 19 May 2019
irb(main):090:0> Date.today
=> Thu, 16 May 2019
irb(main):091:0> Date.today.increase_by("3 days") - Date.today
=> (3/1)
Disclaimer: Please note that I am new to Ruby and Rails as well. 2 months of experience so far :)

You can use
Date.today # Thu, 16 May 2019
Date.today + 3 # Thu, 19 May 2019
Date.today - 3 # Thu, 13 May 2019
For Difference
Date.today + 3 # Thu, 19 May 2019
Date.today - 3 # Thu, 13 May 2019
(d1 - d2).to_i # 6 (Days)

Related

Rails TimeWithZone and leap years

Today is Feb 29th: the day our tests broke.
Our tests are failing because these tests do things that, in the end, can be compared to a command like this: Time.zone.now - 1.year + 1.year. And it happens to be NOT equal to Time.zone.now.
Why does this happen? Why isn't ActiveSupport able to handle leap years in calculations like that? Doesn't it work with timestamps, that would prevent this sort of problem from happening?
You could use 4 years instead of 1 for the same effect. (Note: - 1.day because it is 1st March right now)
(Time.zone.now - 1.day) - 4.year + 4.year
=> Mon, 29 Feb 2016 15:12:58 UTC +00:00
It may be worth noting that (below), regardless of date.
Time.zone.now
=> Tue, 01 Mar 2016 15:11:51 UTC +00:00
Time.zone.now == Time.zone.now - 1.year + 1.year
=> false
Unless you use beginning_of_day:
(Time.zone.now - 1.day).beginning_of_day == ((Time.zone.now - 1.day) - 4.year + 4.year).beginning_of_day
=> true
Also, it depends what you are actually trying to do... Why would you want to test Time.now - 1.year + 1.year ?
Also...
1.year == 365.days
=> false
1.year == 365.25.days
=> true

Select object based on date range

Tech specs: ruby 2.1.5p273, Rails 4.2.3.
I have an array of Days that I want to loop through to pick the right Exits (model) that fall within a date range.
#exits has :start_date and :end_date
#days is an array of dates like:
=> [Sun, 06 Sep 2015, Sat, 12 Sep 2015, Tue, 15 Sep 2015, Fri, 18 Sep 2015, Sat, 19 Sep 2015, Sun, 20 Sep 2015, Wed, 23 Sep 2015]
I thought something like this would work:
#days.each do |day|
#exits.where(:start_date..:end_date).include?(day)
end
but I get an error:
TypeError: Cannot visit Range
What is the best way to query an object that has a date range (between two fields) by comparing it against a single date? Thanks!
You can use the following:
#days.each do |day|
exits = Exit.where('? BETWEEN start_date AND end_date', day)
# etc.
end
If you don't want to loop over them then you can do:
Event.where("start_date IN (:days) AND end_date IN (:days)", { days: #days })
or
Event.where(start_date: #days, end_date: #days)
Exit.where(day: #exit.start_date..#exits.end_date)
or
Exit.where('day >= ? AND day <= ?', #exit.start_date, #exits.end_date)
Doing SQL queries in a loop is probably a bad idea, it could be refactored to be be one call most likely. And this should happen in the controller not in the view.

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.

"Ago" date/time functions in Ruby/Rails

I was wondering if there's a way in Rails to calculate time stamp like - half a minute ago, 2 minute ago, 1 day ago etc. Something like twitter real time date stamp.
I want to know if Ruby/Rails has a built-in function for such date-time conversion?
You can use:
10.minutes.ago
2.days.since
Or in your views you have the helpers:
distance_of_time_in_words(from_time, to_time)
time_ago_in_words(from_time)
Check the API for details and more options.
You can use available methods to get the time in past or future using ago, since alias for from_now and many available methods
Time.current
#=> Tue, 20 Sep 2016 15:03:30 UTC +00:00
2.minutes.ago
#=> Tue, 20 Sep 2016 15:01:30 UTC +00:00
2.minutes.since
#=> Tue, 20 Sep 2016 15:05:30 UTC +00:00
1.month.ago
#=> Sat, 20 Aug 2016 15:03:30 UTC +00:00
1.year.since
#=> Wed, 20 Sep 2017 15:03:30 UTC +00:00
Check all the available methods in Time class
distance_of_time_in_words:
from_time = Time.now
distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour
distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
distance_of_time_in_words(from_time, from_time + 15.seconds, include_seconds: true) # => less than 20 seconds
time_ago_in_words:
time_ago_in_words(3.minutes.from_now) # => 3 minutes
time_ago_in_words(3.minutes.ago) # => 3 minutes
time_ago_in_words(Time.now - 15.hours) # => about 15 hours

Working with date and time

I have a UTC date of Tue, 16 Feb 2010 03:12:02 UTC +00:00, for example.
I want to add 168 hours to this date to get a future UTC date.
What's the best way to do that?
You tagged the question rails so here is how you can do this in Rails, using some of the helpers:
time_string = 'Tue, 16 Feb 2010 03:12:02 UTC +00:00'
new_time = Time.parse( time_string ) + 168.hours
If you already have it as a Time object, just add the 168.hours:
new_time = old_time + 168.hours
Or you can just add 1.week:
new_time = old_time + 1.week
FYI, '9.days' is more simpler than '168.hours'.
>> new_time = Time.parse( time_string ) + 168.hours
=> Tue Feb 23 03:12:02 UTC 2010
>> new_time = Time.parse( time_string ) + 9.days
=> Thu Feb 25 03:12:02 UTC 2010
In vanilla Ruby it's not much more difficult:
time_string = 'Tue, 16 Feb 2010 03:12:02 UTC +00:00'
new_time = DateTime.parse( time_string ) + 7
(You could just use the Date class, it would still work.)
I admit adding in hours is a little more tricky.

Resources