Class: Duration

Inherits:
Object show all
Defined in:
lib/days_and_times/duration.rb

Direct Known Subclasses

Days, Hours, Minutes, Seconds, Weeks

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(count = 0, unit = 1, start_time = nil, auto_klass = {}) ⇒ Duration

Returns a new instance of Duration.



8
9
10
11
12
13
14
15
16
17
18
# File 'lib/days_and_times/duration.rb', line 8

def initialize(count=0,unit=1,start_time=nil,auto_klass={})
  if unit.is_a?(Time) || unit.is_a?(DateTime)
    start_time = unit
    unit = 1
  end
  options = {:count => count || 0, :unit => unit || 1, :start_time => start_time}.merge(count.is_a?(Hash) ? count : {})

  @unit = options[:unit]
  @length = (@unit * options[:count].to_f).round
  @start_time = options[:start_time]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ Object

                                                    • *



266
267
268
269
270
# File 'lib/days_and_times/duration.rb', line 266

def method_missing(method_name, *args)
  # Delegate any missing methods to the start_time Time object, if we have a start_time and the method exists there.
  return self.start_time.send(method_name, *args) if self.anchored? && self.start_time.respond_to?(method_name)
  super
end

Instance Attribute Details

#lengthObject

Length is the length of the time span, in seconds Unit is a length of time (in seconds) to use in collection methods StartTime is an optional attribute that can ‘anchor’ a duration

to a specific real time.


7
8
9
# File 'lib/days_and_times/duration.rb', line 7

def length
  @length
end

#start_timeObject

Length is the length of the time span, in seconds Unit is a length of time (in seconds) to use in collection methods StartTime is an optional attribute that can ‘anchor’ a duration

to a specific real time.


7
8
9
# File 'lib/days_and_times/duration.rb', line 7

def start_time
  @start_time
end

#unitObject

Length is the length of the time span, in seconds Unit is a length of time (in seconds) to use in collection methods StartTime is an optional attribute that can ‘anchor’ a duration

to a specific real time.


7
8
9
# File 'lib/days_and_times/duration.rb', line 7

def unit
  @unit
end

Class Method Details

.create_find_within_method_for(other, method_name, other_method_name) ⇒ Object



261
262
263
# File 'lib/days_and_times/duration.rb', line 261

def self.create_find_within_method_for(other, method_name, other_method_name)
  self.bind_class_object_method(other, method_name, other_method_name, [[], ['self.start_time', 'self.end_time']])
end

.lengthObject



27
28
29
# File 'lib/days_and_times/duration.rb', line 27

def self.length
  1
end

.new(*args) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/days_and_times/duration.rb', line 19

def self.new(*args)
  a = super
  if self.name == 'Duration' && (args.last.is_a?(Hash) ? args.last[:auto_class] == true : true)
    a.send(:auto_class)
  else
    a
  end
end

Instance Method Details

#*(value) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/days_and_times/duration.rb', line 103

def *(value)
  if value.is_a?(Duration)
    @length * value.length * value.unit
  elsif value.respond_to?(:to_i)
    auto_class(Duration.new(@length * value))
  else
    raise TypeError, "Can't convert #{value.class.name} to an integer."
  end
end

#+(value) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/days_and_times/duration.rb', line 96

def +(value)
  if value.respond_to?(:to_i)
    auto_class(Duration.new(@length + value.to_i))
  else
    raise TypeError, "Can't convert #{value.class.name} to an integer."
  end
end

#-(value) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/days_and_times/duration.rb', line 89

def -(value)
  if value.respond_to?(:to_i)
    auto_class(Duration.new(@length - value.to_i))
  else
    raise TypeError, "Can't convert #{value.class.name} to an integer."
  end
end

#/(value) ⇒ Object



112
113
114
115
116
117
118
119
120
# File 'lib/days_and_times/duration.rb', line 112

def /(value)
  if value.is_a?(Duration)
    @length / (value.length * value.unit)
  elsif value.respond_to?(:to_i)
    auto_class(Duration.new(@length / value))
  else
    raise TypeError, "Can't convert #{value.class.name} to an integer."
  end
end

#===(other) ⇒ Object



70
71
72
# File 'lib/days_and_times/duration.rb', line 70

def ===(other)
  self.to_f == other.to_f
end

#abs_lengthObject



54
55
56
# File 'lib/days_and_times/duration.rb', line 54

def abs_length
  @length
end

#abs_length=(value) ⇒ Object



47
48
49
50
51
52
53
# File 'lib/days_and_times/duration.rb', line 47

def abs_length=(value)
  if value.respond_to?(:to_i)
    @length = value.to_i
  else
    raise TypeError, "Can't set a Duration's length to a #{value.class.name} object."
  end
end

#agoObject



194
195
196
# File 'lib/days_and_times/duration.rb', line 194

def ago
  self.before(Time.now)
end

#anchored?Boolean

Returns:

  • (Boolean)


178
179
180
# File 'lib/days_and_times/duration.rb', line 178

def anchored?
  !self.start_time.nil?
end

#before(time) ⇒ Object



188
189
190
# File 'lib/days_and_times/duration.rb', line 188

def before(time)
  time - @length
end

#coerce(*args) ⇒ Object



66
67
68
# File 'lib/days_and_times/duration.rb', line 66

def coerce(*args)
  to_f.coerce(*args)
end

#collect(use_unit = self.class.length, &block) ⇒ Object



224
225
226
227
228
229
230
# File 'lib/days_and_times/duration.rb', line 224

def collect(use_unit=self.class.length,&block)
  ary = []
  self.each(use_unit) do |x|
    ary << (block_given? ? yield(x) : x)
  end
  ary
end

#create_find_within_method_for(other, method_name, other_method_name) ⇒ Object

                                                    • *

