Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the count of elements in a ruby range made of Time objects

Tags:

time

range

ruby

How would I be able to get the size or count of a range made up of Time objects?

Something that would achieve the same result as my pseudo Ruby code, which doesn't work:

((Time.now.end_of_day - 31.days)..(Time.now.end_of_day - 1.day)).size == 30

currently doing the above gives an error:

NoMethodError: undefined method `size' for 2012-05-18 23:59:59 -0400..2012-06-17 23:59:59 -0400:Range

and trying to turn it into array (range).to_a :

can't iterate from Time

update

Interesting, Just tried to do

((Date.today.end_of_day - 31.days)..(Date.today.end_of_day - 1.day)).count

Users/.../gems/ruby/1.9.1/gems/activesupport-3.0.15/lib/active_support/time_with_zone.rb:322: warning: Time#succ is obsolete; use time + 1

However

((Date.today - 31.days)..(Date.today - 1.day)).count == 31

I would be willing to settle for that?

Also ((Date.today - 31.days)..(Date.yesterday)).count == 31

update 2

On the other hand, taking Mu's hint we can do:

(((Time.now.end_of_day - 31.days)..(Time.now.end_of_day - 1.day)).first.to_date..((Time.now.end_of_day - 31.days)..(Time.now.end_of_day - 1.day)).last.to_date).count == 31

like image 759
Victor S Avatar asked Oct 24 '25 18:10

Victor S


2 Answers

There's no such method as Range#size, try Range#count (as suggested by Andrew Marshall), though it still won't work for a range of Time objects.

If you want to perform number-of-days computations, you're better off using Date objects, either by instantiating them directly (Date.today - 31, for example), or by calling #to_date on your Time objects.

Date objects can be used for iteration too:

((Date.today - 2)..(Date.today)).to_a
=> [#<Date: 2012-06-17 ((2456096j,0s,0n),+0s,2299161j)>,
 #<Date: 2012-06-18 ((2456097j,0s,0n),+0s,2299161j)>,
 #<Date: 2012-06-19 ((2456098j,0s,0n),+0s,2299161j)>]

((Date.today - 2)..(Date.today)).map(&:to_s)
=> ["2012-06-17", "2012-06-18", "2012-06-19"]
like image 111
Lars Haugseth Avatar answered Oct 26 '25 08:10

Lars Haugseth


It's because a size for a date range doesn't make sense—it doesn't know if you want to view it as days, minutes, seconds, months, or something else. The reason the error mentions iterating is that in order to determine the size of the range, it must know how to iterate over them so that it may count the number of elements.

Since what you want is the difference in days, just do that:

date_one = Time.now.end_of_day - 31.days
date_two = Time.now.end_of_day - 1.day

((date_one - date_two) / 1.day).abs
#=> 30.0

You must divide by 1.day since a difference of Times returns seconds.

like image 20
Andrew Marshall Avatar answered Oct 26 '25 09:10

Andrew Marshall



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!