class TimeMath::Sequence
Sequence
represents a sequential units of time between two points. It has several options and convenience methods for creating arrays of data.
Basic usage example:
“`ruby from = Time.parse('2016-05-01 13:30') to = Time.parse('2016-05-04 18:20') seq = TimeMath.day.sequence(from…to) # => #<TimeMath::Sequence day (2016-05-01 00:00:00 +0300-2016 - 2016-05-04 00:00:00 +0300)> “`
Now, you can use it:
“`ruby seq.to_a # => [2016-05-01 00:00:00 +0300, 2016-05-02 00:00:00 +0300, 2016-05-03 00:00:00 +0300] “` – it's an “each day start between from and to”.
Depending of including/excluding of range, you will, or will not receive period that includes `to`:
“`ruby TimeMath.day.sequence(from..to).to_a # => [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] “`
Besides each period beginning, you can also request pairs of begin/end of a period, either as an array of arrays, or array of ranges:
“`ruby seq.pairs # => [[2016-05-01 00:00:00 +0300, 2016-05-02 00:00:00 +0300], [2016-05-02 00:00:00 +0300, 2016-05-03 00:00:00 +0300], [2016-05-03 00:00:00 +0300, 2016-05-04 00:00:00 +0300]] seq.ranges # => [2016-05-01 00:00:00 +0300…2016-05-02 00:00:00 +0300, 2016-05-02 00:00:00 +0300…2016-05-03 00:00:00 +0300, 2016-05-03 00:00:00 +0300…2016-05-04 00:00:00 +0300] “`
It is pretty convenient for filtering data from databases or APIs: TimeMath
creates list of filtering ranges in a blink.
Sequence
also supports any item-updating operations in the same fashion {Op} does:
“`ruby seq = TimeMath.day.sequence(from…to).advance(:hour, 5).decrease(:min, 20) # => #<TimeMath::Sequence day (2016-05-01 00:00:00 +0300 - 2016-05-03 00:00:00 +0300).advance(:hour, 5).decrease(:min, 20)> seq.to_a # => [2016-05-01 04:40:00 +0300, 2016-05-02 04:40:00 +0300, 2016-05-03 04:40:00 +0300] “`
Attributes
Public Class Methods
Creates a sequence. Typically, it is easier to do it with {Units::Base#sequence}, like this:
“`ruby TimeMath.day.sequence(from…to) “`
@param unit [Symbol] one of {TimeMath.units}; @param range [Range] range of time-y values (Time, Date, DateTime);
note that range with inclusive and exclusive and will produce different sequences.
# File lib/time_math/sequence.rb, line 66 def initialize(unit, range) @unit = Units.get(unit) @from, @to = process_range(range) @op = Op.new end
Public Instance Methods
Compares two sequences, considering their start, end, unit and operations.
@param other [Sequence] @return [Boolean]
# File lib/time_math/sequence.rb, line 86 def ==(other) # rubocop:disable Metrics/AbcSize self.class == other.class && unit == other.unit && from == other.from && to == other.to && op == other.op end
Enumerates time unit between `from` and `to`. They will have same granularity as from (e.g. if `unit` is day and from is 2016-05-01 13:30, each of return values will be next day at 13:30), unless sequence is not set to floor values.
@return [Enumerator<Time, or Date, or DateTime>]
# File lib/time_math/sequence.rb, line 194 def each return to_enum(:each) unless block_given? iter = from while iter <= to yield(op.call(iter)) iter = unit.advance(iter) end end
@private
# File lib/time_math/sequence.rb, line 73 def initialize_copy(other) @unit = other.unit @from, @to = other.from, other.to @op = other.op.dup end
# File lib/time_math/sequence.rb, line 224 def inspect ops = op.inspect_operations ops = '.' + ops unless ops.empty? "#<#{self.class} #{unit.name} (#{from} - #{to})#{ops}>" end
Creates an array of pairs (time unit start, time unit end) between from and to.
@return [Array<Array>]
# File lib/time_math/sequence.rb, line 211 def pairs seq = to_a seq.zip([*seq[1..-1], unit.advance(to)]) end
Creates an array of Ranges (time unit start…time unit end) between from and to.
@return [Array<Range>]
# File lib/time_math/sequence.rb, line 220 def ranges pairs.map { |b, e| (b...e) } end
Private Instance Methods
# File lib/time_math/sequence.rb, line 236 def process_range(range) valid_time_range?(range) or raise ArgumentError, "Range of time-y values expected, #{range} got" range_end = unit.floor(range.end) [unit.floor(range.begin), range.exclude_end? ? unit.decrease(range_end) : range_end] end
# File lib/time_math/sequence.rb, line 232 def valid_time_range?(range) range.is_a?(Range) && Util.timey?(range.begin) && Util.timey?(range.end) end