Ruby/Rails - How to convert seconds to time?

Viewed 23348

I need to perform the following conversion:

0     -> 12.00AM
1800  -> 12.30AM
3600  -> 01.00AM
...
82800 -> 11.00PM
84600 -> 11.30PM

I came up with this:

(0..84600).step(1800){|n| puts "#{n.to_s} #{Time.at(n).strftime("%I:%M%p")}"}

which gives me the wrong time, because Time.at(n) expects n to be number of seconds from epoch:

0     -> 07:00PM
1800  -> 07:30PM
3600  -> 08:00PM
...
82800 -> 06:00PM
84600 -> 06:30PM

What would be the most optimal, time zone independent solution for this transformation?

4 Answers

In other solutions, the hour-counter would be reset to 00 when crossing 24-hour day boundaries. Also beware that Time.at rounds down, so it will give the wrong result if the input has any fractional seconds (f.ex. when t=479.9 then Time.at(t).utc.strftime("%H:%M:%S") will give 00:07:59 and not 00:08:00` which is the correct one).

If you want a way to convert any number of seconds (even high counts larger than 24-hour day spans) into an ever increasing HH:MM:SS counter, and handle potential fractional seconds, then try this:

# Will take as input a time in seconds (which is typically a result after subtracting two Time objects),
# and return the result in HH:MM:SS, even if it exceeds a 24 hour period.
def formatted_duration(total_seconds)
  total_seconds = total_seconds.round # to avoid fractional seconds potentially compounding and messing up seconds, minutes and hours
  hours = total_seconds / (60*60)
  minutes = (total_seconds / 60) % 60 # the modulo operator (%) gives the remainder when leftside is divided by rightside. Ex: 121 % 60 = 1
  seconds = total_seconds % 60
  [hours, minutes, seconds].map do |t|
    # Right justify and pad with 0 until length is 2. 
    # So if the duration of any of the time components is 0, then it will display as 00
    t.round.to_s.rjust(2,'0')
  end.join(':')
end

Modified from @springerigor's and suggestion in the discussion at https://gist.github.com/shunchu/3175001

Related