Class: Duration
- Inherits:
-
Object
- Object
- Duration
- 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
readonly
Returns the value of attribute days.
-
#hours ⇒ Object
readonly
Returns the value of attribute hours.
-
#minutes ⇒ Object
readonly
Returns the value of attribute minutes.
-
#seconds ⇒ Object
readonly
Returns the value of attribute seconds.
-
#total ⇒ Object
(also: #to_i)
readonly
Returns the value of attribute total.
-
#weeks ⇒ Object
readonly
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.
-
#initialize(seconds_or_attr) ⇒ Duration
constructor
Initialize Duration class.
-
#inspect ⇒ Object
Inspection string–Similar to #to_s except that it has the class name.
-
#method_missing(method, *args) ⇒ Object
Intercept certain attribute writers.
-
#strftime(fmt) ⇒ Object
Format duration.
-
#to_s ⇒ Object
Friendly, human-readable string representation of the duration.
Constructor Details
#initialize(seconds_or_attr) ⇒ 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>
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/duration.rb', line 48 def initialize(seconds_or_attr) if (h = seconds_or_attr).kind_of? Hash seconds = 0 seconds += h[:weeks] * WEEK if h.key? :weeks seconds += h[:days] * DAY if h.key? :days seconds += h[:hours] * HOUR if h.key? :hours seconds += h[:minutes] * MINUTE if h.key? :minutes seconds += h[:seconds] * SECOND if h.key? :seconds 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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ Object
Intercept certain attribute writers. Intercepts ‘weeks=’, ‘days=’, ‘hours=’, ‘minutes=’, ‘seconds=’, and ‘total=’
Example
d = Duration.new(:days => 6) => #<Duration: 6 days> d.days += 1; d => #<Duration: 1 week>
109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/duration.rb', line 109 def method_missing(method, *args) case method when :weeks= then initialize(WEEK * args[0] + (@total - WEEK * @weeks )) when :days= then initialize(DAY * args[0] + (@total - DAY * @days )) when :hours= then initialize(HOUR * args[0] + (@total - HOUR * @hours )) when :minutes= then initialize(MINUTE * args[0] + (@total - MINUTE * @minutes)) when :seconds= then initialize(SECOND * args[0] + (@total - SECOND * @seconds)) when :total= then initialize(args[0]) else raise NoMethodError, "undefined method `#{method}' for #{inspect}" end end |
Instance Attribute Details
#days ⇒ Object (readonly)
Returns the value of attribute days.
30 31 32 |
# File 'lib/duration.rb', line 30 def days @days end |
#hours ⇒ Object (readonly)
Returns the value of attribute hours.
30 31 32 |
# File 'lib/duration.rb', line 30 def hours @hours end |
#minutes ⇒ Object (readonly)
Returns the value of attribute minutes.
30 31 32 |
# File 'lib/duration.rb', line 30 def minutes @minutes end |
#seconds ⇒ Object (readonly)
Returns the value of attribute seconds.
30 31 32 |
# File 'lib/duration.rb', line 30 def seconds @seconds end |
#total ⇒ Object (readonly) Also known as: to_i
Returns the value of attribute total.
30 31 32 |
# File 'lib/duration.rb', line 30 def total @total end |
#weeks ⇒ Object (readonly)
Returns the value of attribute weeks.
30 31 32 |
# File 'lib/duration.rb', line 30 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>
196 197 198 |
# File 'lib/duration.rb', line 196 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>
170 171 172 |
# File 'lib/duration.rb', line 170 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>
183 184 185 |
# File 'lib/duration.rb', line 183 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>
209 210 211 |
# File 'lib/duration.rb', line 209 def /(other) self.class.new(@total / other.to_i) 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>
157 158 159 |
# File 'lib/duration.rb', line 157 def inspect "#<#{self.class}: #{(s = to_s).empty? ? '...' : s}>" 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 %% - 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!”
86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/duration.rb', line 86 def strftime(fmt) h =\ {'w' => @weeks , 'd' => @days , 'h' => @hours , 'm' => @minutes, 's' => @seconds} fmt.gsub(/%?%(w|d|h|m|s)/) 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”
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/duration.rb', line 131 def to_s str = '' [['weeks' , @weeks ], ['days' , @days ], ['hours' , @hours ], ['minutes' , @minutes], ['seconds' , @seconds]].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 |