time_math2 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35d2a3523dac20994a38d19862500ce1eae98854
4
- data.tar.gz: 82b7664f95fb1879a4911886cd257c41282f9327
3
+ metadata.gz: f2e42b79bda1365a78f8c74b1b2d41af59f4c5c0
4
+ data.tar.gz: b2dcd6572c88be32bfbff1f9a3f15cda929551b9
5
5
  SHA512:
6
- metadata.gz: 99dc9701481d961e93e9d803e4b943ce390bd03e55e8b23a779456094051d1fce129c5bb2a3900cf7f1d8c64f20be684839e2f1f80234c6a6c79912e78eb7954
7
- data.tar.gz: 22dcc1315f78bd1d323ae9faed9b5e8ef6b39267ddd65b7c3be40cfe33b4f4ec217c79eecfc89c49c14b37ce60c92497ac49d5b5fa7b5d69a6afbd947687da8b
6
+ metadata.gz: 987ddc51e856db1f2f9baa77d68beb189b7a2f6193a82d5839cf11b3e4b9f989d8fe676d4539087a60bbda75e4779f90a7c8d0b706a5d2cef1c85123c8fd9f6b
7
+ data.tar.gz: 0d5a36c6e120c1244ae40a768b13f499455e855890a46013674464e9d6939b7797ef14aed268a05491e29e98be4249467bb112d5b29381611606be7346f4632e
@@ -1,5 +1,10 @@
1
1
  # TimeMath Changelog
2
2
 
3
+ # 0.1.0 (2017-07-30)
4
+
5
+ * Update sequences logic to be, well... More logical (Thanks @kenn again for meaningful discussion!);
6
+ * Various code cleanups.
7
+
3
8
  # 0.0.8 (2017-06-02)
4
9
 
