Class: RelativeTime

Inherits:
Object
  • Object
show all
Defined in:
lib/timerizer.rb

Overview

Represents a relative amount of time. For example, ‘5 days`, `4 years`, and `5 years, 4 hours, 3 minutes, 2 seconds` are all RelativeTimes.

Constant Summary collapse

@@units =

All potential units. Key is the unit name, and the value is its plural form.

{
  :second     => :seconds,
  :minute     => :minutes,
  :hour       => :hours,
  :day        => :days,
  :week       => :weeks,
  :month      => :months,
  :year       => :years,
  :decade     => :decades,
  :century    => :centuries,
  :millennium => :millennia
}
@@in_seconds =

Unit values in seconds. If a unit is not present in this hash, it is assumed to be in the @@in_months hash.

{
    :second => 1,
    :minute => 60,
    :hour   => 3600,
    :day    => 86400,
    :week   => 604800
}
@@in_months =

Unit values in months. If a unit is not present in this hash, it is assumed to be in the @@in_seconds hash.

{
  :month      => 1,
  :year       => 12,
  :decade     => 120,
  :century    => 1200,
  :millennium => 12000
}
@@average_seconds =

Average amount of time in a given unit. Used internally within the #average and #unaverage methods.

{
  :month => 2629746,
  :year  => 31556952
}

Instance Method Summary collapse

Constructor Details

#new(hash) ⇒ RelativeTime #new(count, unit) ⇒ RelativeTime

Initialize a new instance of RelativeTime.

Overloads:

  • #new(hash) ⇒ RelativeTime

    Parameters:

    • The base units to initialize with

  • #new(count, unit) ⇒ RelativeTime

    Parameters:

    • The number of units to initialize with

    • The unit to initialize. See @@units



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/timerizer.rb', line 51

def initialize(count = 0, unit = :second)
  if(count.is_a? Hash)
    @seconds = count[:seconds] || 0
    @months = count[:months] || 0
    return
  end

  @seconds = 0
  @months = 0

  if(@@in_seconds.has_key?(unit))
    @seconds = count * @@in_seconds.fetch(unit)
  elsif(@@in_months.has_key?(unit))
    @months = count * @@in_months.fetch(unit)
  end
end

Instance Method Details

#+(time) ⇒ Object

Add two RelativeTimes together.

Raises:

See Also:



226
227
228
229
230
231
232
# File 'lib/timerizer.rb', line 226

def +(time)
  raise ArgumentError unless time.is_a?(RelativeTime)
  RelativeTime.new({
    :seconds => @seconds + time.get(:seconds),
    :months => @months + time.get(:months)
  })
end

#-(time) ⇒ Object

Find the difference between two RelativeTimes.

Raises:

See Also:



237
238
239
240
241
242
243
# File 'lib/timerizer.rb', line 237

def -(time)
  raise ArgumentError unless time.is_a?(RelativeTime)
  RelativeTime.new({
    :seconds => @seconds - time.get(:seconds),
    :months => @months - time.get(:months)
  })
end

#after(time) ⇒ Time

Return the time after the given time according to the current RelativeTime.

Parameters:

  • The starting time

Returns:

  • The time after the current RelativeTime and the given time

See Also:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/timerizer.rb', line 120

def after(time)
  time = time.to_time + @seconds

  new_year = time.year
  new_month = time.month + @months
  while new_month > 12
    new_year += 1
    new_month -= 12
  end
  if(Date.valid_date?(new_year, new_month, time.day))
    new_day = time.day
  else
    new_day = Date.new(new_year, new_month).days_in_month
  end


  new_time = Time.new(
    new_year, new_month, new_day,
    time.hour, time.min, time.sec
  )
  Time.at(new_time.to_i, time.nsec/1000.0)
end

#agoTime

Return the time between the RelativeTime and the current time.

Returns:

  • The difference between the current RelativeTime and Time#now

See Also:



112
113
114
# File 'lib/timerizer.rb', line 112

def ago
  self.before(Time.now)
end

#averageRelativeTime

Average second-based units to month-based units.

Examples:

5.weeks.average
  => 1 month, 4 days, 13 hours, 30 minutes, 54 seconds

Returns:

  • The averaged RelativeTime

See Also:



181
182
183
184
185
186
187
188
189
190
# File 'lib/timerizer.rb', line 181

def average
  return self unless @seconds > 0

  months = (@seconds / @@average_seconds[:month])
  seconds = @seconds - months.months.unaverage.get(:seconds)
  RelativeTime.new({
    :seconds => seconds,
    :months => months + @months
  })
end

#average!Object

Destructively average second-based units to month-based units.

See Also:



194
195
196
197
198
199
# File 'lib/timerizer.rb', line 194

def average!
  averaged = self.average
  @seconds = averaged.get(:seconds)
  @months = averaged.get(:months)
  self
end

#before(time) ⇒ Time

Determines the time between RelativeTime and the given time.

Examples:

5 hours before January 1st, 2000 at noon

5.minutes.before(Time.now(2000, 1, 1, 12, 00, 00))
  => 2000-01-01 11:55:00 -0800

Parameters:

  • The initial time.

Returns:

  • The difference between the current RelativeTime and the given time

See Also:



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/timerizer.rb', line 87

def before(time)
  time = time.to_time - @seconds

  new_month = time.month - @months
  new_year = time.year
  while new_month < 1
    new_month += 12
    new_year -= 1
  end
  if(Date.valid_date?(new_year, new_month, time.day))
    new_day = time.day
  else
    new_day = Date.new(new_year, new_month).days_in_month
  end

  new_time = Time.new(
    new_year, new_month, new_day,
    time.hour, time.min, time.sec
  )
  Time.at(new_time.to_i, time.nsec/1000)
end

#from_nowTime

Return the time after the current time and the RelativeTime.

Returns:

  • The time after the current time



145
146
147
# File 'lib/timerizer.rb', line 145

def from_now
  self.after(Time.now)
end

#get(unit) ⇒ Fixnum

Return the number of base units in a RelativeTime.

Parameters:

  • The unit to return, either :seconds or :months

Returns:

  • The requested unit count

Raises:

  • Unit requested was not :seconds or :months



72
73
74
75
76
# File 'lib/timerizer.rb', line 72

def get(unit)
  return @seconds if unit == :seconds
  return @months if unit == :months
  raise ArgumentError
end

#to_sObject

Convert RelativeTime to a human-readable format.

Examples:

(14.months 49.hours).to_s
  => 2 years, 2 months, 3 days, 1 hour


249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/timerizer.rb', line 249

def to_s
  times = [] 

  @@units.each do |unit, plural|
    time = self.respond_to?(plural) ? self.send(plural) : 0
    times << [time, (time != 1) ? plural : unit] if time > 0
  end

  times.map do |time|
    time.join(' ')
  end.reverse.join(', ')
end

#unaverageRelativeTime

Average month-based units to second-based units.

Examples:

1.month.unaverage
  => 4 weeks, 2 days, 10 hours, 29 minutes, 6 seconds

Returns:

  • the unaveraged RelativeTime.

See Also:



208
209
210
211
212
# File 'lib/timerizer.rb', line 208

def unaverage
  seconds = @@average_seconds[:month] * @months
  seconds += @seconds
  RelativeTime.new({:seconds => seconds})
end

#unaverage!Object

Destructively average month-based units to second-based units.

See Also:



216
217
218
219
220
221
# File 'lib/timerizer.rb', line 216

def unaverage!
  unaveraged = self.average
  @seconds = unaverage.get(:seconds)
  @months = unaverage.get(:months)
  self
end