Here’s a quick script I swear I’ve written before but couldn’t find. If given a string as an argument, it converts it to seconds, and if given just a series of numbers, it converts the number to a human-readable string.
I needed this today when setting update intervals for Sparkle, and it’s something I’ve run into in the past. I usually pull up a calculator, which is annoying. There’s probably a simple Unix way to do it that I’ll hear about in the comments, which is ok, I still had fun writing it.
Since this is mostly likely to be of use to programmers, I won’t bother detailing how to turn it into an executable script. You got this.
Convert strings to seconds
Arguments are numbers followed by a timespan. It works on shorthand (w = week, day = d, hours = h, minutes = m, seconds = s), but will convert most strings to this format automatically, e.g. “2 days, 3 hours, and 30 min” is the same as “2d3h”. As long as the format is a number followed by strings that start with w, d, h, m, or s, it’ll figure it out.
#!/usr/bin/env ruby# seconds, a CLI for interval conversion by Brett Terpstra 2017# Free for use by anyone, anywhere, at any time### convert days, hours, and minutes to seconds# Arguments are numbers followed by a timespan# (w = week day = d, hours = h, minutes = m, seconds = s)# e.g. 2 days and 3 hours = "2d3h"# unrecognized characters don't matter, so also "2 days, and 3 hours"# $ seconds 2 days, and 3 hours# => 183600## convert seconds to days, hours, and minutes# $ seconds 183600# => 2 days, 3 hoursrequire'bigdecimal'defhelp(do_exit=false)app=File.basename(__FILE__)usage=["#{app}: convert days, hours, and minutes to seconds"]usage.push("Usage: #{app} [Xw[Xd[Xh[Xm]]]] | [seconds]")usage.push("Examples:")usage.push("#{app} 5d2h3m => 439380")usage.push("#{app} 4d => 345600")usage.push("Or convert seconds to time units: #{app} 1125093 => 13 days, 31 minutes, 33 seconds")$stdout.puts(usage.join("\n"))ifdo_exitcode=do_exit.to_irescue0Process.exitcodeendendclassStringdefpluralnum,unit=self.split(/ /)ifnum.to_i>1returnself+'s'elsereturnselfendendenddeffrom_seconds(seconds)t=BigDecimal.new(seconds)mm,ss=t.divmod(60)hh,mm=mm.divmod(60)dd,hh=hh.divmod(24)output=[]output.push("#{dd.to_i} day".plural)ifdd>0output.push("#{hh.to_i} hour".plural)ifhh>0output.push("#{mm.to_i} minute".plural)ifmm>0output.push("#{ss.to_i} second".plural)ifss>0output.join(", ")# "%d days, %d hours, %d minutes, %d seconds" % [dd, hh, mm, ss]enddefto_seconds(input)secs={'w'=>604800,'d'=>86400,'h'=>3600,'m'=>60,'s'=>1}total=0parts=input.gsub(/([wdhms])[a-z]+/,'\1').gsub(/[^wdhms\d]/,'').scan(/\d+\w/)parts.eachdo|p|num,qty=p.split(/(?=[wdhms])/)ifsecs.key?qtytotal+=num.to_i*secs[qty]endendtotalendifSTDIN.stat.size>0ifRUBY_VERSION.to_f>1.9Encoding.default_external=Encoding::UTF_8Encoding.default_internal=Encoding::UTF_8input=STDIN.read.force_encoding('utf-8')elseinput=STDIN.readendelseifARGV.length>0ifARGV[0].strip.match(/^(-h|help|--help)$/)help(0)endinput=ARGV.join('')elsehelp(1)endendifinput=~/^\d+$/res=from_seconds(input)elseres=to_seconds(input)end$stdout.print(res)