views:

304

answers:

4

Can Ruby do something like this?

irb(main):001:0> start = Time.now
=> Thu Nov 05 01:02:54 -0800 2009

irb(main):002:0> Time.now - start
=> 25.239

irb(main):003:0> (Time.now - start).duration
=> "25 seconds"

(the duration method doesn't exist now)... and similarly, report

23 minutes and 35 seconds
1 hour and 33 minutes
2 days and 3 hours

(either report the whole duration, up to how many seconds, or report up to 2 numbers and units (if day and hour is reported, then no need to tell how many minutes))

+1  A: 

You can do something like this, there may be a more elegant way to do it though:

require 'date'

start_time = Time.now
end_time = Time.now

time_diff = end_time - start_time
hours,minutes,seconds,frac = Date.day_fraction_to_time(time_diff)
puts "Time elapsed: #{hours} hours, #{minutes} minutes and #{seconds} seconds"

You could do some fairly simple funkiness with hours to get days and hours, and some switching to report the first two non-zero units.

Dominic Rodger
how come Date.day_fraction_to_time(25) returns [600, 0, 0, Rational(0, 1)] ?
動靜能量
This doesn't seem to get the right answer - end_time - start_time seems to be giving a number of seconds. I suspect there needs to be some kind of conversion before the day_fraction_to_time - perhaps day_fraction = time_diff / (24 * 60 * 60) and then use day_fraction in the call to day_fraction_to_time
edebill
(the reason it's saying 600 is because it thinks you're passing in 25 days as the day fraction, instead of 25 seconds)
edebill
+5  A: 

Here's a quick and simple way to implement this. Set predefined measurements for seconds, minutes, hours and days. Then depending on the size of the number, output the appropriate string with the those units. We'll extend Numeric so that you can invoke the method on any numeric class (Fixnum, Bignum, or in your case Float).

class Numeric
  def duration
    secs  = self.to_int
    mins  = secs / 60
    hours = mins / 60
    days  = hours / 24

    if days > 0
      "#{days} days and #{hours % 24} hours"
    elsif hours > 0
      "#{hours} hours and #{mins % 60} minutes"
    elsif mins > 0
      "#{mins} minutes and #{secs % 60} seconds"
    elsif secs >= 0
      "#{secs} seconds"
    end
  end
end
Mike Richards
Perhaps some additional handling should be added for cases where one or more of the items is equal to one (1 hours and 1 minutes => 1 hour and 1 minute) also.
Splash
Very neat. I love it :D
felipec
I spoke too soon; it doesn't work correctly. Should be something like: "#{days} days and #{hours % 24} hours"not "#{days} days and #{hours % days} hours"
felipec
@felipec You're absolutely right. Answer changed.
Mike Richards
+2  A: 

Have a look at the Rails DateHelpe.distance_of_time_in_words method. It will give you a great starting place. Despite being loaded with magic numbers, the approach should work for you.

EmFi
A: 
time_difference = current_time - old_time



 def seconds_fraction_to_time(time_difference)
    days = hours = mins = 0
      mins = (seconds / 60).to_i
      seconds = (seconds % 60 ).to_i
      hours = (mins / 60).to_i
      mins = (mins % 60).to_i
      days = (hours / 24).to_i
      hours = (hours % 24).to_i
    return [days,hours,mins,seconds]
  end

then you can print it out what ever way you wish,

i.e

if(days > 0)
return "#{days} Days #{hours} Hours"
else
return "#{hours} Hours #{mins} Minutes"
end
Mo