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.
@@ -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