fat_core 2.0.1 → 3.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 +4 -4
- data/.ruby-version +1 -1
- data/bin/console +14 -0
- data/fat_core.gemspec +1 -0
- data/lib/fat_core/all.rb +14 -0
- data/lib/fat_core/array.rb +29 -22
- data/lib/fat_core/big_decimal.rb +12 -0
- data/lib/fat_core/date.rb +951 -938
- data/lib/fat_core/enumerable.rb +19 -3
- data/lib/fat_core/hash.rb +48 -43
- data/lib/fat_core/kernel.rb +4 -2
- data/lib/fat_core/nil.rb +13 -13
- data/lib/fat_core/numeric.rb +82 -86
- data/lib/fat_core/range.rb +164 -160
- data/lib/fat_core/string.rb +247 -242
- data/lib/fat_core/symbol.rb +17 -11
- data/lib/fat_core/version.rb +2 -2
- data/lib/fat_core.rb +0 -21
- data/spec/lib/array_spec.rb +2 -0
- data/spec/lib/big_decimal_spec.rb +7 -0
- data/spec/lib/date_spec.rb +7 -26
- data/spec/lib/enumerable_spec.rb +26 -1
- data/spec/lib/hash_spec.rb +2 -0
- data/spec/lib/kernel_spec.rb +2 -0
- data/spec/lib/nil_spec.rb +6 -0
- data/spec/lib/numeric_spec.rb +1 -5
- data/spec/lib/range_spec.rb +1 -1
- data/spec/lib/string_spec.rb +1 -6
- data/spec/lib/symbol_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -2
- metadata +9 -8
- data/lib/fat_core/boolean.rb +0 -25
- data/lib/fat_core/latex_eruby.rb +0 -11
- data/lib/fat_core/period.rb +0 -533
- data/spec/lib/period_spec.rb +0 -677
data/spec/lib/period_spec.rb
DELETED
@@ -1,677 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Period do
|
4
|
-
before :each do
|
5
|
-
# Pretend it is this date. Not at beg or end of year, quarter,
|
6
|
-
# month, or week. It is a Wednesday
|
7
|
-
allow(Date).to receive_messages(today: Date.parse('2012-07-18'))
|
8
|
-
allow(Date).to receive_messages(current: Date.parse('2012-07-18'))
|
9
|
-
end
|
10
|
-
|
11
|
-
describe 'initialization' do
|
12
|
-
it 'should be initializable with date strings' do
|
13
|
-
expect(Period.new('2013-01-01', '2013-12-13')).to be_instance_of Period
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'should be initializable with Dates' do
|
17
|
-
expect(Period.new('2013-01-01', '2013-12-13'))
|
18
|
-
.to be_instance_of Period
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'should raise a ArgumentError if last > first' do
|
22
|
-
expect {
|
23
|
-
Period.new('2013-01-01', '2012-12-31')
|
24
|
-
}.to raise_error ArgumentError
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'should raise a ArgumentError if initialized with invalid date string' do
|
28
|
-
expect {
|
29
|
-
Period.new('2013-01-01', '2013-12-32')
|
30
|
-
}.to raise_error ArgumentError
|
31
|
-
expect {
|
32
|
-
Period.new('2013-13-01', '2013-12-31')
|
33
|
-
}.to raise_error ArgumentError
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'should raise a ArgumentError if initialized otherwise' do
|
37
|
-
expect {
|
38
|
-
Period.new(2013 - 1 - 1, 2013 - 12 - 31)
|
39
|
-
}.to raise_error ArgumentError
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe 'class methods' do
|
44
|
-
it 'should be able to parse a period phrase' do
|
45
|
-
pd = Period.parse_phrase('from this_year')
|
46
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
47
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
48
|
-
|
49
|
-
pd = Period.parse_phrase('from 2012-07 to 2012')
|
50
|
-
expect(pd.first).to eq(Date.parse('2012-07-01'))
|
51
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
52
|
-
|
53
|
-
pd = Period.parse_phrase('from 1H')
|
54
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
55
|
-
expect(pd.last).to eq(Date.parse('2012-06-30'))
|
56
|
-
|
57
|
-
pd = Period.parse_phrase('to 2H')
|
58
|
-
expect(pd.first).to eq(Date.parse('2012-07-01'))
|
59
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
60
|
-
|
61
|
-
pd = Period.parse_phrase('from 2Q')
|
62
|
-
expect(pd.first).to eq(Date.parse('2012-04-01'))
|
63
|
-
expect(pd.last).to eq(Date.parse('2012-06-30'))
|
64
|
-
|
65
|
-
pd = Period.parse_phrase('to 3Q')
|
66
|
-
expect(pd.first).to eq(Date.parse('2012-07-01'))
|
67
|
-
expect(pd.last).to eq(Date.parse('2012-09-30'))
|
68
|
-
|
69
|
-
pd = Period.parse_phrase('to 2012-2Q')
|
70
|
-
expect(pd.first).to eq(Date.parse('2012-04-01'))
|
71
|
-
expect(pd.last).to eq(Date.parse('2012-06-30'))
|
72
|
-
|
73
|
-
pd = Period.parse_phrase('from 2012-1Q')
|
74
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
75
|
-
expect(pd.last).to eq(Date.parse('2012-03-31'))
|
76
|
-
|
77
|
-
pd = Period.parse_phrase('from 2H')
|
78
|
-
expect(pd.first).to eq(Date.parse('2012-07-01'))
|
79
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
80
|
-
|
81
|
-
pd = Period.parse_phrase('to 1H')
|
82
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
83
|
-
expect(pd.last).to eq(Date.parse('2012-06-30'))
|
84
|
-
|
85
|
-
pd = Period.parse_phrase('to 2012-2H')
|
86
|
-
expect(pd.first).to eq(Date.parse('2012-07-01'))
|
87
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
88
|
-
|
89
|
-
pd = Period.parse_phrase('from 2012-1H')
|
90
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
91
|
-
expect(pd.last).to eq(Date.parse('2012-06-30'))
|
92
|
-
|
93
|
-
pd = Period.parse_phrase('to 2012')
|
94
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
95
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
96
|
-
|
97
|
-
pd = Period.parse_phrase('from 2012')
|
98
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
99
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
100
|
-
|
101
|
-
pd = Period.parse_phrase('2012')
|
102
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
103
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
104
|
-
|
105
|
-
pd = Period.parse_phrase('this_year')
|
106
|
-
expect(pd.first).to eq(Date.parse('2012-01-01'))
|
107
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
108
|
-
|
109
|
-
pd = Period.parse_phrase('from last_year to this_year')
|
110
|
-
expect(pd.first).to eq(Date.parse('2011-01-01'))
|
111
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
112
|
-
|
113
|
-
pd = Period.parse_phrase('from last_year to this_year')
|
114
|
-
expect(pd.first).to eq(Date.parse('2011-01-01'))
|
115
|
-
expect(pd.last).to eq(Date.parse('2012-12-31'))
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'should return nil when parsing never' do
|
119
|
-
expect(Period.parse('never')).to be_nil
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'should know how to parse a pair of date specs' do
|
123
|
-
expect(Period.parse('2014-3Q').first).to eq Date.parse('2014-07-01')
|
124
|
-
expect(Period.parse('2014-3Q').last).to eq Date.parse('2014-09-30')
|
125
|
-
expect(Period.parse('2014-3Q').last).to eq Date.parse('2014-09-30')
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'should know what the valid chunk syms are' do
|
129
|
-
expect(Period.chunk_syms.size).to eq(10)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'should know the days in a chunk sym' do
|
133
|
-
expect(Period.chunk_sym_to_days(:year)).to eq(365)
|
134
|
-
expect(Period.chunk_sym_to_days(:quarter)).to eq(90)
|
135
|
-
expect(Period.chunk_sym_to_days(:bimonth)).to eq(60)
|
136
|
-
expect(Period.chunk_sym_to_days(:month)).to eq(30)
|
137
|
-
expect(Period.chunk_sym_to_days(:semimonth)).to eq(15)
|
138
|
-
expect(Period.chunk_sym_to_days(:biweek)).to eq(14)
|
139
|
-
expect(Period.chunk_sym_to_days(:week)).to eq(7)
|
140
|
-
expect(Period.chunk_sym_to_days(:day)).to eq(1)
|
141
|
-
expect(Period.chunk_sym_to_days(:irregular)).to eq(30)
|
142
|
-
expect {
|
143
|
-
Period.chunk_sym_to_days(:eon)
|
144
|
-
}.to raise_error ArgumentError
|
145
|
-
end
|
146
|
-
|
147
|
-
it 'should know the maximum days in a chunk sym' do
|
148
|
-
expect(Period.chunk_sym_to_max_days(:year)).to eq(366)
|
149
|
-
expect(Period.chunk_sym_to_max_days(:quarter)).to eq(92)
|
150
|
-
expect(Period.chunk_sym_to_max_days(:bimonth)).to eq(62)
|
151
|
-
expect(Period.chunk_sym_to_max_days(:month)).to eq(31)
|
152
|
-
expect(Period.chunk_sym_to_max_days(:semimonth)).to eq(16)
|
153
|
-
expect(Period.chunk_sym_to_max_days(:biweek)).to eq(14)
|
154
|
-
expect(Period.chunk_sym_to_max_days(:week)).to eq(7)
|
155
|
-
expect(Period.chunk_sym_to_max_days(:day)).to eq(1)
|
156
|
-
expect { Period.chunk_sym_to_max_days(:irregular) }
|
157
|
-
.to raise_error ArgumentError
|
158
|
-
expect {
|
159
|
-
Period.chunk_sym_to_days(:eon)
|
160
|
-
}.to raise_error ArgumentError
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'should know the chunk sym for given days but only :year, :quarter, :month' do
|
164
|
-
(356..376).each { |d| expect(Period.days_to_chunk_sym(d)).to eq(:year) }
|
165
|
-
(180..183).each { |d| expect(Period.days_to_chunk_sym(d)).to eq(:half) }
|
166
|
-
(86..96).each { |d| expect(Period.days_to_chunk_sym(d)).to eq(:quarter) }
|
167
|
-
(28..31).each { |d| expect(Period.days_to_chunk_sym(d)).to eq(:month) }
|
168
|
-
expect(Period.days_to_chunk_sym(7)).to eq(:week)
|
169
|
-
expect(Period.days_to_chunk_sym(1)).to eq(:day)
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'should know what to call a chunk based on its size' do
|
173
|
-
expect(Period.new('2011-01-01', '2011-12-31').chunk_name).to eq('Year')
|
174
|
-
expect(Period.new('2011-01-01', '2011-06-30').chunk_name).to eq('Half')
|
175
|
-
expect(Period.new('2011-01-01', '2011-03-31').chunk_name).to eq('Quarter')
|
176
|
-
expect(Period.new('2011-01-01', '2011-02-28').chunk_name)
|
177
|
-
.to eq('Bi-month')
|
178
|
-
expect(Period.new('2011-01-01', '2011-01-31').chunk_name).to eq('Month')
|
179
|
-
expect(Period.new('2011-01-01', '2011-01-15').chunk_name)
|
180
|
-
.to eq('Semi-month')
|
181
|
-
expect(Period.new('2011-01-09', '2011-01-22').chunk_name).to eq('Bi-week')
|
182
|
-
expect(Period.new('2011-01-01', '2011-01-07').chunk_name).to eq('Week')
|
183
|
-
expect(Period.new('2011-01-01', '2011-01-01').chunk_name).to eq('Day')
|
184
|
-
expect(Period.new('2011-01-01', '2011-01-21').chunk_name).to eq('Period')
|
185
|
-
# Only size matters, not whether the period begins and ends on
|
186
|
-
# calendar unit boundaries.
|
187
|
-
expect(Period.new('2011-02-11', '2011-03-10').chunk_name).to eq('Month')
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
describe 'sorting' do
|
192
|
-
it 'should sort by first, then size' do
|
193
|
-
periods = []
|
194
|
-
periods << Period.new('2012-07-01', '2012-07-31')
|
195
|
-
periods << Period.new('2012-06-01', '2012-06-30')
|
196
|
-
periods << Period.new('2012-08-01', '2012-08-31')
|
197
|
-
periods.sort!
|
198
|
-
# First by start_date, then shortest period to longest
|
199
|
-
expect(periods[0].first).to eq(Date.parse('2012-06-01'))
|
200
|
-
expect(periods[1].first).to eq(Date.parse('2012-07-01'))
|
201
|
-
expect(periods[2].first).to eq(Date.parse('2012-08-01'))
|
202
|
-
expect(periods[0].last).to eq(Date.parse('2012-06-30'))
|
203
|
-
expect(periods[1].last).to eq(Date.parse('2012-07-31'))
|
204
|
-
expect(periods[2].last).to eq(Date.parse('2012-08-31'))
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'should return nil if comparing incomparables' do
|
208
|
-
pd = Period.new('2012-08-01', '2012-08-31')
|
209
|
-
rg = (Date.parse('2012-08-01')..Date.parse('2012-08-31'))
|
210
|
-
expect(pd <=> rg).to be_nil
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
describe 'instance methods' do
|
215
|
-
it 'should be able to set first' do
|
216
|
-
pp = Period.new('2014-12-07', '2014-12-17')
|
217
|
-
pp.first = Date.parse('2014-12-01')
|
218
|
-
expect(pp.first).to eq Date.parse('2014-12-01')
|
219
|
-
end
|
220
|
-
|
221
|
-
it 'should be able to set last' do
|
222
|
-
pp = Period.new('2014-12-07', '2014-12-17')
|
223
|
-
pp.last = Date.parse('2014-12-31')
|
224
|
-
expect(pp.last).to eq Date.parse('2014-12-31')
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'should not be able to set first > last' do
|
228
|
-
pp = Period.new('2014-12-07', '2014-12-17')
|
229
|
-
expect {
|
230
|
-
pp.first = Date.parse('2014-12-31')
|
231
|
-
}.to raise_error ArgumentError
|
232
|
-
end
|
233
|
-
|
234
|
-
it 'should not be able to set last < first' do
|
235
|
-
pp = Period.new('2014-12-07', '2014-12-17')
|
236
|
-
expect {
|
237
|
-
pp.last = Date.parse('2014-12-01')
|
238
|
-
}.to raise_error ArgumentError
|
239
|
-
end
|
240
|
-
|
241
|
-
it 'should be able to compare for equality' do
|
242
|
-
pp1 = Period.new('2013-01-01', '2013-12-31')
|
243
|
-
pp2 = Period.new('2013-01-01', '2013-12-31')
|
244
|
-
pp3 = Period.new('2013-01-01', '2013-12-30')
|
245
|
-
expect((pp1 == pp2)).to be true
|
246
|
-
expect((pp1 == pp3)).to_not be true
|
247
|
-
expect((pp1 != pp3)).to be true
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'should be able to convert into a Range' do
|
251
|
-
pp = Period.new('2013-01-01', '2013-12-31')
|
252
|
-
rr = Period.new('2013-01-01', '2013-12-31').to_range
|
253
|
-
expect(rr).to be_instance_of Range
|
254
|
-
expect(rr.first).to eq(pp.first)
|
255
|
-
expect(rr.last).to eq(pp.last)
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'should be able to tell if it contains a date' do
|
259
|
-
pp = Period.new('2013-01-01', '2013-12-31')
|
260
|
-
expect(pp.contains?(Date.parse('2013-01-01'))).to be true
|
261
|
-
expect(pp.contains?(Date.parse('2013-07-04'))).to be true
|
262
|
-
expect(pp.contains?(Date.parse('2013-12-31'))).to be true
|
263
|
-
expect(pp.contains?(Date.parse('2012-07-04'))).to be false
|
264
|
-
end
|
265
|
-
|
266
|
-
it 'should raise an error if contains? arg is not a date' do
|
267
|
-
pp = Period.new('2013-01-01', '2013-12-31')
|
268
|
-
expect {
|
269
|
-
pp.contains?(Period.new('2013-06-01', '2013-06-30'))
|
270
|
-
}.to raise_error(/must be a Date/)
|
271
|
-
|
272
|
-
# But not if argument can be converted to date with to_date
|
273
|
-
expect {
|
274
|
-
pp.contains?(Time.now)
|
275
|
-
}.not_to raise_error
|
276
|
-
end
|
277
|
-
|
278
|
-
it 'should be able to tell if it contains a date with ===' do
|
279
|
-
pp = Period.new('2013-01-01', '2013-12-31')
|
280
|
-
expect(pp === Date.parse('2013-01-01')).to be true
|
281
|
-
expect(pp === Date.parse('2013-07-04')).to be true
|
282
|
-
expect(pp === Date.parse('2013-12-31')).to be true
|
283
|
-
expect(pp === Date.parse('2012-07-04')).to be false
|
284
|
-
end
|
285
|
-
|
286
|
-
it 'should be able to convert itself to days' do
|
287
|
-
expect(Period.new('2013-01-01', '2013-01-01').days).to eq(1)
|
288
|
-
expect(Period.new('2013-01-01', '2013-12-31').days).to eq(365)
|
289
|
-
end
|
290
|
-
|
291
|
-
it 'should be able to convert itself to fractional months' do
|
292
|
-
expect(Period.new('2013-01-01', '2013-01-01').months).to eq(1 / 30.436875)
|
293
|
-
expect(Period.new('2013-01-01', '2013-12-31').months(30)).to eq(365 / 30.0)
|
294
|
-
expect(Period.new('2013-01-01', '2013-06-30').months.round(0)).to eq(6.0)
|
295
|
-
end
|
296
|
-
|
297
|
-
it 'should be able to convert itself to fractional years' do
|
298
|
-
expect(Period.new('2013-01-01', '2013-01-01').years).to eq(1 / 365.2425)
|
299
|
-
expect(Period.new('2013-01-01', '2013-12-31').years(365)).to eq(1.0)
|
300
|
-
expect(Period.new('2013-01-01', '2013-06-30').years.round(1)).to eq(0.5)
|
301
|
-
end
|
302
|
-
|
303
|
-
it 'should be able to enumerate its days' do
|
304
|
-
Period.parse('2014-12').each do |dy|
|
305
|
-
expect(dy.class).to eq Date
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
it 'should be able to return the trading days within period' do
|
310
|
-
tds = Period.parse('2014-12').trading_days
|
311
|
-
expect(tds.count).to eq(22)
|
312
|
-
end
|
313
|
-
|
314
|
-
it 'should know its size' do
|
315
|
-
pp = Period.new('2013-01-01', '2013-12-31')
|
316
|
-
expect(pp.size).to eq 365
|
317
|
-
expect(pp.length).to eq 365
|
318
|
-
end
|
319
|
-
|
320
|
-
it 'should implement the each method' do
|
321
|
-
pp = Period.new('2013-12-01', '2013-12-31')
|
322
|
-
pp.map(&:iso)
|
323
|
-
.each { |s| expect(s).to match(/\d{4}-\d\d-\d\d/) }
|
324
|
-
end
|
325
|
-
|
326
|
-
it 'should be able to make a concise period string' do
|
327
|
-
expect(Period.new('2013-01-01', '2013-12-31').to_s).to eq('2013')
|
328
|
-
expect(Period.new('2013-04-01', '2013-06-30').to_s).to eq('2013-2Q')
|
329
|
-
expect(Period.new('2013-03-01', '2013-03-31').to_s).to eq('2013-03')
|
330
|
-
expect(Period.new('2013-03-11', '2013-10-31').to_s)
|
331
|
-
.to eq('2013-03-11 to 2013-10-31')
|
332
|
-
end
|
333
|
-
|
334
|
-
it 'should be able to make a TeX string' do
|
335
|
-
expect(Period.new('2013-01-01', '2013-12-31').tex_quote)
|
336
|
-
.to eq('2013-01-01--2013-12-31')
|
337
|
-
end
|
338
|
-
|
339
|
-
# Note in the following that first period must begin within self.
|
340
|
-
it 'should be able to chunk into years' do
|
341
|
-
chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :year)
|
342
|
-
expect(chunks.size).to eq(3)
|
343
|
-
expect(chunks[0].first.iso).to eq('2010-01-01')
|
344
|
-
expect(chunks[0].last.iso).to eq('2010-12-31')
|
345
|
-
expect(chunks[1].first.iso).to eq('2011-01-01')
|
346
|
-
expect(chunks[1].last.iso).to eq('2011-12-31')
|
347
|
-
expect(chunks[2].first.iso).to eq('2012-01-01')
|
348
|
-
expect(chunks[2].last.iso).to eq('2012-12-31')
|
349
|
-
end
|
350
|
-
|
351
|
-
it 'should be able to chunk into halves' do
|
352
|
-
chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :half)
|
353
|
-
expect(chunks.size).to eq(6)
|
354
|
-
expect(chunks[0].first.iso).to eq('2010-01-01')
|
355
|
-
expect(chunks[0].last.iso).to eq('2010-06-30')
|
356
|
-
expect(chunks[1].first.iso).to eq('2010-07-01')
|
357
|
-
expect(chunks[1].last.iso).to eq('2010-12-31')
|
358
|
-
expect(chunks[2].first.iso).to eq('2011-01-01')
|
359
|
-
expect(chunks[2].last.iso).to eq('2011-06-30')
|
360
|
-
expect(chunks.last.first.iso).to eq('2012-07-01')
|
361
|
-
expect(chunks.last.last.iso).to eq('2012-12-31')
|
362
|
-
end
|
363
|
-
|
364
|
-
it 'should be able to chunk into quarters' do
|
365
|
-
chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :quarter)
|
366
|
-
expect(chunks.size).to eq(12)
|
367
|
-
expect(chunks[0].first.iso).to eq('2010-01-01')
|
368
|
-
expect(chunks[0].last.iso).to eq('2010-03-31')
|
369
|
-
expect(chunks[1].first.iso).to eq('2010-04-01')
|
370
|
-
expect(chunks[1].last.iso).to eq('2010-06-30')
|
371
|
-
expect(chunks[2].first.iso).to eq('2010-07-01')
|
372
|
-
expect(chunks[2].last.iso).to eq('2010-09-30')
|
373
|
-
expect(chunks.last.first.iso).to eq('2012-10-01')
|
374
|
-
expect(chunks.last.last.iso).to eq('2012-12-31')
|
375
|
-
end
|
376
|
-
|
377
|
-
it 'should be able to chunk into bimonths' do
|
378
|
-
chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :bimonth)
|
379
|
-
expect(chunks.size).to eq(18)
|
380
|
-
expect(chunks[0].first.iso).to eq('2010-01-01')
|
381
|
-
expect(chunks[0].last.iso).to eq('2010-02-28')
|
382
|
-
expect(chunks[1].first.iso).to eq('2010-03-01')
|
383
|
-
expect(chunks[1].last.iso).to eq('2010-04-30')
|
384
|
-
expect(chunks[2].first.iso).to eq('2010-05-01')
|
385
|
-
expect(chunks[2].last.iso).to eq('2010-06-30')
|
386
|
-
expect(chunks.last.first.iso).to eq('2012-11-01')
|
387
|
-
expect(chunks.last.last.iso).to eq('2012-12-31')
|
388
|
-
end
|
389
|
-
|
390
|
-
it 'should be able to chunk into months' do
|
391
|
-
chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :month)
|
392
|
-
expect(chunks.size).to eq(36)
|
393
|
-
expect(chunks[0].first.iso).to eq('2010-01-01')
|
394
|
-
expect(chunks[0].last.iso).to eq('2010-01-31')
|
395
|
-
expect(chunks[1].first.iso).to eq('2010-02-01')
|
396
|
-
expect(chunks[1].last.iso).to eq('2010-02-28')
|
397
|
-
expect(chunks[2].first.iso).to eq('2010-03-01')
|
398
|
-
expect(chunks[2].last.iso).to eq('2010-03-31')
|
399
|
-
expect(chunks.last.first.iso).to eq('2012-12-01')
|
400
|
-
expect(chunks.last.last.iso).to eq('2012-12-31')
|
401
|
-
end
|
402
|
-
|
403
|
-
it 'should be able to chunk into semimonths' do
|
404
|
-
chunks = Period.new('2009-12-25', '2013-01-10').chunks(size: :semimonth)
|
405
|
-
expect(chunks.size).to eq(72)
|
406
|
-
expect(chunks[0].first.iso).to eq('2010-01-01')
|
407
|
-
expect(chunks[0].last.iso).to eq('2010-01-15')
|
408
|
-
expect(chunks[1].first.iso).to eq('2010-01-16')
|
409
|
-
expect(chunks[1].last.iso).to eq('2010-01-31')
|
410
|
-
expect(chunks[2].first.iso).to eq('2010-02-01')
|
411
|
-
expect(chunks[2].last.iso).to eq('2010-02-15')
|
412
|
-
expect(chunks.last.first.iso).to eq('2012-12-16')
|
413
|
-
expect(chunks.last.last.iso).to eq('2012-12-31')
|
414
|
-
end
|
415
|
-
|
416
|
-
it 'should be able to chunk into biweeks' do
|
417
|
-
chunks = Period.new('2009-12-29', '2013-01-10').chunks(size: :biweek)
|
418
|
-
expect(chunks.size).to be >= (26 * 3)
|
419
|
-
expect(chunks[0].first.iso).to eq('2010-01-04')
|
420
|
-
expect(chunks[0].last.iso).to eq('2010-01-17')
|
421
|
-
expect(chunks[1].first.iso).to eq('2010-01-18')
|
422
|
-
expect(chunks[1].last.iso).to eq('2010-01-31')
|
423
|
-
expect(chunks[2].first.iso).to eq('2010-02-01')
|
424
|
-
expect(chunks[2].last.iso).to eq('2010-02-14')
|
425
|
-
expect(chunks.last.first.iso).to eq('2012-12-17')
|
426
|
-
expect(chunks.last.last.iso).to eq('2012-12-30')
|
427
|
-
end
|
428
|
-
|
429
|
-
it 'should be able to chunk into weeks' do
|
430
|
-
chunks = Period.new('2010-01-01', '2012-12-31').chunks(size: :week)
|
431
|
-
expect(chunks.size).to be >= (52 * 3)
|
432
|
-
expect(chunks[0].first.iso).to eq('2010-01-04')
|
433
|
-
expect(chunks[0].last.iso).to eq('2010-01-10')
|
434
|
-
expect(chunks[1].first.iso).to eq('2010-01-11')
|
435
|
-
expect(chunks[1].last.iso).to eq('2010-01-17')
|
436
|
-
expect(chunks[2].first.iso).to eq('2010-01-18')
|
437
|
-
expect(chunks[2].last.iso).to eq('2010-01-24')
|
438
|
-
expect(chunks.last.first.iso).to eq('2012-12-24')
|
439
|
-
expect(chunks.last.last.iso).to eq('2012-12-30')
|
440
|
-
end
|
441
|
-
|
442
|
-
it 'should be able to chunk into days' do
|
443
|
-
chunks = Period.new('2012-12-28', '2012-12-31').chunks(size: :day)
|
444
|
-
expect(chunks.size).to eq(4)
|
445
|
-
expect(chunks[0].first.iso).to eq('2012-12-28')
|
446
|
-
expect(chunks[0].last.iso).to eq('2012-12-28')
|
447
|
-
expect(chunks[1].first.iso).to eq('2012-12-29')
|
448
|
-
expect(chunks[1].last.iso).to eq('2012-12-29')
|
449
|
-
expect(chunks[2].first.iso).to eq('2012-12-30')
|
450
|
-
expect(chunks[2].last.iso).to eq('2012-12-30')
|
451
|
-
expect(chunks.last.first.iso).to eq('2012-12-31')
|
452
|
-
expect(chunks.last.last.iso).to eq('2012-12-31')
|
453
|
-
end
|
454
|
-
|
455
|
-
it 'should raise error for invalid chunk name' do
|
456
|
-
expect {
|
457
|
-
Period.new('2012-12-28', '2012-12-31').chunks(size: :wally)
|
458
|
-
}.to raise_error /unknown chunk sym/
|
459
|
-
end
|
460
|
-
|
461
|
-
it 'should raise error for too large a chunk and no partials allowed' do
|
462
|
-
expect {
|
463
|
-
Period.new('2012-12-01', '2012-12-31').
|
464
|
-
chunks(size: :bimonth, partial_first: false, partial_last: false)
|
465
|
-
}.to raise_error /longer than/
|
466
|
-
end
|
467
|
-
|
468
|
-
it 'should return period itself for too large chunk if partials allowed' do
|
469
|
-
pd = Period.new('2012-12-01', '2012-12-31')
|
470
|
-
expect(pd.chunks(size: :bimonth, partial_first: true).first).to eq(pd)
|
471
|
-
expect(pd.chunks(size: :bimonth, partial_last: true).first).to eq(pd)
|
472
|
-
end
|
473
|
-
|
474
|
-
it 'should not include a partial final chunk by default' do
|
475
|
-
chunks = Period.new('2012-01-01', '2012-03-30').chunks(size: :month)
|
476
|
-
expect(chunks.size).to eq(2)
|
477
|
-
end
|
478
|
-
|
479
|
-
it 'should include a partial final chunk if partial_last' do
|
480
|
-
chunks = Period.new('2012-01-01', '2012-03-30')
|
481
|
-
.chunks(size: :month, partial_last: true)
|
482
|
-
expect(chunks.size).to eq(3)
|
483
|
-
expect(chunks.last.first).to eq(Date.parse('2012-03-01'))
|
484
|
-
expect(chunks.last.last).to eq(Date.parse('2012-03-30'))
|
485
|
-
end
|
486
|
-
|
487
|
-
it 'should include a final chunk beyond end_date if round_up' do
|
488
|
-
chunks = Period.new('2012-01-01', '2012-03-30')
|
489
|
-
.chunks(size: :month, round_up_last: true)
|
490
|
-
expect(chunks.size).to eq(3)
|
491
|
-
expect(chunks.last.first).to eq(Date.parse('2012-03-01'))
|
492
|
-
expect(chunks.last.last).to eq(Date.parse('2012-03-31'))
|
493
|
-
end
|
494
|
-
|
495
|
-
it 'should not include a partial initial chunk by default' do
|
496
|
-
chunks = Period.new('2012-01-13', '2012-03-31').chunks(size: :month)
|
497
|
-
expect(chunks.size).to eq(2)
|
498
|
-
expect(chunks[0].first).to eq(Date.parse('2012-02-01'))
|
499
|
-
expect(chunks[0].last).to eq(Date.parse('2012-02-29'))
|
500
|
-
end
|
501
|
-
|
502
|
-
it 'should include a partial initial chunk by if partial_first' do
|
503
|
-
chunks = Period.new('2012-01-13', '2012-03-31')
|
504
|
-
.chunks(size: :month, partial_first: true)
|
505
|
-
expect(chunks.size).to eq(3)
|
506
|
-
expect(chunks[0].first).to eq(Date.parse('2012-01-13'))
|
507
|
-
expect(chunks[0].last).to eq(Date.parse('2012-01-31'))
|
508
|
-
end
|
509
|
-
|
510
|
-
it 'should include a final chunk beyond end_date if round_up' do
|
511
|
-
chunks = Period.new('2012-01-01', '2012-03-30')
|
512
|
-
.chunks(size: :month, round_up_last: true)
|
513
|
-
expect(chunks.size).to eq(3)
|
514
|
-
expect(chunks.last.first).to eq(Date.parse('2012-03-01'))
|
515
|
-
expect(chunks.last.last).to eq(Date.parse('2012-03-31'))
|
516
|
-
end
|
517
|
-
|
518
|
-
it 'should be able to determine its chunk_sym' do
|
519
|
-
expect(Period.new('2013-01-01', '2013-12-31').chunk_sym).to eq(:year)
|
520
|
-
expect(Period.new('2012-01-01', '2013-12-31').chunk_sym).to_not eq(:year)
|
521
|
-
|
522
|
-
expect(Period.new('2013-01-01', '2013-06-30').chunk_sym).to eq(:half)
|
523
|
-
expect(Period.new('2012-01-01', '2013-05-31').chunk_sym).to_not eq(:half)
|
524
|
-
|
525
|
-
expect(Period.new('2013-04-01', '2013-06-30').chunk_sym).to eq(:quarter)
|
526
|
-
expect(Period.new('2013-04-01', '2013-09-30').chunk_sym)
|
527
|
-
.to_not eq(:quarter)
|
528
|
-
|
529
|
-
expect(Period.new('2013-03-01', '2013-04-30').chunk_sym).to eq(:bimonth)
|
530
|
-
expect(Period.new('2013-03-01', '2013-06-30').chunk_sym)
|
531
|
-
.to_not eq(:bimonth)
|
532
|
-
|
533
|
-
expect(Period.new('2013-04-01', '2013-04-30').chunk_sym).to eq(:month)
|
534
|
-
expect(Period.new('2013-04-01', '2013-05-30').chunk_sym).to_not eq(:month)
|
535
|
-
|
536
|
-
expect(Period.new('2013-05-16', '2013-05-31').chunk_sym).to eq(:semimonth)
|
537
|
-
expect(Period.new('2013-05-16', '2013-06-30').chunk_sym)
|
538
|
-
.to_not eq(:semimonth)
|
539
|
-
|
540
|
-
expect(Period.new('2013-11-04', '2013-11-17').chunk_sym).to eq(:biweek)
|
541
|
-
expect(Period.new('2013-11-04', '2013-11-24').chunk_sym)
|
542
|
-
.to_not eq(:biweek)
|
543
|
-
|
544
|
-
expect(Period.new('2013-11-11', '2013-11-17').chunk_sym).to eq(:week)
|
545
|
-
expect(Period.new('2013-11-11', '2013-11-24').chunk_sym).to_not eq(:week)
|
546
|
-
|
547
|
-
expect(Period.new('2013-11-10', '2013-11-10').chunk_sym).to eq(:day)
|
548
|
-
expect(Period.new('2013-11-10', '2013-11-11').chunk_sym).to_not eq(:day)
|
549
|
-
|
550
|
-
expect(Period.new('2013-11-02', '2013-12-16').chunk_sym).to eq(:irregular)
|
551
|
-
end
|
552
|
-
|
553
|
-
it 'should know if it\'s a subset of another period' do
|
554
|
-
year = Period.parse('this_year')
|
555
|
-
month = Period.parse('this_month')
|
556
|
-
expect(month.subset_of?(year)).to be true
|
557
|
-
expect(year.subset_of?(year)).to be true
|
558
|
-
end
|
559
|
-
|
560
|
-
it 'should know if it\'s a proper subset of another period' do
|
561
|
-
year = Period.parse('this_year')
|
562
|
-
month = Period.parse('this_month')
|
563
|
-
expect(month.proper_subset_of?(year)).to be true
|
564
|
-
expect(year.proper_subset_of?(year)).to be false
|
565
|
-
end
|
566
|
-
|
567
|
-
it 'should know if it\'s a superset of another period' do
|
568
|
-
year = Period.parse('this_year')
|
569
|
-
month = Period.parse('this_month')
|
570
|
-
expect(year.superset_of?(month)).to be true
|
571
|
-
expect(year.superset_of?(year)).to be true
|
572
|
-
end
|
573
|
-
|
574
|
-
it 'should know if it\'s a proper superset of another period' do
|
575
|
-
year = Period.parse('this_year')
|
576
|
-
month = Period.parse('this_month')
|
577
|
-
expect(year.proper_superset_of?(month)).to be true
|
578
|
-
expect(year.proper_superset_of?(year)).to be false
|
579
|
-
end
|
580
|
-
|
581
|
-
it 'should know if it overlaps another period' do
|
582
|
-
period1 = Period.parse('2013')
|
583
|
-
period2 = Period.parse('2012-10', '2013-03')
|
584
|
-
period3 = Period.parse('2014')
|
585
|
-
expect(period1.overlaps?(period2)).to be true
|
586
|
-
expect(period2.overlaps?(period1)).to be true
|
587
|
-
expect(period1.overlaps?(period3)).to be false
|
588
|
-
end
|
589
|
-
|
590
|
-
it 'should know whether an array of periods have overlaps within it' do
|
591
|
-
months = (1..12).to_a.map { |k| Period.parse("2013-#{k}") }
|
592
|
-
year = Period.parse('2013')
|
593
|
-
expect(year.has_overlaps_within?(months)).to be false
|
594
|
-
months << Period.parse('2013-09-15', '2013-10-02')
|
595
|
-
expect(year.has_overlaps_within?(months)).to be true
|
596
|
-
end
|
597
|
-
|
598
|
-
it 'should know whether an array of periods span it' do
|
599
|
-
months = (1..12).to_a.map { |k| Period.parse("2013-#{k}") }
|
600
|
-
year = Period.parse('2013')
|
601
|
-
expect(year.spanned_by?(months)).to be true
|
602
|
-
|
603
|
-
months = (2..12).to_a.map { |k| Period.parse("2013-#{k}") }
|
604
|
-
expect(year.spanned_by?(months)).to be false
|
605
|
-
end
|
606
|
-
|
607
|
-
it 'should know its intersection with other period' do
|
608
|
-
year = Period.parse('this_year')
|
609
|
-
month = Period.parse('this_month')
|
610
|
-
expect(year & month).to eq(month)
|
611
|
-
expect(month & year).to eq(month)
|
612
|
-
# It should return a Period, not a Range
|
613
|
-
expect((month & year).class).to eq(Period)
|
614
|
-
end
|
615
|
-
|
616
|
-
it 'should alias narrow_to to intersection' do
|
617
|
-
period1 = Period.parse('2014')
|
618
|
-
period2 = Period.new('2014-06-01', '2015-02-28')
|
619
|
-
period3 = period1.narrow_to(period2)
|
620
|
-
expect(period3.first).to eq(period2.first)
|
621
|
-
expect(period3.last).to eq(period1.last)
|
622
|
-
end
|
623
|
-
|
624
|
-
it 'should return nil if no intersection' do
|
625
|
-
year = Period.parse('2014')
|
626
|
-
month = Period.parse('2013-05')
|
627
|
-
expect(year & month).to be_nil
|
628
|
-
end
|
629
|
-
|
630
|
-
it 'should know its union with other period' do
|
631
|
-
last_month = Period.parse('last_month')
|
632
|
-
month = Period.parse('this_month')
|
633
|
-
expect((last_month + month).first).to eq(last_month.first)
|
634
|
-
expect((last_month + month).last).to eq(month.last)
|
635
|
-
# It should return a Period, not a Range
|
636
|
-
expect((last_month + month).class).to eq(Period)
|
637
|
-
end
|
638
|
-
|
639
|
-
it 'should know its differences with other period' do
|
640
|
-
year = Period.parse('this_year')
|
641
|
-
month = Period.parse('this_month')
|
642
|
-
# Note: the difference operator returns an Array of Periods resulting
|
643
|
-
# from removing other from self.
|
644
|
-
expect((year - month).first)
|
645
|
-
.to eq(Period.new(year.first, month.first - 1.day))
|
646
|
-
expect((year - month).last)
|
647
|
-
.to eq(Period.new(month.last + 1.day, year.last))
|
648
|
-
# It should return an Array of Periods, not a Ranges
|
649
|
-
(year - month).each do |p|
|
650
|
-
expect(p.class).to eq(Period)
|
651
|
-
end
|
652
|
-
|
653
|
-
last_year = Period.parse('last_year')
|
654
|
-
month = Period.parse('this_month')
|
655
|
-
expect(last_year - month).to eq([last_year])
|
656
|
-
end
|
657
|
-
|
658
|
-
it 'should be able to find gaps from an array of periods' do
|
659
|
-
pp = Period.parse('2014-2Q')
|
660
|
-
periods = [
|
661
|
-
Period.parse('2013-11', '2013-12-20'),
|
662
|
-
Period.parse('2014-01', '2014-04-20'),
|
663
|
-
# Gap 2014-04-21 to 2014-04-30
|
664
|
-
Period.parse('2014-05', '2014-05-11'),
|
665
|
-
# Gap 2014-05-12 to 2014-05-24
|
666
|
-
Period.parse('2014-05-25', '2014-07-11'),
|
667
|
-
Period.parse('2014-09')
|
668
|
-
]
|
669
|
-
gaps = pp.gaps(periods)
|
670
|
-
expect(gaps.size).to eq(2)
|
671
|
-
expect(gaps.first.first).to eq(Date.parse('2014-04-21'))
|
672
|
-
expect(gaps.first.last).to eq(Date.parse('2014-04-30'))
|
673
|
-
expect(gaps.last.first).to eq(Date.parse('2014-05-12'))
|
674
|
-
expect(gaps.last.last).to eq(Date.parse('2014-05-24'))
|
675
|
-
end
|
676
|
-
end
|
677
|
-
end
|