Representing a span of time

Say I have two time objects represented as floats like so:

x = 64299600.0
y = 1157489583.2798

I want to subtract x from y and then represent the difference as years,
months, days, hours, minutes and seconds.

I don't see how the Time library would do this. Has anyone done
something like this? If so, how?

Thanks,
Brad

···

--
Posted via http://www.ruby-forum.com/.

Say I have two time objects represented as floats like so:

x = 64299600.0
y = 1157489583.2798

I want to subtract x from y and then represent the difference as years,
months, days, hours, minutes and seconds.

I don't see how the Time library would do this. Has anyone done
something like this? If so, how?

Thanks,
Brad

harp:~ > cat a.rb
class Time
   module Units
     def __less__() "/" end
     def __more__() "*" end
     def microseconds() self.send(Float(__more__,(10 ** -6))) end
     def milliseconds() self.send(Float(__more__,(10 ** -3))) end
     def seconds() self end
     def minutes() seconds.send(__more__,60) end
     def hours() minutes.send(__more__,60) end
     def days() hours.send(__more__,24) end
     def weeks() days.send(__more__,7) end
     def months() weeks.send(__more__,4) end
     def years() months.send(__more__,12) end
     def decades() years.send(__more__,10) end
     def centuries() decades.send(__more__,10) end
     instance_methods.select{|m| m !~ /__/}.each do |plural|
       singular = plural.chop
       alias_method singular, plural
     end
   end
   module DiffUnits
     include ::Time::Units
     def __less__() "*" end
     def __more__() "/" end
   end
   alias_method "__delta__", "-" unless respond_to? "__delta__"
   def - other
     ret = __delta__ other
     ret.extend DiffUnits
     ret
   end
end
class Numeric
   include ::Time::Units
end

if $0 == __FILE__
   require "yaml"
   require "time"

   now = Time::now

   a = now
   y 'a' => a

   b = now + 2.hours + 2.minutes
   y 'b' => b

   d = b - a
   %w( seconds minutes hours days ).each do |unit|
     y "d.#{ unit }" => d.send(unit)
   end
end

harp:~ > ruby a.rb
b: 2006-09-05 17:28:06.341147 -06:00
d.seconds: 7320.0
d.minutes: 122.0
d.hours: 2.03333333333333
d.days: 0.0847222222222222

regards.

-a

···

On Wed, 6 Sep 2006, Brad Tilley wrote:
a: 2006-09-05 15:26:06.341147 -06:00
--
what science finds to be nonexistent, we must accept as nonexistent; but what
science merely does not find is a completely different matter... it is quite
clear that there are many, many mysterious things.
- h.h. the 14th dalai lama

Brad Tilley wrote:

Say I have two time objects represented as floats like so:

x = 64299600.0
y = 1157489583.2798

I want to subtract x from y and then represent the difference as years, months, days, hours, minutes and seconds.

I don't see how the Time library would do this. Has anyone done something like this? If so, how?

This may not be exactly what you had in mind, but it's better than the other proposed "solutions" when it comes to displaying the number of months or years between two dates: (uses rails activesupport)

class Time
   def time_span(other = nil)
     other ||= self.utc? ? Time.now.utc : Time.now
     other.time_spent(self)
   end
   def time_spent(other = nil)
     other ||= self.utc? ? Time.now.utc : Time.now
     n = other - self
     case n.abs
     when 0...60 #1.minute
       "%d seconds" % n
     when 0...3600 #1.hour
       "%.1f minutes" % (n / 60)
     when 0...86400 #1.day
       "%.1f hours" % (n / 3600)
     else
       sign = "-" if self > other
       t1,t2 = [other,self].sort
       if t2.year != t1.year and t2 >= t1.advance(:years=>1)
         nb_years = t2.year - t1.year
         t = t1.advance(:years => nb_years)
         t = t1.advance(:years => (nb_years -= 1)) if t > t2
         "#{sign}%.1f years" % (nb_years + (t2 - t).to_f / (t.advance(:years=>1) - t))
       elsif t2 >= t1.advance(:months=>1)
         nb_months = (t1.year==t2.year ? 0 : 12) + t2.month - t1.month
         t = t1.advance(:months => nb_months)
         t = t1.advance(:months => (nb_months -= 1)) if t > t2
         "#{sign}%.1f months" % (nb_months + (t2 - t).to_f / (t.advance(:months=>1) - t))
       else
         "%.1f days" % (n / 1.0.day)
       end
     end
   end
end

>> t.time_span(t - 26.seconds)
=> "26 seconds"
>> t.time_span(t - 26.hours)
=> "1.1 days"
>> t.time_span(t - 26.days)
=> "26.0 days"
>> t.time_span(t - 26.months)
=> "2.1 years"

Say I have two time objects represented as floats like so:

x = 64299600.0
y = 1157489583.2798

I want to subtract x from y and then represent the difference as years,
months, days, hours, minutes and seconds.

I don't see how the Time library would do this. Has anyone done
something like this? If so, how?

[SNIP-CODE]

harp:~ > ruby a.rb
a: 2006-09-05 15:26:06.341147 -06:00
b: 2006-09-05 17:28:06.341147 -06:00
d.seconds: 7320.0
d.minutes: 122.0
d.hours: 2.03333333333333
d.days: 0.0847222222222222

I think he wants something more like this, where all of the different
options collectively add up to the total time interval (rather than yours
where each different unit of time nonetheless represents the whole span)

class TimeSpan
   # takes input in seconds because that's what Time#to_i returns
   def initialize(seconds)
      @raw_seconds=seconds
      breakdown
   end
   
   attr_reader :seconds,:minutes,:hours,:days
   attr_reader :raw_seconds

   private
   attr_writer :seconds,:minutes,:hours,:days

   # [:x=,y] represents that y is the maximum number of x before
   # carrying over to the next larger unit of time
   FACTORS=[[:seconds=,60],[:minutes=,60],
      [:hours=,24],[:days=,nil]]

   def breakdown
      higherintervals=@raw_seconds
      FACTORS.each do |method, max|
   higherintervals, thisinterval= \
      higherintervals.divmod(max) unless max==nil
   thisinterval=higherintervals if max==nil
   send(method,thisinterval)
      end
   end
end

irb(main):020:0> a=Time.now.to_i
=> 1157512271
irb(main):021:0> b=Time.now.to_i
=> 1157512296
irb(main):025:0> TimeSpan.new(b-a)
=> #<TimeSpan:0xa7cbfc58 @days=0, @hours=0, @minutes=0,
   @seconds=25, @raw_seconds=25>

Can't do years and months without more complicated math, and a definite
knowledge of what the start date and end date are. But at least this
should be closer.

--Ken Bloom

···

On Tue, 05 Sep 2006 15:26:41 -0600, ara.t.howard wrote:

On Wed, 6 Sep 2006, Brad Tilley wrote:

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/