Phrogz wrote:
> On Dec 2, 1:58 pm, Daniel Waite <rabbitb... / gmail.com> 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

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

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

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

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

   def time_past
     self.span_to(Time.now)
   end

   def time_left
     Time.now.span_to(self)
   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}