Through some ingenious metacoding (see ‘def bind_object_method’) below, it is possible to create a new method on a Duration object to a method on another object, in order to gather information based on the duration mentioned.



258
259
260
# File 'lib/days_and_times/duration.rb', line 258

def create_find_within_method_for(other, method_name, other_method_name)
  self.bind_object_method(other, method_name, other_method_name, [[], ['self.start_time', 'self.end_time']])
end

#daysObject



144
145
146
# File 'lib/days_and_times/duration.rb', line 144

def days
  @length.to_f / Day.length
end

#each(use_unit = self.class.length) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/days_and_times/duration.rb', line 231

def each(use_unit=self.class.length)
  remainder = @length.to_f % use_unit
  ret = []
  if self.start_time.nil?
    (@length.to_f / use_unit).to_i.times do |i|
      ret << Duration.new(1, use_unit)
      yield(ret[-1])
    end
  else
    (@length.to_f / use_unit).to_i.times do |i|
      ret << Duration.new(1, use_unit, (self.start_time + (use_unit * i)))
      yield(ret[-1])
    end
  end
  if remainder > 0
    ret << (self.start_time.nil? ? Duration.new(remainder, 1) : Duration.new(remainder, 1, (self.start_time + @length - remainder)))
    yield(ret[-1])
  end
  ret
end

#each_day(&block) ⇒ Object



212
213
214
# File 'lib/days_and_times/duration.rb', line 212

def each_day(&block)
  self.each(Day.length,&block)
end

#each_hour(&block) ⇒ Object



215
216
217
# File 'lib/days_and_times/duration.rb', line 215

def each_hour(&block)
  self.each(Hour.length,&block)
end

#each_minute(&block) ⇒ Object



218
219
220
# File 'lib/days_and_times/duration.rb', line 218

def each_minute(&block)
  self.each(Minute.length,&block)
end

#each_second(&block) ⇒ Object



221
222
223
# File 'lib/days_and_times/duration.rb', line 221

def each_second(&block)
  self.each(Second.length,&block)
end

#each_week(&block) ⇒ Object

                                                    • *

A Duration can be treated as a ‘collection’ of units



209
210
211
# File 'lib/days_and_times/duration.rb', line 209

def each_week(&block)
  self.each(Week.length,&block)
end

#end_timeObject



175
176
177
# File 'lib/days_and_times/duration.rb', line 175

def end_time
  @start_time + self
end

#end_time=(value) ⇒ Object



168
169
170
171
172
173
174
# File 'lib/days_and_times/duration.rb', line 168

def end_time=(value)
  if value.is_a?(Time) || value.is_a?(DateTime)
    @start_time = value.to_time - self #Subtracts this duration from the end_time to get the start_time
  else
    raise TypeError, "A Duration's end_time must be a Time or DateTime object."
  end
end

#ending(time) ⇒ Object



201
202
203
204
# File 'lib/days_and_times/duration.rb', line 201

def ending(time)
  self.end_time = time
  self
end

#from(time) ⇒ Object

                                              • *

Calculations using Duration as an intermediate



185
186
187
# File 'lib/days_and_times/duration.rb', line 185

def from(time)
  time + @length
end

#from_nowObject



191
192
193
# File 'lib/days_and_times/duration.rb', line 191

def from_now
  self.from(Time.now)
end

#hoursObject



147
148
149
# File 'lib/days_and_times/duration.rb', line 147

def hours
  @length.to_f / Hour.length
end

#in_daysObject



125
126
127
128
# File 'lib/days_and_times/duration.rb', line 125

def in_days
  self.unit = Day.length
  auto_class(self)
end

#in_hoursObject



129
130
131
132
# File 'lib/days_and_times/duration.rb', line 129

def in_hours
  self.unit = Hour.length
  auto_class(self)
end

#in_minutesObject



133
134
135
136
# File 'lib/days_and_times/duration.rb', line 133

def in_minutes
  self.unit = Minute.length
  auto_class(self)
end

#in_secondsObject



137
138
139
140
# File 'lib/days_and_times/duration.rb', line 137

def in_seconds
  self.unit = Second.length
  auto_class(self)
end

#in_weeksObject



121
122
123
124
# File 'lib/days_and_times/duration.rb', line 121

def in_weeks
  self.unit = Week.length
  auto_class(self)
end

#inspectObject



73
74
75
# File 'lib/days_and_times/duration.rb', line 73

def inspect
  "#<#{self.class.name}:#{self.object_id} (length=#{self.length.inspect}) #{self.instance_variables.reject {|d| d=='@length' || self.instance_variable_get(d).nil?}.collect {|iv| "#{iv}=#{self.instance_variable_get(iv).inspect}"}.join(' ')}>"
end

#minutesObject



150
151
152
# File 'lib/days_and_times/duration.rb', line 150

def minutes
  @length.to_f / Minute.length
end

#secondsObject



153
154
155
# File 'lib/days_and_times/duration.rb', line 153

def seconds
  @length.to_f / Second.length
end

#starting(time) ⇒ Object



197
198
199
200
# File 'lib/days_and_times/duration.rb', line 197

def starting(time)
  self.start_time = time
  self
end

#to_fObject



60
61
62
# File 'lib/days_and_times/duration.rb', line 60

def to_f
  self.abs_length.to_f
end

#to_iObject



57
58
59
# File 'lib/days_and_times/duration.rb', line 57

def to_i
  self.abs_length.to_i
end

#to_sObject



63
64
65
# File 'lib/days_and_times/duration.rb', line 63

def to_s
  "#{self.length} #{self.class.name}"
end

#weeksObject



141
142
143
# File 'lib/days_and_times/duration.rb', line 141

def weeks
  @length.to_f / Week.length
end