5
10
  * Fix `Units::Base#measure` to correctly measure negative distances (e.g. from > to, thanks @kenn for
@@ -2,14 +2,13 @@ module TimeMath
2
2
  # @private
3
3
  class Resampler
4
4
  class << self
5
- def call(name, array_or_hash, symbol = nil, &block)
6
- if array_or_hash.is_a?(Array) && array_or_hash.all?(&Util.method(:timey?))
7
- ArrayResampler.new(name, array_or_hash).call
8
- elsif array_or_hash.is_a?(Hash) && array_or_hash.keys.all?(&Util.method(:timey?))
9
- HashResampler.new(name, array_or_hash).call(symbol, &block)
10
- else
11
- raise ArgumentError, "Array of timestamps or hash with timestamp keys, #{array_or_hash} got"
12
- end
5
+ def call(unit, array_or_hash, symbol = nil, &block)
6
+ resampler =
7
+ ArrayResampler.try(unit, array_or_hash) ||
8
+ HashResampler.try(unit, array_or_hash) or
9
+ raise ArgumentError, "Expected array of timestamps or hash with timestamp keys, #{array_or_hash} got"
10
+
11
+ resampler.call(symbol, &block)
13
12
  end
14
13
  end
15
14
 
@@ -17,29 +16,30 @@ module TimeMath
17
16
  @unit = Units.get(unit)
18
17
  end
19
18
 
20
- private
21
-
22
- def sequence
23
- @sequence ||= @unit.sequence(from...to, expand: true)
19
+ def call
20
+ raise NotImplementedError
24
21
  end
25
22
 
26
- def from
27
- timestamps.min
28
- end
23
+ private
29
24
 
30
- def to
31
- @unit.next(timestamps.max)
25
+ def sequence
26
+ @sequence ||= @unit.sequence(timestamps.min..timestamps.max)
32
27
  end
33
28
  end
34
29
 
35
30
  # @private
36
31
  class ArrayResampler < Resampler
32
+ def self.try(unit, array)
33
+ return nil unless array.is_a?(Array) && array.all?(&Util.method(:timey?))
34
+ new(unit, array)
35
+ end
36
+
37
37
  def initialize(unit, array)
38
38
  super(unit)
39
39
  @array = array
40
40
  end
41
41
 
42
- def call
42
+ def call(*)
43
43
  sequence.to_a
44
44
  end
45
45
 
@@ -52,6 +52,11 @@ module TimeMath
52
52
 
53
53
  # @private
54
54
  class HashResampler < Resampler
55
+ def self.try(unit, hash)
56
+ return nil unless hash.is_a?(Hash) && hash.keys.all?(&Util.method(:timey?))
57
+ new(unit, hash)
58
+ end
59
+
55
60
  def initialize(unit, hash)
56
61
  super(unit)
57
62
  @hash = hash
@@ -9,63 +9,49 @@ module TimeMath
9
9
  # from = Time.parse('2016-05-01 13:30')
10
10
  # to = Time.parse('2016-05-04 18:20')
11
11
  # seq = TimeMath.day.sequence(from...to)
12
- # # => #<TimeMath::Sequence(2016-05-01 13:30:00 +0300...2016-05-04 18:20:00 +0300)>
12
+ # # => #<TimeMath::Sequence day (2016-05-01 00:00:00 +0300-2016 - 2016-05-04 00:00:00 +0300)>
13
13
  # ```
14
14
  #
15
15
  # Now, you can use it:
16
16
  #
17
17
  # ```ruby
18
18
  # seq.to_a
19
- # # => [2016-05-01 13:30:00 +0300, 2016-05-02 13:30:00 +0300, 2016-05-03 13:30:00 +0300, 2016-05-04 13:30:00 +0300]
19
+ # # => [2016-05-01 00:00:00 +0300, 2016-05-02 00:00:00 +0300, 2016-05-03 00:00:00 +0300]
20
20
  # ```
21
- # -- it's an "each day start between from and to". As you can see,
22
- # the period start is the same as in `from`.
21
+ # -- it's an "each day start between from and to".
23
22
  #
24
- # You can expand from and to to nearest round unit by {#expand} method
25
- # or `:expand` option:
23
+ # Depending of including/excluding of range, you will, or will not receive period that includes `to`:
26
24
  #
27
25
  # ```ruby
28
- # seq.expand.to_a
26
+ # TimeMath.day.sequence(from..to).to_a
29
27
  # # => [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]
30
- # # or:
31
- # seq = TimeMath.day.sequence(from...to, expand: true)
32
- # # => #<TimeMath::Sequence(2016-05-01 00:00:00 +0300...2016-05-05 00:00:00 +0300)>
33
- # seq.to_a
34
- # # => [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]
35
- # # ^ note that `to` is excluded.
36
- # # You can include it by creating sequence from including-end range:
37
- # seq = TimeMath.day.sequence(from..to, expand: true)
38
- # # => #<TimeMath::Sequence(:day, 2016-05-01 00:00:00 +0300..2016-05-05 00:00:00 +0300)>
39
- # seq.to_a
40
- # # => [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]
41
28
  # ```
42
29
  #
43
30
  # Besides each period beginning, you can also request pairs of begin/end
44
31
  # of a period, either as an array of arrays, or array of ranges:
45
32
  #
46
33
  # ```ruby
47
- # seq = TimeMath.day.sequence(from...to)
48
34
  # seq.pairs
49
- # # => [[2016-05-01 13:30:00 +0300, 2016-05-02 13:30:00 +0300], [2016-05-02 13:30:00 +0300, 2016-05-03 13:30:00 +0300], [2016-05-03 13:30:00 +0300, 2016-05-04 13:30:00 +0300], [2016-05-04 13:30:00 +0300, 2016-05-04 18:20:00 +0300]]
35
+ # # => [[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]]
50
36
  # seq.ranges
51
- # # => [2016-05-01 13:30:00 +0300...2016-05-02 13:30:00 +0300, 2016-05-02 13:30:00 +0300...2016-05-03 13:30:00 +0300, 2016-05-03 13:30:00 +0300...2016-05-04 13:30:00 +0300, 2016-05-04 13:30:00 +0300...2016-05-04 18:20:00 +0300]
37
+ # # => [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]
52
38
  # ```
53
39
  #
54
- # It is pretty convenient for filtering data from databases or APIs,
55
- # TimeMath creates list of filtering ranges in a blink.
40
+ # It is pretty convenient for filtering data from databases or APIs: TimeMath creates list of
41
+ # filtering ranges in a blink.
56
42
  #
57
43
  # Sequence also supports any item-updating operations in the same fashion
58
44
  # {Op} does:
59
45
  #
60
46
  # ```ruby
61
- # seq = TimeMath.day.sequence(from...to, expand: true).advance(:hour, 5).decrease(:min, 20)
62
- # # => #<TimeMath::Sequence(:day, 2016-05-01 00:00:00 +0300...2016-05-05 00:00:00 +0300).advance(:hour, 5).decrease(:min, 20)>
47
+ # seq = TimeMath.day.sequence(from...to).advance(:hour, 5).decrease(:min, 20)
48
+ # # => #<TimeMath::Sequence day (2016-05-01 00:00:00 +0300 - 2016-05-03 00:00:00 +0300).advance(:hour, 5).decrease(:min, 20)>
63
49
  # seq.to_a
64
- # # => [2016-05-01 04:40:00 +0300, 2016-05-02 04:40:00 +0300, 2016-05-03 04:40:00 +0300, 2016-05-04 04:40:00 +0300]
50
+ # # => [2016-05-01 04:40:00 +0300, 2016-05-02 04:40:00 +0300, 2016-05-03 04:40:00 +0300]
65
51
  # ```
66
52
  #
67
53
  class Sequence
68
- # Creates a sequence. Typically, it is easier to to it with {Units::Base#sequence},
54
+ # Creates a sequence. Typically, it is easier to do it with {Units::Base#sequence},
69
55
  # like this:
70
56
  #
71
57
  # ```ruby
@@ -76,23 +62,17 @@ module TimeMath
76
62
  # @param range [Range] range of time-y values (Time, Date, DateTime);
77
63
  # note that range with inclusive and exclusive and will produce
78
64
  # different sequences.
79
- # @param options [Hash]
80
- # @option options [Boolean] :expand round sequence ends on creation
81
- # (`from` is floored and `to` is ceiled);
82
65
  #
83
- def initialize(unit, range, options = {})
66
+ def initialize(unit, range)
84
67
  @unit = Units.get(unit)
85
- @from, @to, @exclude_end = process_range(range)
86
- @options = options.dup
87
-
88
- expand! if options[:expand]
68
+ @from, @to = process_range(range)
89
69
  @op = Op.new
90
70
  end
91
71
 
92
72
  # @private
93
73
  def initialize_copy(other)
94
74
  @unit = other.unit
95
- @from, @to, @exclude_end = other.from, other.to, other.exclude_end?
75
+ @from, @to = other.from, other.to
96
76
  @op = other.op.dup
97
77
  end
98
78
 
@@ -106,33 +86,9 @@ module TimeMath
106
86
  def ==(other) # rubocop:disable Metrics/AbcSize
107
87
  self.class == other.class && unit == other.unit &&
108
88
  from == other.from && to == other.to &&
109
- exclude_end? == other.exclude_end? &&
110
89
  op == other.op
111
90
  end
112
91
 
113
- # Whether sequence was created from exclude-end range (and, therefore,
114
- # will exclude `to` when converted to array).
115
- def exclude_end?
116
- @exclude_end
117
- end
118
-
119
- # Expand sequence ends to nearest round unit.
120
- #
121
- # @return [self]
122
- def expand!
123
- @from = unit.floor(from)
124
- @to = unit.ceil(to)
125
-
126
- self
127
- end
128
-
129
- # Creates new sequence with ends rounded to nearest unit.
130
- #
131
- # @return [Sequence]
132
- def expand
133
- dup.expand!
134
- end
135
-
136
92
  # @method floor!(unit, span = 1)
137
93
  # Adds {Units::Base#floor} to list of operations to apply to sequence items.
138
94
  #
@@ -239,12 +195,11 @@ module TimeMath
239
195
  return to_enum(:each) unless block_given?
240
196
 
241
197
  iter = from
242
- while iter < to
198
+ while iter <= to
243
199
  yield(op.call(iter))
244
200
 
245
201
  iter = unit.advance(iter)
246
202
  end
247
- yield(op.call(to)) unless exclude_end?
248
203
  end
249
204
 
250
205
  include Enumerable
@@ -255,7 +210,7 @@ module TimeMath
255
210
  # @return [Array<Array>]
256
211
  def pairs
257
212
  seq = to_a
258
- seq.zip(seq[1..-1] + [to])
213
+ seq.zip([*seq[1..-1], unit.advance(to)])
259
214
  end
260
215
 
261
216
  # Creates an array of Ranges (time unit start...time unit end) between
@@ -269,16 +224,21 @@ module TimeMath
269
224
  def inspect
270
225
  ops = op.inspect_operations
271
226
  ops = '.' + ops unless ops.empty?
272
- "#<#{self.class}(#{unit.name.inspect}, #{from}#{exclude_end? ? '...' : '..'}#{to})#{ops}>"
227
+ "#<#{self.class} #{unit.name} (#{from} - #{to})#{ops}>"
273
228
  end
274
229
 
275
230
  private
276
231
 
232
+ def valid_time_range?(range)
233
+ range.is_a?(Range) && Util.timey?(range.begin) && Util.timey?(range.end)
234
+ end
235
+
277
236
  def process_range(range)
278
- range.is_a?(Range) && Util.timey?(range.begin) && Util.timey?(range.end) or
237
+ valid_time_range?(range) or
279
238
  raise ArgumentError, "Range of time-y values expected, #{range} got"
280
239
 
281
- [range.begin, range.end, range.exclude_end?]
240
+ range_end = unit.floor(range.end)
241
+ [unit.floor(range.begin), range.exclude_end? ? unit.decrease(range_end) : range_end]
282
242
  end
283
243
  end
284
244
  end
@@ -223,20 +223,13 @@ module TimeMath
223
223
  end
224
224
 
225
225
  # Creates {Sequence} instance for producing all time units between
226
- # from and too. See {Sequence} class documentation for available
227
- # options and functionality.
226
+ # from and too. See {Sequence} class documentation for detailed functionality description.
228
227
  #
229
- # @param from [Time,Date,DateTime] start of sequence;
230
- # @param to [Time,Date,DateTime] upper limit of sequence;
231
- # @param options [Hash]
232
- # @option options [Boolean] :expand round sequence ends on creation
233
- # (from is floored and to is ceiled);
234
- # @option options [Boolean] :floor sequence will be rounding'ing all
235
- # the intermediate values.
228
+ # @param range [Range<Time,Date,DateTime>] start and end of sequence.
236
229
  #
237
230
  # @return [Sequence]
238
- def sequence(range, options = {})
239
- TimeMath::Sequence.new(name, range, options)
231
+ def sequence(range)
232
+ TimeMath::Sequence.new(name, range)
240
233
  end
241
234
 
242
235
  # Converts input timestamps list to regular list of timestamps
@@ -1,4 +1,4 @@
1
1
  module TimeMath
2
2
  # @private
3
- VERSION = '0.0.8'.freeze
3
+ VERSION = '0.1.0'.freeze
4
4
  end
@@ -16,6 +16,8 @@ Gem::Specification.new do |s|
16
16
  EOF
17
17
  s.licenses = ['MIT']
18
18
 
19
+ s.required_ruby_version = '>= 2.1.0'
20
+
19
21
  s.files = `git ls-files`.split($RS).reject do |file|
20
22
  file =~ /^(?:
21
23
  spec\/.*
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_math2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-02 00:00:00.000000000 Z
11
+ date: 2017-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -165,7 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
165
165
  requirements:
166
166
  - - ">="
167
167
  - !ruby/object:Gem::Version
168
- version: '0'
168
+ version: 2.1.0
169
169
  required_rubygems_version: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - ">="