# Name this method

**URL:** <https://rubytalk.org/t/name-this-method/42681>\
**Category:** ruby-talk\
**Created:** [2 December 2007 20:58 UTC](https://rubytalk.org/t/name-this-method/42681 "2007-12-02T20:58:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Daniel\_Waite](https://avatars.discourse-cdn.com/v4/letter/d/a9adbd/32.png) [@Daniel\_Waite](https://rubytalk.org/u/Daniel_Waite)\
**Post date:** [2 December 2007 20:58 UTC](https://rubytalk.org/t/name-this-method/42681/1 "2007-12-02T20:58:29Z")

</div>

First off, if there's already a method that does this please point it  
out; I couldn't find one so I wrote my own.

It's currently called #to\_elapsed\_time and is attached to Fixnum. What  
it does...

> > 10.to\_elapsed\_time

=\> {:days=\>0, :minutes=\>0, :seconds=\>10, :hours=\>0}

> > 75.to\_elapsed\_time

=\> {:days=\>0, :minutes=\>1, :seconds=\>15, :hours=\>0}

> > 75018.to\_elapsed\_time

=\> {:days=\>0, :minutes=\>50, :seconds=\>18, :hours=\>20}

> > 789010.to\_elapsed\_time

=\> {:days=\>9, :minutes=\>10, :seconds=\>10, :hours=\>3}

The current name makes sense to me because I wrote it with this in mind:

started = Time.now  
ended = Time.now + some\_time\_into\_the\_future  
elapsed = (ended.to\_i - started.to\_i).to\_elapsed\_time

Looking at it now I suppose I could attach it to Time, too...

time\_1.elapsed(time\_2)

That would be kinda cool, too.

What do you think?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![fedzor](https://avatars.discourse-cdn.com/v4/letter/f/bbe5ce/32.png) [@fedzor](https://rubytalk.org/u/fedzor)\
**Post date:** [2 December 2007 21:18 UTC](https://rubytalk.org/t/name-this-method/42681/2 "2007-12-02T21:18:17Z")

</div>

> First off, if there's already a method that does this please point it  
> out; I couldn't find one so I wrote my own.
> 
> It's currently called #to\_elapsed\_time and is attached to Fixnum. What  
> it does...
> 
> > > 10.to\_elapsed\_time
> 
> =\> {:days=\>0, :minutes=\>0, :seconds=\>10, :hours=\>0}
> 
> > > 75.to\_elapsed\_time
> 
> =\> {:days=\>0, :minutes=\>1, :seconds=\>15, :hours=\>0}
> 
> > > 75018.to\_elapsed\_time
> 
> =\> {:days=\>0, :minutes=\>50, :seconds=\>18, :hours=\>20}
> 
> > > 789010.to\_elapsed\_time
> 
> =\> {:days=\>9, :minutes=\>10, :seconds=\>10, :hours=\>3}

That's DEFINITELY a nice method to have around 🙂

Unfortunately....

> started = Time.now  
> ended = Time.now + some\_time\_into\_the\_future  
> elapsed = (ended.to\_i - started.to\_i).to\_elapsed\_time

puts ended - started  
&nbsp;&nbsp;#=\> Some Time

already works

Don't trash your method though! It will probably come in handy one day

Ari Brown  
--------------------------------------------|  
If you're not living on the edge,  
then you're just wasting space.

> **···**
>
> On Dec 2, 2007, at 3:58 PM, Daniel Waite wrote:

---

<div class="post-metadata">

**Author:** ![Chris\_Shea1](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@Chris\_Shea1](https://rubytalk.org/u/Chris_Shea1)\
**Post date:** [2 December 2007 21:30 UTC](https://rubytalk.org/t/name-this-method/42681/3 "2007-12-02T21:30:06Z")

</div>

You might want to take a look at the Duration gem: [http://rubyforge.org/projects/duration/](http://rubyforge.org/projects/duration/)

It's very similar to what you have here.

HTH,  
Chris

> **···**
>
> On Dec 2, 1:58 pm, Daniel Waite \<rabbitb...@gmail.com\> wrote:
> 
> > First off, if there's already a method that does this please point it  
> > out; I couldn't find one so I wrote my own.
> > 
> > It's currently called #to\_elapsed\_time and is attached to Fixnum. What  
> > it does...
> > 
> > \>\> 10.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>0, :seconds=\>10, :hours=\>0}\>\> 75.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>1, :seconds=\>15, :hours=\>0}\>\> 75018.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>50, :seconds=\>18, :hours=\>20}\>\> 789010.to\_elapsed\_time
> > 
> > =\> {:days=\>9, :minutes=\>10, :seconds=\>10, :hours=\>3}
> > 
> > The current name makes sense to me because I wrote it with this in mind:
> > 
> > started = Time.now  
> > ended = Time.now + some\_time\_into\_the\_future  
> > elapsed = (ended.to\_i - started.to\_i).to\_elapsed\_time
> > 
> > Looking at it now I suppose I could attach it to Time, too...
> > 
> > time\_1.elapsed(time\_2)
> > 
> > That would be kinda cool, too.
> > 
> > What do you think?  
> > --  
> > Posted viahttp://www.ruby-forum.com/.

---

<div class="post-metadata">

**Author:** ![Gavin\_Kistner3](https://avatars.discourse-cdn.com/v4/letter/g/dfb087/32.png) [@Gavin\_Kistner3](https://rubytalk.org/u/Gavin_Kistner3)\
**Post date:** [3 December 2007 03:49 UTC](https://rubytalk.org/t/name-this-method/42681/4 "2007-12-03T03:49:59Z")

</div>

Not as cool as the duration gem, but I offer this also:  
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/266462](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/266462)

> **···**
>
> On Dec 2, 1:58 pm, Daniel Waite \<rabbitb...@gmail.com\> wrote:
> 
> > First off, if there's already a method that does this please point it  
> > out; I couldn't find one so I wrote my own.
> > 
> > It's currently called #to\_elapsed\_time and is attached to Fixnum. What  
> > it does...
> > 
> > \>\> 10.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>0, :seconds=\>10, :hours=\>0}\>\> 75.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>1, :seconds=\>15, :hours=\>0}\>\> 75018.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>50, :seconds=\>18, :hours=\>20}\>\> 789010.to\_elapsed\_time
> > 
> > =\> {:days=\>9, :minutes=\>10, :seconds=\>10, :hours=\>3}
> > 
> > The current name makes sense to me because I wrote it with this in mind:
> > 
> > started = Time.now  
> > ended = Time.now + some\_time\_into\_the\_future  
> > elapsed = (ended.to\_i - started.to\_i).to\_elapsed\_time

---

<div class="post-metadata">

**Author:** ![Daniel\_Waite](https://avatars.discourse-cdn.com/v4/letter/d/a9adbd/32.png) [@Daniel\_Waite](https://rubytalk.org/u/Daniel_Waite)\
**Post date:** [2 December 2007 21:25 UTC](https://rubytalk.org/t/name-this-method/42681/5 "2007-12-02T21:25:41Z")

</div>

thefed wrote:

> > > > 75018.to\_elapsed\_time
> > 
> > =\> {:days=\>0, :minutes=\>50, :seconds=\>18, :hours=\>20}
> > 
> > > > 789010.to\_elapsed\_time
> > 
> > =\> {:days=\>9, :minutes=\>10, :seconds=\>10, :hours=\>3}
> 
> That's DEFINITELY a nice method to have around 🙂

Thank you!

> Unfortunately....
> 
> > started = Time.now  
> > ended = Time.now + some\_time\_into\_the\_future  
> > elapsed = (ended.to\_i - started.to\_i).to\_elapsed\_time
> 
> puts ended - started  
> &nbsp;&nbsp;#=\> Some Time
> 
> already works

I aware of that, but didn't want a float due to its inaccuracies.  
(Though I admit I'm still uncertain exactly HOW those inconsistencies  
manifest themselves, I know they can be wrong from time to time.) I  
suppose I could write..

(ended - started).to\_i

> Don't trash your method though! It will probably come in handy one day

Thank you again! 🙂

I've added elapsed to Time, which piggybacks off Fixnum's implementation  
(that sounds bad... is it?)

class Fixnum

&nbsp;&nbsp;def seconds\_into\_time  
&nbsp;&nbsp;&nbsp;&nbsp;elapsed\_time = Hash.new  
&nbsp;&nbsp;&nbsp;&nbsp;elapsed\_time[:days], remainder = self.divmod(86400)  
&nbsp;&nbsp;&nbsp;&nbsp;elapsed\_time[:hours], remainder = remainder.divmod(3600)  
&nbsp;&nbsp;&nbsp;&nbsp;elapsed\_time[:minutes], remainder = remainder.divmod(60)  
&nbsp;&nbsp;&nbsp;&nbsp;elapsed\_time[:seconds] = remainder  
&nbsp;&nbsp;&nbsp;&nbsp;elapsed\_time  
&nbsp;&nbsp;end

end

class Time

&nbsp;&nbsp;def elapsed(time)  
&nbsp;&nbsp;&nbsp;&nbsp;(time - self).to\_i.seconds\_into\_time  
&nbsp;&nbsp;end

end

As you can see I renamed it to #seconds\_into\_time. Any thoughts on that  
name?

I like the to\_xxx family of methods, but...

100.to\_time\_breakdown  
100.from\_seconds\_into\_time\_breakdown  
100.to\_time  
100.to\_elapsed\_time

None of them feel right. I'm sad. =(

> **···**
>
> > On Dec 2, 2007, at 3:58 PM, Daniel Waite wrote:
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Daniel\_Waite](https://avatars.discourse-cdn.com/v4/letter/d/a9adbd/32.png) [@Daniel\_Waite](https://rubytalk.org/u/Daniel_Waite)\
**Post date:** [2 December 2007 21:41 UTC](https://rubytalk.org/t/name-this-method/42681/6 "2007-12-02T21:41:24Z")

</div>

Chris Shea wrote:

> You might want to take a look at the Duration gem:  
> [http://rubyforge.org/projects/duration/](http://rubyforge.org/projects/duration/)
> 
> It's very similar to what you have here.

Damn it! That makes so much more sense! Just like Ruby makes the concept  
of a range explicit via Range, I should have thought to make \_duration\_  
(brilliant name, by the way) explicit via Duration.

Objects, Daniel, objects! Not objects grafted as methods onto other  
objects!

Here's an excerpt from the doc:

require 'duration'  
=\> true  
d = Duration.new(60 \* 60 \* 24 \* 10 + 120 + 30)  
=\> #\<Duration: 1 week, 3 days, 2 minutes and 30 seconds\>  
d.to\_s  
=\> "1 week, 3 days, 2 minutes and 30 seconds"  
[d.weeks, d.days]  
=\> [1, 3]  
d.days = 7; d  
=\> #\<Duration: 2 weeks, 2 minutes and 30 seconds\>  
d.strftime('%w w, %d d, %h h, %m m, %s s')  
=\> "2 w, 0 d, 0 h, 2 m, 30 s"

And a direct link to the docs:  
[http://duration.rubyforge.org/doc/](http://duration.rubyforge.org/doc/)

Thanks Chris for pointing this out to me.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Daniel\_DeLorme](https://avatars.discourse-cdn.com/v4/letter/d/9d8465/32.png) [@Daniel\_DeLorme](https://rubytalk.org/u/Daniel_DeLorme)\
**Post date:** [3 December 2007 04:08 UTC](https://rubytalk.org/t/name-this-method/42681/7 "2007-12-03T04:08:36Z")

</div>

Phrogz wrote:

> > started = Time.now  
> > ended = Time.now + some\_time\_into\_the\_future  
> > elapsed = (ended.to\_i - started.to\_i).to\_elapsed\_time
> 
> Not as cool as the duration gem, but I offer this also:  
> [http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/266462](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/266462)

That approach works for a while but you can't accurately represent months or years because some months and some years have more seconds in them than some others. Let's see if I can get anyone interested in my implementation...

require "date  
class Time

&nbsp;&nbsp;&nbsp;#get the difference between 2 times as number of years+months+days+...  
&nbsp;&nbsp;&nbsp;def diff(other)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1,t2 = [self,other].map do |t|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, Rational(t.utc\_offset, 86400))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff = Hash.new(0)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff[:past] = t2 \< t1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1,t2 = t2,t1 if diff[:past]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = t1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff[:str] = ""  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = calc\_diff(diff,:year, t2){ |n| t \>\> 12\*n }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = calc\_diff(diff,:month, t2){ |n| t \>\> n }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = calc\_diff(diff,:day, t2){ |n| t + n }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = calc\_diff(diff,:hour, t2){ |n| t + Rational(n,24) }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = calc\_diff(diff,:minute,t2){ |n| t + Rational(n,24\*60) }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = calc\_diff(diff,:second,t2){ |n| t + Rational(n,24\*60\*60) }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;#utility method used above  
&nbsp;&nbsp;&nbsp;def calc\_diff(diff,type,t2)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff[type] += 1 until t2 \< yield(diff[type]+1)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if diff[type] \> 0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff[:str] \<\< ", " unless diff[:str].empty?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff[:str] \<\< "#{diff[type]} #{type}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diff[:str] \<\< "s" if diff[type] \> 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield(diff[type])  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;private :calc\_diff

&nbsp;&nbsp;&nbsp;#get the difference between 2 times as a human-friendly string  
&nbsp;&nbsp;&nbsp;#e.g. "5 hours, 23 minutes"  
&nbsp;&nbsp;&nbsp;def span\_to(other)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n = other - self  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "%.3f second" % n if n.abs \< 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d = self.diff(other)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str = d[:str].split(",").first(2).join(",")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str.gsub!(/(\d+)/,'-\1') if d[:past]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return str  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def time\_past  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.span\_to(Time.now)  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def time\_left  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Time.now.span\_to(self)  
&nbsp;&nbsp;&nbsp;end

end

\>\> t = Time.now  
=\> Mon Dec 03 13:02:21 JST 2007

\>\> t.diff(t+3600)  
=\> {:hour=\>1, :str=\>"1 hour", :past=\>false}

\>\> t.diff(t+86400)  
=\> {:str=\>"1 day", :day=\>1, :past=\>false}

\>\> t.diff(t+123456)  
=\> {:second=\>36, :hour=\>10, :str=\>"1 day, 10 hours, 17 minutes, 36 seconds", :day=\>1, :past=\>false, :minute=\>17}

\>\> Time.mktime(2007,1,1).diff Time.mktime(2007,10,1)  
=\> {:str=\>"9 months", :past=\>false, :month=\>9}

\>\> Time.mktime(2007,1,1).diff Time.mktime(2008,1,1)  
=\> {:year=\>1, :str=\>"1 year", :past=\>false}

> **···**
>
> > On Dec 2, 1:58 pm, Daniel Waite \<rabbitb...@gmail.com\> wrote:
