Class: Duration
- Inherits:
-
Object
- Object
- Duration
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/duration.rb
Overview
Author
Matthew Harris ([email protected])
Project
www.rubyforge.org/projects/duration
Synopsis
Duration is a simple class that provides ways of easily manipulating durations (timespans) and formatting them as well.
Usage
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”
Constant Summary collapse
- WEEK =
60 * 60 * 24 * 7
- DAY =
60 * 60 * 24
- HOUR =
60 * 60
- MINUTE =
60
- SECOND =
1
Instance Attribute Summary collapse
-
#days ⇒ Object
Returns the value of attribute days.
-
#hours ⇒ Object
Returns the value of attribute hours.
-
#minutes ⇒ Object
Returns the value of attribute minutes.
-
#total ⇒ Object
(also: #to_i)
readonly
Returns the value of attribute total.
-
#weeks ⇒ Object
Returns the value of attribute weeks.
Instance Method Summary collapse
-
#*(other) ⇒ Object
Multiply two Durations.
-
#+(other) ⇒ Object
Add to Duration.
-
#-(other) ⇒ Object
Subtract from Duration.
-
#/(other) ⇒ Object
Divide two Durations.
-
#<=>(other) ⇒ Object
Calls ‘<=>’ on Duration#total.
-
#each ⇒ Object
For iterating through the duration set of weeks, days, hours, minutes, and seconds.
-
#initialize(seconds_or_attr = 0) ⇒ Duration
constructor
Initialize Duration class.
-
#inspect ⇒ Object
Inspection string–Similar to #to_s except that it has the class name.
-
#seconds(part = nil) ⇒ Object
Get the number of seconds of a given part, or simply just get the number of seconds.
-
#seconds=(n) ⇒ Object
Set the number of minutes.
-
#strftime(fmt) ⇒ Object
Format duration.
-
#to_s ⇒ Object
Friendly, human-readable string representation of the duration.
Constructor Details
#initialize(seconds_or_attr = 0) ⇒ Duration
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>
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/duration.rb', line 50 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 |
Instance Attribute Details
#days ⇒ Object
Returns the value of attribute days.
33 34 35 |
# File 'lib/duration.rb', line 33 def days @days end |
#hours ⇒ Object
Returns the value of attribute hours.
33 34 35 |
# File 'lib/duration.rb', line 33 def hours @hours end |
#minutes ⇒ Object
Returns the value of attribute minutes.
33 34 35 |
# File 'lib/duration.rb', line 33 def minutes @minutes end |
#total ⇒ Object (readonly) Also known as: to_i
Returns the value of attribute total.
33 34 35 |
# File 'lib/duration.rb', line 33 def total @total end |
#weeks ⇒ Object
Returns the value of attribute weeks.
33 34 35 |
# File 'lib/duration.rb', line 33 def weeks @weeks end |
Instance Method Details
#*(other) ⇒ Object
Multiply two Durations.
Example
d = Duration.new(30) => #<Duration: 30 seconds> d * 2 => #<Duration: 1 minute>
311 312 313 |
# File 'lib/duration.rb', line 311 def *(other) self.class.new(@total * other.to_i) end |
#+(other) ⇒ Object
Add to Duration.
Example
d = Duration.new(30) => #<Duration: 30 seconds> d + 30 => #<Duration: 1 minute>
285 286 287 |
# File 'lib/duration.rb', line 285 def +(other) self.class.new(@total + other.to_i) end |
#-(other) ⇒ Object
Subtract from Duration.
Example
d = Duration.new(30) => #<Duration: 30 seconds> d - 15 => #<Duration: 15 seconds>
298 299 300 |
# File 'lib/duration.rb', line 298 def -(other) self.class.new(@total - other.to_i) end |
#/(other) ⇒ Object
Divide two Durations.
Example
d = Duration.new(30) => #<Duration: 30 seconds> d / 2 => #<Duration: 15 seconds>
324 325 326 |
# File 'lib/duration.rb', line 324 def /(other) self.class.new(@total / other.to_i) end |
#<=>(other) ⇒ Object
Calls ‘<=>’ on Duration#total.
Example
5.days == 24.hours * 5 => true
173 174 175 |
# File 'lib/duration.rb', line 173 def <=>(other) @total <=> other.to_i end |
#each ⇒ Object
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
155 156 157 158 159 160 161 162 163 164 |
# File 'lib/duration.rb', line 155 def each [['weeks' , @weeks ], ['days' , @days ], ['hours' , @hours ], ['minutes' , @minutes], ['seconds' , @seconds]].each do |part, time| # Yield to block yield part, time end end |
#inspect ⇒ Object
Inspection string–Similar to #to_s except that it has the class name.
Example
Duration.new(:seconds => 140) => #<Duration: 2 minutes and 20 seconds>
272 273 274 |
# File 'lib/duration.rb', line 272 def inspect "#<#{self.class}: #{(s = to_s).empty? ? '...' : s}>" end |
#seconds(part = nil) ⇒ Object
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
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/duration.rb', line 127 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 |
#seconds=(n) ⇒ Object
Set the number of minutes.
Example
d = Duration.new(0) => #<Duration: …> d.seconds = 30; d => #<Duration: 30 seconds>
238 239 240 |
# File 'lib/duration.rb', line 238 def seconds=(n) initialize(:seconds => (@total + n) - @seconds) end |
#strftime(fmt) ⇒ Object
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!”
96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/duration.rb', line 96 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 |
#to_s ⇒ Object
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”
251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/duration.rb', line 251 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 |