Class: TimeMath::Units::Base
- Inherits:
-
Object
- Object
- TimeMath::Units::Base
- Defined in:
- lib/time_math/units/base.rb
Overview
It is a main class representing most of TimeMath functionality. It (or rather its descendants) represents "unit of time" and connected calculations logic. Typical usage:
TimeMath.day.advance(tm, 5) # advances tm by 5 days
See also Op for performing multiple operations in concise & DRY manner, like this:
TimeMath().advance(:day, 5).floor(:hour).advance(:min, 20).call(tm)
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
-
#advance(tm, amount = 1) ⇒ Time, ...
Advances
tm
by given amount of unit. -
#ceil(tm, span = 1) ⇒ Time, ...
Rounds
tm
up to nearest unit (this means,TimeMath.day.ceil(tm)
will return beginning of day next aftertm
, and so on). -
#decrease(tm, amount = 1) ⇒ Time, ...
Decreases
tm
by given amount of unit. -
#floor(tm, span = 1) ⇒ Time, ...
Rounds
tm
down to nearest unit (this means,TimeMath.day.floor(tm)
will return beginning oftm
-s day, and so on). -
#initialize(name) ⇒ Base
constructor
Creates unit of time.
- #inspect ⇒ Object
-
#measure(from, to) ⇒ Integer
Measures distance between
from
andto
in units of this class. -
#measure_rem(from, to) ⇒ Array<Integer, Time or DateTime>
Like #measure but also returns "remainder": the time where it would be exactly returned amount of units between
from
andto
:. -
#next(tm, span = 1) ⇒ Time, ...
Like #ceil, but always return value greater than
tm
(e.g. iftm
is exactly midnight, thenTimeMath.day.next(tm)
will return next midnight). -
#prev(tm, span = 1) ⇒ Time, ...
Like #floor, but always return value lower than
tm
(e.g. iftm
is exactly midnight, thenTimeMath.day.prev(tm)
will return previous midnight). -
#range(tm, amount = 1) ⇒ Range
Creates range from
tm
totm
increased by amount of units. -
#range_back(tm, amount = 1) ⇒ Range
Creates range from
tm
decreased by amount of units totm
. -
#resample(array_or_hash, symbol = nil, &block) ⇒ Object
Converts input timestamps list to regular list of timestamps over current unit.
-
#round(tm, span = 1) ⇒ Time, ...
Rounds
tm
up or down to nearest unit (this means,TimeMath.day.round(tm)
will return beginning oftm
day iftm
is before noon, and day next aftertm
if it is after, and so on). -
#round?(tm, span = 1) ⇒ Boolean
Checks if
tm
is exactly rounded to unit. -
#sequence(range, options = {}) ⇒ Sequence
Creates Sequence instance for producing all time units between from and too.
Constructor Details
#initialize(name) ⇒ Base
Creates unit of time. Typically you don't need it, as it is
easier to do TimeMath.day
or TimeMath[:day]
to obtain it.
23 24 25 |
# File 'lib/time_math/units/base.rb', line 23 def initialize(name) @name = name end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
27 28 29 |
# File 'lib/time_math/units/base.rb', line 27 def name @name end |
Instance Method Details
#advance(tm, amount = 1) ⇒ Time, ...
Advances tm
by given amount of unit.
139 140 141 142 |
# File 'lib/time_math/units/base.rb', line 139 def advance(tm, amount = 1) return decrease(tm, -amount) if amount < 0 _advance(tm, amount) end |
#ceil(tm, span = 1) ⇒ Time, ...
Rounds tm
up to nearest unit (this means, TimeMath.day.ceil(tm)
will return beginning of day next after tm
, and so on).
An optional second argument allows to ceil to arbitrary
amount of units (see #floor for more detailed explanation).
66 67 68 69 70 |
# File 'lib/time_math/units/base.rb', line 66 def ceil(tm, span = 1) f = floor(tm, span) f == tm ? f : advance(f, span) end |
#decrease(tm, amount = 1) ⇒ Time, ...
Decreases tm
by given amount of unit.
152 153 154 155 |
# File 'lib/time_math/units/base.rb', line 152 def decrease(tm, amount = 1) return advance(tm, -amount) if amount < 0 _decrease(tm, amount) end |
#floor(tm, span = 1) ⇒ Time, ...
Rounds tm
down to nearest unit (this means, TimeMath.day.floor(tm)
will return beginning of tm
-s day, and so on).
An optional second argument allows you to floor to arbitrary number of units, like to "each 3-hour" mark:
TimeMath.hour.floor(Time.parse('14:00'), 3)
# => 2016-06-23 12:00:00 +0300
# works well with float/rational spans
TimeMath.hour.floor(Time.parse('14:15'), 1/2r)
# => 2016-06-23 14:00:00 +0300
TimeMath.hour.floor(Time.parse('14:45'), 1/2r)
# => 2016-06-23 14:30:00 +0300
51 52 53 54 |
# File 'lib/time_math/units/base.rb', line 51 def floor(tm, span = 1) int_floor = advance(floor_1(tm), (tm.send(name) / span.to_f).floor * span - tm.send(name)) float_fix(tm, int_floor, span % 1) end |
#inspect ⇒ Object
299 300 301 |
# File 'lib/time_math/units/base.rb', line 299 def inspect "#<#{self.class}>" end |
#measure(from, to) ⇒ Integer
Measures distance between from
and to
in units of this class.
:nocov:
198 199 200 201 |
# File 'lib/time_math/units/base.rb', line 198 def measure(from, to) # rubocop:disable Lint/UnusedMethodArgument raise NotImplementedError, '#measure should be implemented in subclasses' end |
#measure_rem(from, to) ⇒ Array<Integer, Time or DateTime>
Like #measure but also returns "remainder": the time where
it would be exactly returned amount of units between from
and to
:
TimeMath.day.measure(Time.parse('2016-05-01 16:20'), Time.parse('2016-05-28 15:00'))
# => 26
TimeMath.day.measure_rem(Time.parse('2016-05-01 16:20'), Time.parse('2016-05-28 15:00'))
# => [26, 2016-05-27 16:20:00 +0300]
220 221 222 223 |
# File 'lib/time_math/units/base.rb', line 220 def measure_rem(from, to) m = measure(from, to) [m, advance(from, m)] end |
#next(tm, span = 1) ⇒ Time, ...
116 117 118 119 |
# File 'lib/time_math/units/base.rb', line 116 def next(tm, span = 1) c = ceil(tm, span) c == tm ? advance(c, span) : c end |
#prev(tm, span = 1) ⇒ Time, ...
100 101 102 103 |
# File 'lib/time_math/units/base.rb', line 100 def prev(tm, span = 1) f = floor(tm, span) f == tm ? decrease(f, span) : f end |
#range(tm, amount = 1) ⇒ Range
Creates range from tm
to tm
increased by amount of units.
tm = Time.parse('2016-05-28 16:30')
TimeMath.day.range(tm, 5)
# => 2016-05-28 16:30:00 +0300...2016-06-02 16:30:00 +0300
170 171 172 |
# File 'lib/time_math/units/base.rb', line 170 def range(tm, amount = 1) (tm...advance(tm, amount)) end |
#range_back(tm, amount = 1) ⇒ Range
Creates range from tm
decreased by amount of units to tm
.
tm = Time.parse('2016-05-28 16:30')
TimeMath.day.range_back(tm, 5)
# => 2016-05-23 16:30:00 +0300...2016-05-28 16:30:00 +0300
187 188 189 |
# File 'lib/time_math/units/base.rb', line 187 def range_back(tm, amount = 1) (decrease(tm, amount)...tm) end |
#resample(array_or_hash, symbol = nil, &block) ⇒ Object
Converts input timestamps list to regular list of timestamps over current unit.
Like this:
times = [Time.parse('2016-05-01'), Time.parse('2016-05-03'), Time.parse('2016-05-08')]
TimeMath.day.resample(times)
# => => [2016-05-01 00:00:00 +0300, 2016-05-02 00:00:00 +0300, 2016-05-03 00:00:00 +0300, 2016-05-04 00:00:00 +0300, 2016-05-05 00:00:00 +0300, 2016-05-06 00:00:00 +0300, 2016-05-07 00:00:00 +0300, 2016-05-08 00:00:00 +0300]
The best way about resampling it also works for hashes with time keys. Like this:
h = {Date.parse('Wed, 01 Jun 2016')=>1, Date.parse('Tue, 07 Jun 2016')=>3, Date.parse('Thu, 09 Jun 2016')=>1}
# => {#<Date: 2016-06-01>=>1, #<Date: 2016-06-07>=>3, #<Date: 2016-06-09>=>1}
pp TimeMath.day.resample(h)
# {#<Date: 2016-06-01>=>[1],
# #<Date: 2016-06-02>=>[],
# #<Date: 2016-06-03>=>[],
# #<Date: 2016-06-04>=>[],
# #<Date: 2016-06-05>=>[],
# #<Date: 2016-06-06>=>[],
# #<Date: 2016-06-07>=>[3],
# #<Date: 2016-06-08>=>[],
# #<Date: 2016-06-09>=>[1]}
# The default resample just groups all related values in arrays
# You can pass block or symbol, to have the values you need:
pp TimeMath.day.resample(h,&:first)
# {#<Date: 2016-06-01>=>1,
# #<Date: 2016-06-02>=>nil,
# #<Date: 2016-06-03>=>nil,
# #<Date: 2016-06-04>=>nil,
# #<Date: 2016-06-05>=>nil,
# #<Date: 2016-06-06>=>nil,
# #<Date: 2016-06-07>=>3,
# #<Date: 2016-06-08>=>nil,
# #<Date: 2016-06-09>=>1}
295 296 297 |
# File 'lib/time_math/units/base.rb', line 295 def resample(array_or_hash, symbol = nil, &block) Resampler.call(name, array_or_hash, symbol, &block) end |
#round(tm, span = 1) ⇒ Time, ...
Rounds tm
up or down to nearest unit (this means, TimeMath.day.round(tm)
will return beginning of tm
day if tm
is before noon, and
day next after tm
if it is after, and so on).
An optional second argument allows to round to arbitrary
amount of units (see #floor for more detailed explanation).
83 84 85 86 87 |
# File 'lib/time_math/units/base.rb', line 83 def round(tm, span = 1) f, c = floor(tm, span), ceil(tm, span) (tm - f).abs < (tm - c).abs ? f : c end |
#round?(tm, span = 1) ⇒ Boolean
Checks if tm
is exactly rounded to unit.
127 128 129 |
# File 'lib/time_math/units/base.rb', line 127 def round?(tm, span = 1) floor(tm, span) == tm end |
#sequence(range, options = {}) ⇒ Sequence
238 239 240 |
# File 'lib/time_math/units/base.rb', line 238 def sequence(range, = {}) TimeMath::Sequence.new(name, range, ) end |