| Class | Duration |
| In: |
lib/more/facets/duration.rb
|
| Parent: | Object |
Duration is a simple class that provides ways of easily manipulating durations (timespans) and formatting them as well.
require 'duration'
=> true
d = Duration.new(60 * 60 * 24 * 10 + 120 + 30)
=> #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
d.to_s
=> "1 week, 3 days, 2 minutes and 30 seconds"
[d.weeks, d.days]
=> [1, 3]
d.days = 7; d
=> #<Duration: 2 weeks, 2 minutes and 30 seconds>
d.strftime('%w w, %d d, %h h, %m m, %s s')
=> "2 w, 0 d, 0 h, 2 m, 30 s"
| WEEK | = | 60 * 60 * 24 * 7 |
| DAY | = | 60 * 60 * 24 |
| HOUR | = | 60 * 60 |
| MINUTE | = | 60 |
| SECOND | = | 1 |
| total | -> | to_i |
| days | [R] | |
| hours | [R] | |
| minutes | [R] | |
| total | [R] | |
| weeks | [R] |
Initialize Duration class.
Example
d = Duration.new(60 * 60 * 24 * 10 + 120 + 30)
=> #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
d = Duration.new(:weeks => 1, :days => 3, :minutes => 2, :seconds => 30)
=> #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
# File lib/more/facets/duration.rb, line 71 def initialize(seconds_or_attr = 0) if seconds_or_attr.kind_of? Hash # Part->time map table. h = {:weeks => WEEK, :days => DAY, :hours => HOUR, :minutes => MINUTE, :seconds => SECOND} # Loop through each valid part, ignore all others. seconds = seconds_or_attr.inject(0) do |sec, args| # Grab the part of the duration (week, day, whatever) and the number of seconds for it. part, time = args # Map each part to their number of seconds and the given value. # {:weeks => 2} maps to h[:weeks] -- so... weeks = WEEK * 2 if h.key?(prt = part.to_s.to_sym) then sec + time * h[prt] else 0 end end else seconds = seconds_or_attr end @total, array = seconds.to_f.round, [] @seconds = [WEEK, DAY, HOUR, MINUTE].inject(@total) do |left, part| array << left / part; left % part end @weeks, @days, @hours, @minutes = array end
Multiply two Durations.
Example
d = Duration.new(30)
=> #<Duration: 30 seconds>
d * 2
=> #<Duration: 1 minute>
# File lib/more/facets/duration.rb, line 332 def *(other) self.class.new(@total * other.to_i) end
Divide two Durations.
Example
d = Duration.new(30)
=> #<Duration: 30 seconds>
d / 2
=> #<Duration: 15 seconds>
# File lib/more/facets/duration.rb, line 345 def /(other) self.class.new(@total / other.to_i) end
Calls `<=>’ on Duration#total.
Example
5.days == 24.hours * 5
=> true
# File lib/more/facets/duration.rb, line 194 def <=>(other) @total <=> other.to_i end
For iterating through the duration set of weeks, days, hours, minutes, and seconds.
Example
Duration.new(:weeks => 1, :seconds => 30).each do |part, time|
puts "part: #{part}, time: #{time}"
end
Output
part: weeks, time: 1
part: days, time: 0
part: hours, time: 0
part: minutes, time: 0
part: seconds, time: 30
# File lib/more/facets/duration.rb, line 176 def each [['weeks' , @weeks ], ['days' , @days ], ['hours' , @hours ], ['minutes' , @minutes], ['seconds' , @seconds]].each do |part, time| # Yield to block yield part, time end end
Get the number of seconds of a given part, or simply just get the number of seconds.
Example
d = Duration.new(:weeks => 1, :days => 1, :hours => 1, :seconds => 30)
=> #<Duration: 1 week, 1 day, 1 hour and 30 seconds>
d.seconds(:weeks)
=> 604800
d.seconds(:days)
=> 86400
d.seconds(:hours)
=> 3600
d.seconds
=> 30
# File lib/more/facets/duration.rb, line 148 def seconds(part = nil) # Table mapping h = {:weeks => WEEK, :days => DAY, :hours => HOUR, :minutes => MINUTE} if [:weeks, :days, :hours, :minutes].include? part __send__(part) * h[part] else @seconds end end
Format duration.
Identifiers
%w -- Number of weeks
%d -- Number of days
%h -- Number of hours
%m -- Number of minutes
%s -- Number of seconds
%t -- Total number of seconds
%x -- Duration#to_s
%% -- Literal `%' character
Example
d = Duration.new(:weeks => 10, :days => 7)
=> #<Duration: 11 weeks>
d.strftime("It's been %w weeks!")
=> "It's been 11 weeks!"
# File lib/more/facets/duration.rb, line 117 def strftime(fmt) h =\ {'w' => @weeks , 'd' => @days , 'h' => @hours , 'm' => @minutes, 's' => @seconds, 't' => @total , 'x' => to_s} fmt.gsub(/%?%(w|d|h|m|s|t|x)/) do |match| match.size == 3 ? match : h[match[1..1]] end.gsub('%%', '%') end
Friendly, human-readable string representation of the duration.
Example
d = Duration.new(:seconds => 140)
=> #<Duration: 2 minutes and 20 seconds>
d.to_s
=> "2 minutes and 20 seconds"
# File lib/more/facets/duration.rb, line 272 def to_s str = '' each do |part, time| # Skip any zero times. next if time.zero? # Concatenate the part of the time and the time itself. str << "#{time} #{time == 1 ? part[0..-2] : part}, " end str.chomp(', ').sub(/(.+), (.+)/, '\1 and \2') end