3scale_time_range 0.0.6 → 0.3.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/README.md +15 -0
- data/lib/3scale_time_range/granulate.rb +33 -31
- data/lib/3scale_time_range/version.rb +1 -1
- data/lib/3scale_time_range.rb +2 -4
- data/test/granulate_test.rb +89 -89
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f48ca9ad688668fe899b7be2cec2a53294890ace
|
4
|
+
data.tar.gz: 349ebce201722a0c4de5a298ef38d2a27effd07f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b463ef4d67758bc596de440019620ba8d6eeaa0bb36d74a9451e03f1d215c7b6c339b6d1303b8699cc85673ec8b65ed745f0d4e7359df718ba4339cfedb787a6
|
7
|
+
data.tar.gz: 868c4fdd292f83014593d3550bbaff2b0d4eef14e6236251385eefaadae5d885dfffc0e78e4ac27205997837b80134d53bbb131edb4db4dd54875e675668963b
|
data/README.md
CHANGED
@@ -27,3 +27,18 @@ Enumerate by custom period
|
|
27
27
|
Supports all Enumerable interface: find, select, reject, inject, etc.
|
28
28
|
|
29
29
|
|
30
|
+
Version compatibility
|
31
|
+
--------
|
32
|
+
0.3.0: Public repository along with the very first RubyGems gem
|
33
|
+
|
34
|
+
0.2.0: The Granulate class has been converted to a class method that returns a
|
35
|
+
hash. Granulate was not easy to use because it returned an instance of
|
36
|
+
'Granulate'. This prevented clients from iterating through the result.
|
37
|
+
|
38
|
+
0.1.0: breaks compatibility with previous versions because it adds hours to the
|
39
|
+
Granulate class. This means that in previous versions Granulate.rest contained
|
40
|
+
time ranges that cannot be separated into days when granulating, but now it
|
41
|
+
just contains ranges that cannot be separated into hours.
|
42
|
+
|
43
|
+
|
44
|
+
|
@@ -1,55 +1,58 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Granulate
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
module ClassMethods
|
7
|
+
GRANULARITIES = [:year, :month, :day, :hour]
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def granulate(range)
|
10
|
+
result = { rest: [] }
|
11
|
+
GRANULARITIES.each do |granularity|
|
12
|
+
result[(granularity.to_s + 's').to_sym] = []
|
13
|
+
end
|
14
|
+
time_range = TimeRange.new(range.begin, range.end, range.exclude_end?)
|
15
|
+
extract(time_range, GRANULARITIES.first, result)
|
16
|
+
result
|
13
17
|
end
|
14
18
|
|
15
19
|
private
|
16
20
|
|
17
|
-
def extract(range, cycle)
|
21
|
+
def extract(range, cycle, result)
|
18
22
|
if cycle.nil?
|
19
|
-
rest << range unless empty_range?(range)
|
23
|
+
result[:rest] << range unless empty_range?(range)
|
20
24
|
return
|
21
25
|
end
|
22
26
|
|
23
27
|
cycle_start, cycle_end = extract_boundaries(range, cycle)
|
24
28
|
if cycle_start && cycle_end
|
25
|
-
|
29
|
+
result[(cycle.to_s + 's').to_sym] << TimeRange.new(cycle_start, cycle_end)
|
26
30
|
|
27
31
|
if range.begin < cycle_start
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
)
|
32
|
+
# Getting the last hour is enough because is the smallest resolution
|
33
|
+
# that we support. If we supported minutes, we would need to get the
|
34
|
+
# last minute non included.
|
35
|
+
last_hour_not_treated = (cycle_start - 1.hour).end_of_hour
|
36
|
+
extract(TimeRange.new(range.begin, last_hour_not_treated, false),
|
37
|
+
next_cycle(cycle),
|
38
|
+
result)
|
32
39
|
end
|
40
|
+
|
33
41
|
if range.end > cycle_end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
next_cycle(cycle)
|
39
|
-
)
|
42
|
+
first_hour_not_treated = (cycle_end + 1.hour).beginning_of_hour
|
43
|
+
extract(TimeRange.new(first_hour_not_treated, range.end, range.exclude_end?),
|
44
|
+
next_cycle(cycle),
|
45
|
+
result)
|
40
46
|
end
|
41
47
|
else
|
42
|
-
extract(range, next_cycle(cycle))
|
48
|
+
extract(range, next_cycle(cycle), result)
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
52
|
def next_cycle(current_cycle)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
when :day then nil
|
51
|
-
else raise "Unknown cycle: #{current_cycle.inspect}"
|
52
|
-
end
|
53
|
+
current_cycle_index = GRANULARITIES.find_index(current_cycle)
|
54
|
+
raise "Unknown cycle: #{current_cycle.inspect}" unless current_cycle_index
|
55
|
+
GRANULARITIES[current_cycle_index + 1]
|
53
56
|
end
|
54
57
|
|
55
58
|
def extract_boundaries(range, cycle)
|
@@ -80,6 +83,5 @@ class TimeRange
|
|
80
83
|
def empty_range?(range)
|
81
84
|
(range.begin.to_i == range.end.to_i) && range.exclude_end?
|
82
85
|
end
|
83
|
-
|
84
86
|
end
|
85
87
|
end
|
data/lib/3scale_time_range.rb
CHANGED
@@ -4,6 +4,8 @@ require '3scale_time_range/granulate'
|
|
4
4
|
|
5
5
|
class TimeRange < Range
|
6
6
|
|
7
|
+
include Granulate
|
8
|
+
|
7
9
|
def initialize(start_time, end_time, exclusive = false)
|
8
10
|
raise ArgumentError, 'start and end must act like Time' unless start_time.acts_like?(:time) && end_time.acts_like?(:time)
|
9
11
|
|
@@ -114,10 +116,6 @@ class TimeRange < Range
|
|
114
116
|
"#{self.class.name}(#{super})"
|
115
117
|
end
|
116
118
|
|
117
|
-
def granulate
|
118
|
-
@granulate ||= Granulate.new(self)
|
119
|
-
end
|
120
|
-
|
121
119
|
class SimpleEnumerator
|
122
120
|
include Enumerable
|
123
121
|
|
data/test/granulate_test.rb
CHANGED
@@ -4,133 +4,133 @@ require_relative '../lib/3scale_time_range'
|
|
4
4
|
class GranulateTest < Minitest::Test
|
5
5
|
|
6
6
|
def setup
|
7
|
-
|
8
|
-
|
9
|
-
).granulate
|
7
|
+
range = DateTime.parse('2012-10-09 07:23')..DateTime.parse('2014-02-05 13:45')
|
8
|
+
@granulated_range = TimeRange.granulate(range)
|
10
9
|
end
|
11
10
|
|
12
11
|
def test_granulates_by_year
|
13
|
-
assert_equal @
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
]
|
12
|
+
assert_equal @granulated_range[:years],
|
13
|
+
[TimeRange.new(
|
14
|
+
DateTime.parse('2013-01-01').beginning_of_year,
|
15
|
+
DateTime.parse('2013-12-31').end_of_year)]
|
18
16
|
end
|
19
17
|
|
20
18
|
def test_granulates_by_month
|
21
|
-
assert_equal @
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
DateTime.parse("2014-01-31").end_of_month)
|
29
|
-
]
|
19
|
+
assert_equal @granulated_range[:months],
|
20
|
+
[TimeRange.new(
|
21
|
+
DateTime.parse('2012-11-01').beginning_of_month,
|
22
|
+
DateTime.parse('2012-12-31').end_of_month),
|
23
|
+
TimeRange.new(
|
24
|
+
DateTime.parse('2014-01-01').beginning_of_month,
|
25
|
+
DateTime.parse('2014-01-31').end_of_month)]
|
30
26
|
end
|
31
27
|
|
28
|
+
|
32
29
|
def test_granulates_by_day
|
33
|
-
assert_equal @
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
DateTime.parse("2014-02-04").end_of_day)
|
41
|
-
]
|
30
|
+
assert_equal @granulated_range[:days],
|
31
|
+
[TimeRange.new(
|
32
|
+
DateTime.parse('2012-10-10').beginning_of_day,
|
33
|
+
DateTime.parse('2012-10-31').end_of_day),
|
34
|
+
TimeRange.new(
|
35
|
+
DateTime.parse('2014-02-01').beginning_of_day,
|
36
|
+
DateTime.parse('2014-02-04').end_of_day)]
|
42
37
|
end
|
43
38
|
|
44
|
-
def
|
45
|
-
assert_equal @
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
DateTime.parse("2014-02-05 13:45"))
|
53
|
-
]
|
39
|
+
def test_granulates_by_hour
|
40
|
+
assert_equal @granulated_range[:hours],
|
41
|
+
[TimeRange.new(
|
42
|
+
DateTime.parse('2012-10-09 08:00').beginning_of_hour,
|
43
|
+
DateTime.parse('2012-10-09 23:00').end_of_hour),
|
44
|
+
TimeRange.new(
|
45
|
+
DateTime.parse('2014-02-05 00:00').beginning_of_hour,
|
46
|
+
DateTime.parse('2014-02-05 12:00').end_of_hour)]
|
54
47
|
end
|
55
48
|
|
56
|
-
def
|
57
|
-
@
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
DateTime.parse("2012-10-09 13:45"))
|
65
|
-
]
|
49
|
+
def test_exposes_information_on_not_granulated_ranges
|
50
|
+
assert_equal @granulated_range[:rest],
|
51
|
+
[TimeRange.new(
|
52
|
+
DateTime.parse('2012-10-09 07:23'),
|
53
|
+
DateTime.parse('2012-10-09 07:00').end_of_hour),
|
54
|
+
TimeRange.new(
|
55
|
+
DateTime.parse('2014-02-05 13:45').beginning_of_hour,
|
56
|
+
DateTime.parse('2014-02-05 13:45'))]
|
66
57
|
end
|
67
58
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
)
|
59
|
+
def test_range_that_cannot_be_granulated
|
60
|
+
granulated_range = TimeRange.granulate(
|
61
|
+
DateTime.parse('2012-10-09 07:23')..DateTime.parse('2012-10-09 07:45'))
|
72
62
|
|
73
|
-
assert_equal
|
63
|
+
assert_equal granulated_range[:rest],
|
64
|
+
[TimeRange.new(
|
65
|
+
DateTime.parse('2012-10-09 07:23'),
|
66
|
+
DateTime.parse('2012-10-09 07:45'))]
|
74
67
|
end
|
75
68
|
|
76
69
|
def test_properly_parses_open_ended_ranges_1
|
77
|
-
|
78
|
-
|
70
|
+
granulated_range = TimeRange.granulate(
|
71
|
+
DateTime.parse('2011-01-01')...DateTime.parse('2012-01-01'))
|
79
72
|
|
80
|
-
assert_equal 1,
|
81
|
-
assert_equal 0,
|
82
|
-
assert_equal 0,
|
83
|
-
assert_equal 0,
|
73
|
+
assert_equal 1, granulated_range[:years].size
|
74
|
+
assert_equal 0, granulated_range[:months].size
|
75
|
+
assert_equal 0, granulated_range[:days].size
|
76
|
+
assert_equal 0, granulated_range[:hours].size
|
77
|
+
assert_equal 0, granulated_range[:rest].size
|
84
78
|
|
85
|
-
refute
|
79
|
+
refute granulated_range[:years].first.exclude_end?
|
86
80
|
end
|
87
81
|
|
88
82
|
def test_properly_parses_open_ended_ranges_2
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
assert_equal 0,
|
93
|
-
assert_equal 1,
|
94
|
-
assert_equal 1,
|
95
|
-
assert_equal 1,
|
96
|
-
|
97
|
-
|
98
|
-
refute
|
99
|
-
|
83
|
+
granulated_range = TimeRange.granulate(
|
84
|
+
DateTime.parse('2011-01-01')...DateTime.parse('2011-12-31').end_of_year)
|
85
|
+
|
86
|
+
assert_equal 0, granulated_range[:years].size
|
87
|
+
assert_equal 1, granulated_range[:months].size
|
88
|
+
assert_equal 1, granulated_range[:days].size
|
89
|
+
assert_equal 1, granulated_range[:hours].size
|
90
|
+
assert_equal 1, granulated_range[:rest].size
|
91
|
+
|
92
|
+
refute granulated_range[:hours].first.exclude_end?
|
93
|
+
refute granulated_range[:months].first.exclude_end?
|
94
|
+
refute granulated_range[:days].first.exclude_end?
|
95
|
+
assert granulated_range[:rest].first.exclude_end?
|
100
96
|
end
|
101
97
|
|
102
98
|
def test_properly_parses_close_ended_ranges_1
|
103
|
-
|
104
|
-
|
99
|
+
granulated_range = TimeRange.granulate(
|
100
|
+
DateTime.parse('2011-01-01')..DateTime.parse('2012-01-01'))
|
105
101
|
|
106
|
-
assert_equal 1,
|
107
|
-
assert_equal 0,
|
108
|
-
assert_equal 0,
|
109
|
-
assert_equal
|
102
|
+
assert_equal 1, granulated_range[:years].size
|
103
|
+
assert_equal 0, granulated_range[:months].size
|
104
|
+
assert_equal 0, granulated_range[:days].size
|
105
|
+
assert_equal 0, granulated_range[:hours].size
|
106
|
+
assert_equal 1, granulated_range[:rest].size
|
110
107
|
|
111
|
-
refute
|
108
|
+
refute granulated_range[:rest].first.exclude_end?
|
112
109
|
end
|
113
110
|
|
114
111
|
def test_properly_parses_close_ended_ranges_2
|
115
|
-
|
116
|
-
|
112
|
+
granulated_range = TimeRange.granulate(
|
113
|
+
DateTime.parse('2011-01-01')..DateTime.parse('2011-12-31').end_of_year)
|
117
114
|
|
118
|
-
assert_equal 1,
|
119
|
-
assert_equal 0,
|
120
|
-
assert_equal 0,
|
121
|
-
assert_equal 0,
|
115
|
+
assert_equal 1, granulated_range[:years].size
|
116
|
+
assert_equal 0, granulated_range[:months].size
|
117
|
+
assert_equal 0, granulated_range[:days].size
|
118
|
+
assert_equal 0, granulated_range[:hours].size
|
119
|
+
assert_equal 0, granulated_range[:rest].size
|
122
120
|
|
123
|
-
refute
|
121
|
+
refute granulated_range[:years].first.exclude_end?
|
124
122
|
end
|
125
123
|
|
126
124
|
def test_properly_handles_Time_UTC_ends_of_months
|
127
125
|
d = DateTime.parse('2010-01-01')
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
assert_equal
|
132
|
-
assert_equal
|
133
|
-
assert_equal 0,
|
126
|
+
granulated_range = TimeRange.granulate(
|
127
|
+
d.beginning_of_month.to_time.utc..d.end_of_month.to_time.utc)
|
128
|
+
|
129
|
+
assert_equal 0, granulated_range[:years].size
|
130
|
+
assert_equal 1, granulated_range[:months].size
|
131
|
+
assert_equal 0, granulated_range[:days].size
|
132
|
+
assert_equal 0, granulated_range[:hours].size
|
133
|
+
assert_equal 0, granulated_range[:rest].size
|
134
134
|
end
|
135
135
|
|
136
136
|
end
|