Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert seconds into HH:MM:SS in Ruby
t = 236 # seconds
Time.at(t).utc.strftime("%H:%M:%S")
=> "00:03:56"
# Reference
# http://stackoverflow.com/questions/3963930/ruby-rails-how-to-convert-seconds-to-time
@kinnrot
Copy link

kinnrot commented Jul 19, 2017

+3

@guillermoap
Copy link

guillermoap commented Jul 21, 2017

+1

@Aminbhs
Copy link

Aminbhs commented Aug 26, 2017

+1

@redbar0n
Copy link

redbar0n commented Sep 8, 2017

I have used the solutions of @springerigor and @NayanaBhagat to make it a bit more readable / understandable than a cryptic oneliner. It also removes decimals by using rounding.

# 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

Updated: Added the initial total_seconds.round to fix the bug with fractional seconds, after @dblock commented on Jun 26, 2018, which brought it to attention (thanks).

I will try to keep my most updated version here, for the future: https://gist.github.com/redbar0n/2eb154b8381994b2c55301bd37f57c1f

@somethvictory
Copy link

somethvictory commented Nov 20, 2017

+1

@tangens
Copy link

tangens commented Jan 17, 2018

+1

@RemiDuvoux
Copy link

RemiDuvoux commented Feb 23, 2018

+1

@iGEL
Copy link

iGEL commented Mar 6, 2018

If you want to have output like 1h 30m:

def seconds_to_str(seconds)
  ["#{seconds / 3600}h", "#{seconds / 60 % 60}m", "#{seconds % 60}s"]
    .select { |str| str =~ /[1-9]/ }.join(" ")
end

seconds_to_str(2) # => "2s"
seconds_to_str(69) # => "1m 9s"
seconds_to_str(600) # => "10m"*
seconds_to_str(43_200) #=> "12h"
seconds_to_str(43_205) # => "12h 5s" <- no minutes!
seconds_to_str(100_000) # => "27h 46m 40s" <- you could adjust it for days etc.

@ardinusawan
Copy link

ardinusawan commented Mar 22, 2018

+1

@joerzepiejewski
Copy link

joerzepiejewski commented May 9, 2018

👍

@dblock
Copy link

dblock commented Jun 26, 2018

Beware of round being used here. If total seconds is 479.8282647584973

  • @redbar0n code produces the wrong result, "00:08:60"
  • @lonny code and the original Time.at version round down, so "00:07:59", but this is not the best approximation

Related and working:

@zalivanvitaly
Copy link

zalivanvitaly commented Sep 6, 2018

+1

@eliasdouglas
Copy link

eliasdouglas commented Feb 19, 2019

+1

@dhurba87
Copy link

dhurba87 commented Feb 21, 2019

+1

@YoshitsuguFujii
Copy link

YoshitsuguFujii commented Mar 15, 2019

+1

@alexwebgr
Copy link

alexwebgr commented Apr 3, 2019

Added days!
extending on @springerigor solution

    def formatted_duration(total_seconds)
      days = total_seconds / (60 * 60 * 24)
      hours = total_seconds / (60 * 60)
      hours -= 24 if days > 0
      minutes = (total_seconds / 60) % 60
      seconds = total_seconds % 60

      "#{days}d #{hours}h #{minutes}m #{seconds}s"
    end

@PoombavaiS
Copy link

PoombavaiS commented Jun 24, 2019

👍

Copy link

ghost commented Jul 15, 2019

This is pretty cool!

@itssomething
Copy link

itssomething commented Aug 7, 2019

👍

@pmichaeljones
Copy link

pmichaeljones commented Nov 26, 2019

Solid!

@hdchinh
Copy link

hdchinh commented Mar 31, 2020

Thanks, really good 😄

@trangtungn
Copy link

trangtungn commented Apr 7, 2020

+1

@tthuydang
Copy link

tthuydang commented Sep 12, 2020

+1

@vilusa
Copy link

vilusa commented Oct 16, 2020

+1

@magne
Copy link

magne commented Dec 6, 2020

@joshuapinter, nice code, but I'm not the Magne that contributed it to SO.

@nfumiya
Copy link

nfumiya commented Jan 21, 2021

+1

@gabrielrb
Copy link

gabrielrb commented Feb 26, 2021

Nice! I also needed days, so thanks @alexwebgr
Just a small change, in case it's more than 48 hours

def formatted_duration(total_seconds)
    days = total_seconds / (60 * 60 * 24)
    hours = total_seconds / (60 * 60)
    hours -= (24 * days) if days >= 1
    minutes = (total_seconds / 60) % 60
    seconds = total_seconds % 60

    "#{days}d #{hours}h #{minutes}min #{seconds}s"
end

Copy link

ghost commented Mar 1, 2021

You can also use %T, it's a combination shortcut to get 24-hour time (%H:%M:%S)

Time.at(624).gmtime.strftime('%T')
=> "00:10:24"

@shilovk
Copy link

shilovk commented Jun 24, 2021

  def formatted_duration(total_seconds)
    days = (total_seconds / (60 * 60 * 24)).to_i
    hours = ((total_seconds / (60 * 60)) % 60).to_i
    minutes = ((total_seconds / 60) % 60).to_i
    seconds = (total_seconds % 60).to_i

    "#{days} d. #{hours} h. #{minutes} m. #{seconds} s."
  end

@aarkerio
Copy link

aarkerio commented Jul 8, 2021

☑️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment