Created
November 5, 2009 07:00
-
-
Save chrisk/226836 to your computer and use it in GitHub Desktop.
DurationHelper#format_duration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module DurationHelper | |
# Takes a number of seconds as input and returns a formatted string. See | |
# tests for examples. | |
def format_duration(seconds, options = {}) | |
return "0 seconds" if seconds.floor == 0 | |
options.reverse_merge!(:parts_to_show => 4, :word_style => :short, :specific_end => false) | |
description = (options[:word_style] == :short) ? | |
[ ['sec', 60], ['min', 60], ['hr', 24], ['day'] ] : | |
[ ['second', 60], ['minute', 60], ['hour', 24], ['day'] ] | |
components = [] | |
units = seconds.floor | |
description.each do |component, max| | |
if max | |
components.unshift([units % max, component]) | |
break unless units >= max | |
units = units.to_f / max | |
else | |
components.unshift([units, component]) | |
end | |
end | |
parts_shown = 0 | |
results = components.map do |c| | |
next if parts_shown >= options[:parts_to_show] | |
parts_shown += 1 | |
number = c.first | |
if options[:specific_end].present? && parts_shown == options[:parts_to_show] && c.last =~ /^(hr|hour|day)/ | |
number = number.round_at(1).to_i_if_whole | |
else | |
number = number.floor | |
end | |
next if number == 0 | |
"#{number} #{number == 1 ? c.last : c.last.pluralize}" | |
end | |
results.compact.join(' ') | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe DurationHelper, "#format_duration" do | |
it "returns the correct string for many different durations" do | |
helper.format_duration(212751).should == "2 days 11 hrs 5 mins 51 secs" | |
helper.format_duration(79805).should == "22 hrs 10 mins 5 secs" | |
helper.format_duration(2730).should == "45 mins 30 secs" | |
helper.format_duration(142800).should == "1 day 15 hrs 40 mins" | |
helper.format_duration(352800).should == "4 days 2 hrs" | |
helper.format_duration(345600).should == "4 days" | |
helper.format_duration(32).should == "32 secs" | |
helper.format_duration(32.9).should == "32 secs" | |
helper.format_duration(0).should == "0 seconds" | |
helper.format_duration(0.5).should == "0 seconds" | |
end | |
it "excludes least-significant units using the :parts_to_show option"do | |
helper.format_duration(212751, :parts_to_show => 1).should == "2 days" | |
helper.format_duration(212751, :parts_to_show => 2).should == "2 days 11 hrs" | |
helper.format_duration(212751, :parts_to_show => 3).should == "2 days 11 hrs 5 mins" | |
helper.format_duration(212751, :parts_to_show => 0).should == "" | |
end | |
it "counts a zero component that's not shown in :parts_to_show" do | |
# By using :parts_to_show => 3, that means we want days, hours, and minutes; | |
# but if hours turns out to be zero, then we'll actually just show 2 parts. | |
helper.format_duration(1.day + 1.minute + 1.second, :parts_to_show => 3).should == "1 day 1 min" | |
end | |
it "uses short duration words with :word_style => :short" do | |
helper.format_duration(2730, :word_style => :short).should == "45 mins 30 secs" | |
end | |
it "uses long duration words with :word_style => :long" do | |
helper.format_duration(2730, :word_style => :long).should == "45 minutes 30 seconds" | |
end | |
it "uses a float for a least-significant part in days or hours with :specific_end => true" do | |
helper.format_duration(352800, :specific_end => true).should == "4 days 2 hrs" | |
helper.format_duration(352800, :parts_to_show => 1, :specific_end => true).should == "4.1 days" | |
helper.format_duration(352835, :parts_to_show => 2, :specific_end => true).should == "4 days 2 hrs" | |
helper.format_duration(79805, :parts_to_show => 1, :specific_end => true).should == "22.2 hrs" | |
helper.format_duration(79805, :parts_to_show => 2, :specific_end => true).should == "22 hrs 10 mins" | |
helper.format_duration(79805, :parts_to_show => 3, :specific_end => true).should == "22 hrs 10 mins 5 secs" | |
helper.format_duration(79200, :parts_to_show => 1, :specific_end => true).should == "22 hrs" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment