time_spanner 1.0.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 +7 -0
- data/.gitignore +18 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +11 -0
- data/lib/time_spanner.rb +8 -0
- data/lib/time_spanner/duration_chain.rb +55 -0
- data/lib/time_spanner/errors.rb +8 -0
- data/lib/time_spanner/time_span.rb +34 -0
- data/lib/time_spanner/time_unit_collector.rb +59 -0
- data/lib/time_spanner/time_units.rb +17 -0
- data/lib/time_spanner/time_units/base/calendar_unit.rb +30 -0
- data/lib/time_spanner/time_units/base/time_unit.rb +39 -0
- data/lib/time_spanner/time_units/base/unit.rb +31 -0
- data/lib/time_spanner/time_units/century.rb +30 -0
- data/lib/time_spanner/time_units/day.rb +25 -0
- data/lib/time_spanner/time_units/decade.rb +25 -0
- data/lib/time_spanner/time_units/hour.rb +15 -0
- data/lib/time_spanner/time_units/microsecond.rb +15 -0
- data/lib/time_spanner/time_units/millennium.rb +25 -0
- data/lib/time_spanner/time_units/millisecond.rb +15 -0
- data/lib/time_spanner/time_units/minute.rb +15 -0
- data/lib/time_spanner/time_units/month.rb +25 -0
- data/lib/time_spanner/time_units/nanosecond.rb +15 -0
- data/lib/time_spanner/time_units/second.rb +15 -0
- data/lib/time_spanner/time_units/week.rb +25 -0
- data/lib/time_spanner/time_units/year.rb +25 -0
- data/lib/time_spanner/version.rb +3 -0
- data/test/test_helper.rb +9 -0
- data/test/time_spanner/duration_chain_test.rb +267 -0
- data/test/time_spanner/time_spanner_test.rb +27 -0
- data/test/time_spanner/time_unit_collector_test.rb +66 -0
- data/test/time_spanner/time_units/base/calendar_unit_test.rb +17 -0
- data/test/time_spanner/time_units/base/time_unit_test.rb +18 -0
- data/test/time_spanner/time_units/base/unit_test.rb +37 -0
- data/test/time_spanner/time_units/century_test.rb +55 -0
- data/test/time_spanner/time_units/day_test.rb +84 -0
- data/test/time_spanner/time_units/decade_test.rb +67 -0
- data/test/time_spanner/time_units/hour_test.rb +56 -0
- data/test/time_spanner/time_units/microsecond_test.rb +56 -0
- data/test/time_spanner/time_units/millennium_test.rb +69 -0
- data/test/time_spanner/time_units/millisecond_test.rb +56 -0
- data/test/time_spanner/time_units/minute_test.rb +84 -0
- data/test/time_spanner/time_units/month_test.rb +68 -0
- data/test/time_spanner/time_units/nanosecond_test.rb +40 -0
- data/test/time_spanner/time_units/second_test.rb +56 -0
- data/test/time_spanner/time_units/week_test.rb +55 -0
- data/test/time_spanner/time_units/year_test.rb +91 -0
- data/time_spanner.gemspec +23 -0
- metadata +143 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module TimeSpanner
|
2
|
+
module TimeUnits
|
3
|
+
|
4
|
+
class Day < CalendarUnit
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super 7
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_amount
|
14
|
+
amount = ( to.to_time - from.to_time ).to_i / 86400
|
15
|
+
@amount = at_amount( amount ) > to ? amount - 1 : amount
|
16
|
+
end
|
17
|
+
|
18
|
+
def at_amount amount
|
19
|
+
( from.to_datetime + amount ).to_time
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TimeSpanner
|
2
|
+
module TimeUnits
|
3
|
+
|
4
|
+
class Decade < CalendarUnit
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super 3
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_amount
|
14
|
+
amount = ( to.year - from.year ) / 10
|
15
|
+
@amount = at_amount( amount ) > to ? amount - 1 : amount
|
16
|
+
end
|
17
|
+
|
18
|
+
def at_amount amount
|
19
|
+
( from.to_datetime >> amount * 120 ).to_time
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TimeSpanner
|
2
|
+
module TimeUnits
|
3
|
+
|
4
|
+
class Millennium < CalendarUnit
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super 1
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_amount
|
14
|
+
amount = ( to.year - from.year ) / 1000
|
15
|
+
@amount = at_amount( amount ) > to ? amount - 1 : amount
|
16
|
+
end
|
17
|
+
|
18
|
+
def at_amount amount
|
19
|
+
( from.to_datetime >> amount * 12000 ).to_time
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TimeSpanner
|
2
|
+
module TimeUnits
|
3
|
+
|
4
|
+
class Month < CalendarUnit
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super 5
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_amount
|
14
|
+
amount = ( to.year * 12 + to.month ) - ( from.year * 12 + from.month ) - ( to.day < from.day ? 1 : 0 )
|
15
|
+
@amount = at_amount( amount ) > to ? amount - 1 : amount
|
16
|
+
end
|
17
|
+
|
18
|
+
def at_amount amount
|
19
|
+
( from.to_datetime >> amount ).to_time
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TimeSpanner
|
2
|
+
module TimeUnits
|
3
|
+
|
4
|
+
class Week < CalendarUnit
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super 6
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_amount
|
14
|
+
amount = ( ( to.to_datetime - from.to_datetime ) / 7 ).to_i
|
15
|
+
@amount = at_amount( amount ) > to ? amount - 1 : amount
|
16
|
+
end
|
17
|
+
|
18
|
+
def at_amount amount
|
19
|
+
( from.to_datetime + amount * 7 ).to_time
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TimeSpanner
|
2
|
+
module TimeUnits
|
3
|
+
|
4
|
+
class Year < CalendarUnit
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super 4
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_amount
|
14
|
+
amount = to.year - from.year
|
15
|
+
@amount = at_amount( amount ) > to ? amount - 1 : amount
|
16
|
+
end
|
17
|
+
|
18
|
+
def at_amount amount
|
19
|
+
( from.to_datetime >> amount * 12 ).to_time
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module TimeSpanner
|
4
|
+
|
5
|
+
class DurationChainTest < TestCase
|
6
|
+
include TimeUnits
|
7
|
+
|
8
|
+
describe 'calculation by given units' do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@from = Time.parse('2013-04-03 00:00:00')
|
12
|
+
@to = Time.parse('2013-04-03 02:12:37')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'initializes' do
|
16
|
+
chain = DurationChain.new(@from, @to, [])
|
17
|
+
|
18
|
+
assert_equal @to, chain.to
|
19
|
+
assert_equal 7957, chain.remaining
|
20
|
+
assert_equal [], chain.units
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should switch time span when target time is smaller than start time' do
|
24
|
+
from = Time.parse('2013-06-17 12:34:56')
|
25
|
+
to = Time.parse('2013-04-17 12:34:56')
|
26
|
+
chain = DurationChain.new(from, to, [])
|
27
|
+
|
28
|
+
assert_equal to, chain.instance_variable_get(:@from)
|
29
|
+
assert_equal from, chain.to
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'sorts' do
|
33
|
+
chain = DurationChain.new(@from, @to, [Second, Hour, Minute])
|
34
|
+
|
35
|
+
assert chain.units.first.is_a?(Hour)
|
36
|
+
assert chain.units[1].is_a?(Minute)
|
37
|
+
assert chain.units.last.is_a?(Second)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'each calles for every unit' do
|
41
|
+
from = Time.at(DateTime.parse('2013-06-17 12:34:56').to_time, 2216234.383)
|
42
|
+
to = Time.at(DateTime.parse('5447-12-12 23:11:12').to_time, 3153476.737)
|
43
|
+
units = [Millennium, Century, Decade, Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond]
|
44
|
+
chain = DurationChain.new(from, to, units)
|
45
|
+
|
46
|
+
yielded = []
|
47
|
+
chain.each{|u| yielded << u}
|
48
|
+
|
49
|
+
assert_equal units.size, yielded.size
|
50
|
+
units.each do |unit|
|
51
|
+
assert_kind_of unit, yielded.shift
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'one unit given' do
|
56
|
+
|
57
|
+
it 'calculates hours' do
|
58
|
+
chain = DurationChain.new(@from, @to, [Hour])
|
59
|
+
|
60
|
+
assert_equal 2, chain.units.first.amount
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'calculates minutes' do
|
64
|
+
chain = DurationChain.new(@from, @to, [Minute])
|
65
|
+
|
66
|
+
assert_equal 132, chain.units.first.amount
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'calculates seconds' do
|
70
|
+
chain = DurationChain.new(@from, @to, [Second])
|
71
|
+
|
72
|
+
assert_equal 7957, chain.units.first.amount
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'two units given' do
|
78
|
+
|
79
|
+
it 'calculates hours and minutes' do
|
80
|
+
chain = DurationChain.new(@from, @to, [Hour, Minute])
|
81
|
+
|
82
|
+
assert_equal 2, chain.units.first.amount
|
83
|
+
assert_equal 12, chain.units.last.amount
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'calculates minutes and seconds' do
|
87
|
+
chain = DurationChain.new(@from, @to, [Minute, Second])
|
88
|
+
|
89
|
+
assert_equal 132, chain.units.first.amount
|
90
|
+
assert_equal 37, chain.units.last.amount
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'calculates hours and seconds' do
|
94
|
+
chain = DurationChain.new(@from, @to, [Second, Hour])
|
95
|
+
|
96
|
+
assert_equal 2, chain.units.first.amount
|
97
|
+
assert_equal 757, chain.units.last.amount
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'calculates months and days' do
|
101
|
+
from = Time.parse('2013-04-01 00:00:00')
|
102
|
+
to = Time.parse('2013-07-19 00:00:00')
|
103
|
+
chain = DurationChain.new(from, to, [Month, Day])
|
104
|
+
|
105
|
+
assert_equal 3, chain.units.first.amount
|
106
|
+
assert_equal 18, chain.units.last.amount
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'calculates months with microseconds' do
|
110
|
+
from = Time.parse('2013-04-01 00:00:00')
|
111
|
+
from_with_months = Time.parse('2013-08-01 00:00:00')
|
112
|
+
to = Time.at(from_with_months.to_f, 2.0)
|
113
|
+
chain = DurationChain.new(from, to, [Month, Microsecond])
|
114
|
+
|
115
|
+
assert_equal 4, chain.units.first.amount
|
116
|
+
assert_equal 2, chain.units.last.amount
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'calculates years and months' do
|
120
|
+
from = Time.parse('2013-04-01 00:00:00')
|
121
|
+
to = Time.parse('2016-08-01 00:00:00')
|
122
|
+
chain = DurationChain.new(from, to, [Year, Month])
|
123
|
+
|
124
|
+
assert_equal 3, chain.units.first.amount
|
125
|
+
assert_equal 4, chain.units.last.amount
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'calculates decades and years' do
|
129
|
+
from = Time.parse('2013-04-01 00:00:00')
|
130
|
+
to = Time.parse('2036-04-01 00:00:00')
|
131
|
+
chain = DurationChain.new(from, to, [Decade, Year])
|
132
|
+
|
133
|
+
assert_equal 2, chain.units.first.amount
|
134
|
+
assert_equal 3, chain.units.last.amount
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'calculates centuries and years' do
|
138
|
+
from = Time.parse('2013-04-01 00:00:00')
|
139
|
+
to = Time.parse('2216-04-01 00:00:00')
|
140
|
+
chain = DurationChain.new(from, to, [Century, Year])
|
141
|
+
|
142
|
+
assert_equal 2, chain.units.first.amount
|
143
|
+
assert_equal 3, chain.units.last.amount
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'calculates milleniums and nanoseconds' do
|
147
|
+
from = Time.parse('2013-04-01 00:00:00')
|
148
|
+
target_millenniums = Time.parse('4013-04-01 00:00:00')
|
149
|
+
to = Time.at(target_millenniums.to_r, 0.001)
|
150
|
+
chain = DurationChain.new(from, to, [Millennium, Nanosecond])
|
151
|
+
|
152
|
+
assert_equal 2, chain.units.first.amount
|
153
|
+
assert_equal 1, chain.units.last.amount
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'calculates weeks and days' do
|
157
|
+
from = Time.parse('2013-04-01 00:00:00')
|
158
|
+
to = Time.parse('2013-04-26 00:00:00')
|
159
|
+
chain = DurationChain.new(from, to, [Week, Day])
|
160
|
+
|
161
|
+
assert_equal 3, chain.units.first.amount
|
162
|
+
assert_equal 4, chain.units.last.amount
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'three units given' do
|
168
|
+
|
169
|
+
it 'calculates hours, minutes and seconds' do
|
170
|
+
chain = DurationChain.new(@from, @to, [Hour, Minute, Second])
|
171
|
+
|
172
|
+
assert_equal 2, chain.units.first.amount
|
173
|
+
assert_equal 12, chain.units[1].amount
|
174
|
+
assert_equal 37, chain.units.last.amount
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'calculates months, days and hours' do
|
178
|
+
from = Time.parse('2013-04-01 00:00:00')
|
179
|
+
to = Time.parse('2013-07-19 02:00:00')
|
180
|
+
chain = DurationChain.new(from, to, [Month, Day, Hour])
|
181
|
+
|
182
|
+
assert_equal 3, chain.units.first.amount
|
183
|
+
assert_equal 18, chain.units[1].amount
|
184
|
+
assert_equal 2, chain.units.last.amount
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'calculates months, weeks and days' do
|
188
|
+
from = Time.parse('2013-04-01 00:00:00')
|
189
|
+
to = Time.parse('2013-07-19 02:00:00')
|
190
|
+
chain = DurationChain.new(from, to, [Month, Week, Day])
|
191
|
+
|
192
|
+
assert_equal 3, chain.units.first.amount
|
193
|
+
assert_equal 2, chain.units[1].amount
|
194
|
+
assert_equal 4, chain.units.last.amount
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
describe 'all units given' do
|
200
|
+
|
201
|
+
it 'calculates everything' do
|
202
|
+
from = Time.at(DateTime.parse('2013-06-17 12:34:56').to_time, 2216234.383)
|
203
|
+
to = Time.at(DateTime.parse('5447-12-12 23:11:12').to_time, 3153476.737)
|
204
|
+
chain = DurationChain.new(from, to, [Millennium, Century, Decade, Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond])
|
205
|
+
|
206
|
+
assert_equal 3, chain.units[0].amount
|
207
|
+
assert_equal 4, chain.units[1].amount
|
208
|
+
assert_equal 3, chain.units[2].amount
|
209
|
+
assert_equal 4, chain.units[3].amount
|
210
|
+
assert_equal 5, chain.units[4].amount
|
211
|
+
assert_equal 3, chain.units[5].amount
|
212
|
+
assert_equal 4, chain.units[6].amount
|
213
|
+
assert_equal 10, chain.units[7].amount
|
214
|
+
assert_equal 36, chain.units[8].amount
|
215
|
+
assert_equal 16, chain.units[9].amount
|
216
|
+
assert_equal 937, chain.units[10].amount
|
217
|
+
assert_equal 242, chain.units[11].amount
|
218
|
+
assert_equal 354, chain.units[12].amount
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'calculates only some of them' do
|
222
|
+
from = Time.at(DateTime.parse('2013-07-28 00:00:01').to_time, 0.021)
|
223
|
+
to = Time.at(DateTime.parse('2014-08-01 00:00:59').to_time, 0.023)
|
224
|
+
chain = DurationChain.new(from, to, [Millennium, Century, Decade, Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond])
|
225
|
+
|
226
|
+
assert_equal 0, chain.units[0].amount
|
227
|
+
assert_equal 0, chain.units[1].amount
|
228
|
+
assert_equal 0, chain.units[2].amount
|
229
|
+
assert_equal 1, chain.units[3].amount
|
230
|
+
assert_equal 0, chain.units[4].amount
|
231
|
+
assert_equal 0, chain.units[5].amount
|
232
|
+
assert_equal 4, chain.units[6].amount
|
233
|
+
assert_equal 0, chain.units[7].amount
|
234
|
+
assert_equal 0, chain.units[8].amount
|
235
|
+
assert_equal 58, chain.units[9].amount
|
236
|
+
assert_equal 0, chain.units[10].amount
|
237
|
+
assert_equal 0, chain.units[11].amount
|
238
|
+
assert_equal 2, chain.units[12].amount
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'calculates nothing' do
|
242
|
+
from = Time.at(DateTime.parse('2013-07-28 00:00:01').to_time, 0.021)
|
243
|
+
to = Time.at(DateTime.parse('2013-07-28 00:00:01').to_time, 0.021)
|
244
|
+
chain = DurationChain.new(from, to, [Millennium, Century, Decade, Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Microsecond, Nanosecond])
|
245
|
+
|
246
|
+
assert_equal 0, chain.units[0].amount
|
247
|
+
assert_equal 0, chain.units[1].amount
|
248
|
+
assert_equal 0, chain.units[2].amount
|
249
|
+
assert_equal 0, chain.units[3].amount
|
250
|
+
assert_equal 0, chain.units[4].amount
|
251
|
+
assert_equal 0, chain.units[5].amount
|
252
|
+
assert_equal 0, chain.units[6].amount
|
253
|
+
assert_equal 0, chain.units[7].amount
|
254
|
+
assert_equal 0, chain.units[8].amount
|
255
|
+
assert_equal 0, chain.units[9].amount
|
256
|
+
assert_equal 0, chain.units[10].amount
|
257
|
+
assert_equal 0, chain.units[11].amount
|
258
|
+
assert_equal 0, chain.units[12].amount
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|