From: Dan Schmidt Date: 2000-12-20T07:40:04+09:00 Subject: [ruby-talk:7717] Re: Code sample for improvement Stephen White writes: | During an idle chat with someone on IRC, they presented some fairly | nasty code for printing a time interval in English. I cleaned it up | a bit and converted it to Ruby. | | #! /usr/bin/env ruby | | # Given the number of seconds, convert to English description | | def format(size, singular, plural) | if size > 0 | (size == 1) ? "#{size} #{singular} " : "#{size} #{plural} " | else | "" | end | end | | time = ARGV[0].to_i | | secs = time % 60; time = time / 60 | mins = time % 60; time = time / 60 | hours = time % 24; time = time / 24 | days = time % 30; time = time / 30 | months = time % 12; time = time / 12 | years = time | | res = "" | res += format(years, 'year', 'years') | res += format(months, 'month', 'months') | res += format(days, 'day', 'days') | res += format(hours, 'hour', 'hours') | res += format(mins, 'min', 'mins') | res += format(secs, 'sec', 'secs') | | puts res | | Example run: | | [steve@localhost steve]$ ./a 10000 | 2 hours 46 mins 40 secs | | I was interested in how the new constructs available in Ruby, like | closures and co-routines, could help clean up what really is pretty | ghastly code. I don't think closures and coroutines are going to be all that helpful here. Here's a translation that shows some of the power of Ruby, though it's optimized mostly for cuteness: def format (hash, name) size = hash[name] if size > 0 "#{size} #{name}" + (size > 1 ? "s" : "") end end time = ARGV[0].to_i Unit = Struct.new ("Unit", :name, :div) units = [['year', 10000], ['month', 12], ['day', 30], ['hour', 24], ['min', 60], ['sec', 60]].map { |u| Unit.new (*u) } t = {} units.reverse.each { |u| (time, t[u.name]) = time.divmod(u.div)} res = units.map { |u| format (t, u.name) } .join (' ').squeeze(' ').strip puts res -- http://www.dfan.org