time_math2 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
- - ">="
|