seconds = 356521N.B.: This relies on Ruby's integer division -- dividing an integer by an integer results in an integer, with any fractional remainder discarded.
days = seconds / (24 * 60 * 60)
seconds = seconds % (24 * 60 * 60)
hours = seconds / (60 * 60)
seconds = seconds % (60 * 60)
minutes = seconds / 60
seconds = seconds % 60
My pair and I ended up implementing something very much like this, but it left a bad taste in my mouth. I mean, it works and all, but it feels kind of ... non-functional. Ya know?
So, after much fretting and sleeplessness last night ... behold:
seconds = 356521This version needs to be run in a Rails
days, hours, minutes, seconds =
[1.day, 1.hour, 1.minute, 1.second].inject([]) do |acc, unit|
quotient, seconds = seconds.divmod unit
acc << quotient
end
script/console
rather than irb
, because it makes use of the Rails shortcut definitions of the number of seconds in various units of time. You could easily convert to plain irb
-able Ruby by replacing 1.day
et al above with their numeric equivalents.The resulting code is both (more) functional, and more quintessentially Ruby-ish.
divmod
and multiple assignment let us figure out the quotient and the remainder of the division in one go, and inject
lets us accumulate the results and ultimately multiply assign them to their respective units. Neato.
I'm a little bummed, though, that this version has the side effect of destroying the original contents of
seconds
, as well as requiring seconds
to be defined outside the scope of the inject
. What would be really cool would be to have a version of inject
that allowed for multiple accumulators (or, really, a 'decumulator' in this case) such that all side effects could be contained within the inject
.