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 +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/time_math/resamplers.rb +23 -18
- data/lib/time_math/sequence.rb +26 -66
- data/lib/time_math/units/base.rb +4 -11
- data/lib/time_math/version.rb +1 -1
- data/time_math2.gemspec +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2e42b79bda1365a78f8c74b1b2d41af59f4c5c0
|
4
|
+
data.tar.gz: b2dcd6572c88be32bfbff1f9a3f15cda929551b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 987ddc51e856db1f2f9baa77d68beb189b7a2f6193a82d5839cf11b3e4b9f989d8fe676d4539087a60bbda75e4779f90a7c8d0b706a5d2cef1c85123c8fd9f6b
|
7
|
+
data.tar.gz: 0d5a36c6e120c1244ae40a768b13f499455e855890a46013674464e9d6939b7797ef14aed268a05491e29e98be4249467bb112d5b29381611606be7346f4632e
|
data/CHANGELOG.md
CHANGED
@@ -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
|
data/lib/time_math/resamplers.rb
CHANGED
@@ -2,14 +2,13 @@ module TimeMath
|
|
2
2
|
# @private
|
3
3
|
class Resampler
|
4
4
|
class << self
|
5
|
-
def call(
|
6
|
-
|
7
|
-
ArrayResampler.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
21
|
-
|
22
|
-
def sequence
|
23
|
-
@sequence ||= @unit.sequence(from...to, expand: true)
|
19
|
+
def call
|
20
|
+
raise NotImplementedError
|
24
21
|
end
|
25
22
|
|
26
|
-
|
27
|
-
timestamps.min
|
28
|
-
end
|
23
|
+
private
|
29
24
|
|
30
|
-
def
|
31
|
-
@unit.
|
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
|
data/lib/time_math/sequence.rb
CHANGED
@@ -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
|
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
|
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".
|
22
|
-
# the period start is the same as in `from`.
|
21
|
+
# -- it's an "each day start between from and to".
|
23
22
|
#
|
24
|
-
#
|
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
|
-
#
|
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
|
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
|
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
|
-
#
|
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
|
62
|
-
# # => #<TimeMath::Sequence
|
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
|
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
|
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
|
66
|
+
def initialize(unit, range)
|
84
67
|
@unit = Units.get(unit)
|
85
|
-
@from, @to
|
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
|
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
|
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]
|
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}
|
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
|
-
|
237
|
+
valid_time_range?(range) or
|
279
238
|
raise ArgumentError, "Range of time-y values expected, #{range} got"
|
280
239
|
|
281
|
-
|
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
|
data/lib/time_math/units/base.rb
CHANGED
@@ -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
|
227
|
-
# options and functionality.
|
226
|
+
# from and too. See {Sequence} class documentation for detailed functionality description.
|
228
227
|
#
|
229
|
-
# @param
|
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
|
239
|
-
TimeMath::Sequence.new(name, range
|
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
|
data/lib/time_math/version.rb
CHANGED
data/time_math2.gemspec
CHANGED
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
|
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-
|
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:
|
168
|
+
version: 2.1.0
|
169
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
171
|
- - ">="
|