From: Daniel DeLorme Date: 2007-12-03T13:08:36+09:00 Subject: Re: Name this method... Phrogz wrote: > On Dec 2, 1:58 pm, Daniel Waite 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}