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) ⇒ 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 143 |
# 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.
153 154 155 156 157 |
# File 'lib/time_math/units/base.rb', line 153 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
294 295 296 |
# File 'lib/time_math/units/base.rb', line 294 def inspect "#<#{self.class}>" end |
#measure(from, to) ⇒ Integer
Measures distance between from
and to
in units of this class.
:nocov:
200 201 202 203 |
# File 'lib/time_math/units/base.rb', line 200 def measure(from, to) from, to = from.to_time, to.to_time unless from.class == to.class from <= to ? _measure(from, to) : -_measure(to, from) 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]
222 223 224 225 |
# File 'lib/time_math/units/base.rb', line 222 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
172 173 174 |
# File 'lib/time_math/units/base.rb', line 172 def range(tm, amount = 1) (tm...advance(tm, amount)) end |
#range_back(tm, amount = 1) ⇒ Range
189 190 191 |
# File 'lib/time_math/units/base.rb', line 189 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}
290 291 292 |
# File 'lib/time_math/units/base.rb', line 290 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 |