timeboss 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gem-push.yml +31 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +2 -1
  6. data/README.md +17 -2
  7. data/Rakefile +3 -1
  8. data/bin/tbsh +2 -2
  9. data/lib/tasks/calendars.rake +5 -5
  10. data/lib/tasks/timeboss.rake +2 -2
  11. data/lib/timeboss/calendar/day.rb +3 -2
  12. data/lib/timeboss/calendar/half.rb +2 -1
  13. data/lib/timeboss/calendar/month.rb +2 -1
  14. data/lib/timeboss/calendar/parser.rb +9 -8
  15. data/lib/timeboss/calendar/period.rb +9 -6
  16. data/lib/timeboss/calendar/quarter.rb +2 -1
  17. data/lib/timeboss/calendar/support/formatter.rb +5 -4
  18. data/lib/timeboss/calendar/support/has_fiscal_weeks.rb +17 -0
  19. data/lib/timeboss/calendar/support/has_iso_weeks.rb +30 -0
  20. data/lib/timeboss/calendar/support/month_basis.rb +1 -1
  21. data/lib/timeboss/calendar/support/monthly_unit.rb +8 -8
  22. data/lib/timeboss/calendar/support/navigable.rb +2 -1
  23. data/lib/timeboss/calendar/support/shiftable.rb +12 -11
  24. data/lib/timeboss/calendar/support/translatable.rb +3 -2
  25. data/lib/timeboss/calendar/support/unit.rb +20 -13
  26. data/lib/timeboss/calendar/waypoints/absolute.rb +4 -3
  27. data/lib/timeboss/calendar/waypoints/relative.rb +14 -13
  28. data/lib/timeboss/calendar/week.rb +3 -2
  29. data/lib/timeboss/calendar/year.rb +2 -1
  30. data/lib/timeboss/calendar.rb +8 -7
  31. data/lib/timeboss/calendars/broadcast.rb +10 -7
  32. data/lib/timeboss/calendars/gregorian.rb +4 -5
  33. data/lib/timeboss/calendars.rb +3 -2
  34. data/lib/timeboss/version.rb +2 -1
  35. data/lib/timeboss.rb +2 -0
  36. data/spec/{calendar → lib/timeboss/calendar}/day_spec.rb +14 -14
  37. data/spec/{calendar → lib/timeboss/calendar}/quarter_spec.rb +9 -9
  38. data/spec/lib/timeboss/calendar/support/monthly_unit_spec.rb +91 -0
  39. data/spec/{calendar → lib/timeboss/calendar}/support/unit_spec.rb +23 -22
  40. data/spec/{calendar → lib/timeboss/calendar}/week_spec.rb +20 -20
  41. data/spec/lib/timeboss/calendars/broadcast_spec.rb +796 -0
  42. data/spec/lib/timeboss/calendars/gregorian_spec.rb +793 -0
  43. data/spec/{calendars_spec.rb → lib/timeboss/calendars_spec.rb} +19 -19
  44. data/spec/spec_helper.rb +2 -2
  45. data/timeboss.gemspec +16 -14
  46. metadata +51 -20
  47. data/lib/timeboss/support/shellable.rb +0 -17
  48. data/spec/calendar/support/monthly_unit_spec.rb +0 -85
  49. data/spec/calendars/broadcast_spec.rb +0 -796
  50. data/spec/calendars/gregorian_spec.rb +0 -684
@@ -1,684 +0,0 @@
1
- module TimeBoss
2
- describe Calendars::Gregorian do
3
- let(:subject) { described_class.new }
4
-
5
- context 'days' do
6
- it 'can get today' do
7
- day = subject.today
8
- expect(day).to be_instance_of(TimeBoss::Calendar::Day)
9
- expect(day.start_date).to eq Date.today
10
- end
11
-
12
- it 'can get yesterday' do
13
- day = subject.yesterday
14
- expect(day).to be_instance_of(TimeBoss::Calendar::Day)
15
- expect(day.start_date).to eq Date.yesterday
16
- end
17
-
18
- it 'can get tomorrow' do
19
- day = subject.tomorrow
20
- expect(day).to be_instance_of(TimeBoss::Calendar::Day)
21
- expect(day.start_date).to eq Date.tomorrow
22
- end
23
- end
24
-
25
- context 'quarters' do
26
- describe '#quarter' do
27
- it 'knows 2017Q2' do
28
- quarter = subject.quarter(2017, 2)
29
- expect(quarter.name).to eq '2017Q2'
30
- expect(quarter.title).to eq 'Q2 2017'
31
- expect(quarter.year_index).to eq 2017
32
- expect(quarter.index).to eq 2
33
- expect(quarter.start_date).to eq Date.parse('2017-04-01')
34
- expect(quarter.end_date).to eq Date.parse('2017-06-30')
35
- expect(quarter.to_range).to eq quarter.start_date..quarter.end_date
36
- end
37
-
38
- it 'knows 2018Q3' do
39
- quarter = subject.quarter(2018, 3)
40
- expect(quarter.name).to eq '2018Q3'
41
- expect(quarter.title).to eq 'Q3 2018'
42
- expect(quarter.year_index).to eq 2018
43
- expect(quarter.index).to eq 3
44
- expect(quarter.start_date).to eq Date.parse('2018-07-01')
45
- expect(quarter.end_date).to eq Date.parse('2018-09-30')
46
- expect(quarter.to_range).to eq quarter.start_date..quarter.end_date
47
- end
48
-
49
- it 'knows 2019Q4' do
50
- quarter = subject.quarter(2019, 4)
51
- expect(quarter.year_index).to eq 2019
52
- expect(quarter.index).to eq 4
53
- expect(quarter.name).to eq '2019Q4'
54
- expect(quarter.title).to eq 'Q4 2019'
55
- expect(quarter.start_date).to eq Date.parse('2019-10-01')
56
- expect(quarter.end_date).to eq Date.parse('2019-12-31')
57
- expect(quarter.to_range).to eq quarter.start_date..quarter.end_date
58
- end
59
- end
60
-
61
- describe '#quarter_for' do
62
- it 'knows what quarter 2018-07-05 is in' do
63
- quarter = subject.quarter_for(Date.parse('2018-07-05'))
64
- expect(quarter.name).to eq '2018Q3'
65
- end
66
-
67
- it 'knows what quarter 2018-06-22 is in' do
68
- quarter = subject.quarter_for(Date.parse('2018-06-22'))
69
- expect(quarter.name).to eq '2018Q2'
70
- end
71
- end
72
-
73
- describe '#quarters_for' do
74
- it 'knows what quarters are in 2020' do
75
- basis = subject.year(2020)
76
- periods = subject.quarters_for(basis)
77
- expect(periods.map(&:name)).to eq %w[2020Q1 2020Q2 2020Q3 2020Q4]
78
- end
79
-
80
- it 'knows what quarter 2018M7 is in' do
81
- basis = subject.month(2018, 7)
82
- periods = subject.quarters_for(basis)
83
- expect(periods.map(&:name)).to eq %w[2018Q3]
84
- end
85
- end
86
-
87
- describe '#this_quarter' do
88
- let(:today) { double }
89
- let(:quarter) { double }
90
-
91
- it 'gets the quarter for today' do
92
- allow(Date).to receive(:today).and_return today
93
- expect(subject).to receive(:quarter_for).with(today).and_return quarter
94
- expect(subject.this_quarter).to eq quarter
95
- end
96
- end
97
-
98
- describe '#format' do
99
- let(:entry) { subject.quarter(2015, 3) }
100
-
101
- it 'can do a default format' do
102
- expect(entry.format).to eq '2015H2Q1'
103
- end
104
-
105
- it 'can format with only the quarter' do
106
- expect(entry.format(:quarter)).to eq '2015Q3'
107
- end
108
-
109
- it 'ignores stupidity' do
110
- expect(entry.format(:day, :banana)).to eq '2015Q3'
111
- end
112
- end
113
-
114
- context 'relative' do
115
- let(:this_quarter) { subject.quarter(2015, 3) }
116
- let(:quarter) { double }
117
- before(:each) { allow(subject).to receive(:this_quarter).and_return this_quarter }
118
-
119
- it 'can get the last quarter' do
120
- allow(this_quarter).to receive(:previous).and_return quarter
121
- expect(subject.last_quarter).to eq quarter
122
- end
123
-
124
- it 'can get the next quarter' do
125
- allow(this_quarter).to receive(:next).and_return quarter
126
- expect(subject.next_quarter).to eq quarter
127
- end
128
-
129
- it 'can get some number of quarters' do
130
- quarters = subject.quarters(5)
131
- expect(quarters.length).to eq 5
132
- quarters.each { |q| expect(q).to be_a TimeBoss::Calendar::Quarter }
133
- expect(quarters.map(&:name)).to eq ['2015Q3', '2015Q4', '2016Q1', '2016Q2', '2016Q3']
134
- end
135
-
136
- it 'can get a quarter ahead' do
137
- quarter = subject.quarters_ahead(4)
138
- expect(quarter).to be_a TimeBoss::Calendar::Quarter
139
- expect(quarter.name).to eq '2016Q3'
140
- end
141
-
142
- it 'can get some number of quarters back' do
143
- quarters = subject.quarters_back(5)
144
- expect(quarters.length).to eq 5
145
- quarters.each { |q| expect(q).to be_a TimeBoss::Calendar::Quarter }
146
- expect(quarters.map(&:name)).to eq ['2014Q3', '2014Q4', '2015Q1', '2015Q2', '2015Q3']
147
- end
148
-
149
- it 'can get a quarter ago' do
150
- quarter = subject.quarters_ago(4)
151
- expect(quarter).to be_a TimeBoss::Calendar::Quarter
152
- expect(quarter.name).to eq '2014Q3'
153
- end
154
- end
155
- end
156
-
157
- context 'months' do
158
- describe '#month' do
159
- it 'knows 2017M2' do
160
- month = subject.month(2017, 2)
161
- expect(month.name).to eq '2017M2'
162
- expect(month.title).to eq 'February 2017'
163
- expect(month.year_index).to eq 2017
164
- expect(month.index).to eq 2
165
- expect(month.start_date).to eq Date.parse('2017-02-01')
166
- expect(month.end_date).to eq Date.parse('2017-02-28')
167
- expect(month.to_range).to eq month.start_date..month.end_date
168
- end
169
-
170
- it 'knows 2018M3' do
171
- month = subject.month(2018, 3)
172
- expect(month.name).to eq '2018M3'
173
- expect(month.title).to eq 'March 2018'
174
- expect(month.year_index).to eq 2018
175
- expect(month.index).to eq 3
176
- expect(month.start_date).to eq Date.parse('2018-03-01')
177
- expect(month.end_date).to eq Date.parse('2018-03-31')
178
- expect(month.to_range).to eq month.start_date..month.end_date
179
- end
180
-
181
- it 'knows 2019M11' do
182
- month = subject.month(2019, 11)
183
- expect(month.year_index).to eq 2019
184
- expect(month.index).to eq 11
185
- expect(month.name).to eq '2019M11'
186
- expect(month.title).to eq 'November 2019'
187
- expect(month.start_date).to eq Date.parse('2019-11-01')
188
- expect(month.end_date).to eq Date.parse('2019-11-30')
189
- expect(month.to_range).to eq month.start_date..month.end_date
190
- end
191
- end
192
-
193
- describe '#month_for' do
194
- it 'knows what month 2018-07-05 is in' do
195
- month = subject.month_for(Date.parse('2018-07-05'))
196
- expect(month.name).to eq '2018M7'
197
- end
198
-
199
- it 'knows what month 2018-06-22 is in' do
200
- month = subject.month_for(Date.parse('2018-06-22'))
201
- expect(month.name).to eq '2018M6'
202
- end
203
- end
204
-
205
- describe '#months_for' do
206
- it 'knows what months are in 2020' do
207
- basis = subject.year(2020)
208
- periods = subject.months_for(basis)
209
- expect(periods.map(&:name)).to eq %w[2020M1 2020M2 2020M3 2020M4 2020M5 2020M6 2020M7 2020M8 2020M9 2020M10 2020M11 2020M12]
210
- end
211
-
212
- it 'knows what months are in 2018Q2' do
213
- basis = subject.parse('2018Q2')
214
- periods = subject.months_for(basis)
215
- expect(periods.map(&:name)).to eq %w[2018M4 2018M5 2018M6]
216
- end
217
-
218
- it 'knows what month 2019-12-12 is in' do
219
- basis = subject.parse('2019-12-12')
220
- periods = subject.months_for(basis)
221
- expect(periods.map(&:name)).to eq %w[2019M12]
222
- end
223
- end
224
-
225
- describe '#this_month' do
226
- let(:today) { double }
227
- let(:month) { double }
228
-
229
- it 'gets the month for today' do
230
- allow(Date).to receive(:today).and_return today
231
- expect(subject).to receive(:month_for).with(today).and_return month
232
- expect(subject.this_month).to eq month
233
- end
234
- end
235
-
236
- describe '#format' do
237
- let(:entry) { subject.month(2015, 8) }
238
-
239
- it 'can do a default format' do
240
- expect(entry.format).to eq '2015H2Q1M2'
241
- end
242
-
243
- it 'can format with only the quarter' do
244
- expect(entry.format(:quarter)).to eq '2015Q3M2'
245
- end
246
-
247
- it 'ignores stupidity' do
248
- expect(entry.format(:banana, :half, :week)).to eq '2015H2M2'
249
- end
250
- end
251
-
252
- context 'relative' do
253
- let(:this_month) { subject.month(2015, 3) }
254
- let(:month) { double }
255
- before(:each) { allow(subject).to receive(:this_month).and_return this_month }
256
-
257
- it 'can get the last month' do
258
- allow(this_month).to receive(:previous).and_return month
259
- expect(subject.last_month).to eq month
260
- end
261
-
262
- it 'can get the next month' do
263
- allow(this_month).to receive(:next).and_return month
264
- expect(subject.next_month).to eq month
265
- end
266
-
267
- it 'can get some number of months' do
268
- months = subject.months(5)
269
- expect(months.length).to eq 5
270
- months.each { |m| expect(m).to be_a TimeBoss::Calendar::Month }
271
- expect(months.map(&:name)).to eq ['2015M3', '2015M4', '2015M5', '2015M6', '2015M7']
272
- end
273
-
274
- it 'can get a month ahead' do
275
- month = subject.months_ahead(4)
276
- expect(month).to be_a TimeBoss::Calendar::Month
277
- expect(month.name).to eq '2015M7'
278
- end
279
-
280
- it 'can get some number of months back' do
281
- months = subject.months_back(5)
282
- expect(months.length).to eq 5
283
- months.each { |m| expect(m).to be_a TimeBoss::Calendar::Month }
284
- expect(months.map(&:name)).to eq ['2014M11', '2014M12', '2015M1', '2015M2', '2015M3']
285
- end
286
-
287
- it 'can get a month ago' do
288
- month = subject.months_ago(4)
289
- expect(month).to be_a TimeBoss::Calendar::Month
290
- expect(month.name).to eq '2014M11'
291
- end
292
- end
293
- end
294
-
295
- context 'weeks' do
296
- it 'is uninterested in weeks' do
297
- expect { subject.this_week }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
298
- expect { subject.parse('2020W3') }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
299
- expect { subject.weeks_ago(2) }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
300
- end
301
- end
302
-
303
- context 'years' do
304
- describe '#year' do
305
- it 'knows 2016' do
306
- year = subject.year(2016)
307
- expect(year.name).to eq '2016'
308
- expect(year.title).to eq '2016'
309
- expect(year.year_index).to eq 2016
310
- expect(year.index).to eq 1
311
- expect(year.start_date).to eq Date.parse('2016-01-01')
312
- expect(year.end_date).to eq Date.parse('2016-12-31')
313
- expect(year.to_range).to eq year.start_date..year.end_date
314
- end
315
-
316
- it 'knows 2017' do
317
- year = subject.year(2017)
318
- expect(year.name).to eq '2017'
319
- expect(year.title).to eq '2017'
320
- expect(year.year_index).to eq 2017
321
- expect(year.index).to eq 1
322
- expect(year.start_date).to eq Date.parse('2017-01-01')
323
- expect(year.end_date).to eq Date.parse('2017-12-31')
324
- expect(year.to_range).to eq year.start_date..year.end_date
325
- end
326
-
327
- it 'knows 2018' do
328
- year = subject.year(2018)
329
- expect(year.name).to eq '2018'
330
- expect(year.title).to eq '2018'
331
- expect(year.year_index).to eq 2018
332
- expect(year.index).to eq 1
333
- expect(year.start_date).to eq Date.parse('2018-01-01')
334
- expect(year.end_date).to eq Date.parse('2018-12-31')
335
- expect(year.to_range).to eq year.start_date..year.end_date
336
- end
337
- end
338
-
339
- describe '#year_for' do
340
- it 'knows what year 2018-04-07 is in' do
341
- year = subject.year_for(Date.parse('2018-04-07'))
342
- expect(year.name).to eq '2018'
343
- end
344
-
345
- it 'knows what year 2016-12-27 is in' do
346
- year = subject.year_for(Date.parse('2016-12-27'))
347
- expect(year.name).to eq '2016'
348
- end
349
- end
350
-
351
- describe '#years_for' do
352
- it 'knows what years are in 2020 (duh)' do
353
- basis = subject.year(2020)
354
- periods = subject.years_for(basis)
355
- expect(periods.map(&:name)).to eq %w[2020]
356
- end
357
-
358
- it 'knows what year 2018Q2 is in' do
359
- basis = subject.parse('2018Q2')
360
- periods = subject.years_for(basis)
361
- expect(periods.map(&:name)).to eq %w[2018]
362
- end
363
-
364
- it 'knows what years 2019-12-12 is in' do
365
- basis = subject.parse('2019-12-12')
366
- periods = subject.years_for(basis)
367
- expect(periods.map(&:name)).to eq %w[2019]
368
- end
369
- end
370
-
371
- describe '#this_year' do
372
- let(:today) { double }
373
- let(:year) { double }
374
-
375
- it 'gets the year for today' do
376
- allow(Date).to receive(:today).and_return today
377
- expect(subject).to receive(:year_for).with(today).and_return year
378
- expect(subject.this_year).to eq year
379
- end
380
- end
381
-
382
- describe '#format' do
383
- let(:entry) { subject.parse('2020M8') }
384
-
385
- it 'can do a default format' do
386
- expect(entry.format).to eq '2020H2Q1M2'
387
- end
388
-
389
- it 'can format with only the quarter' do
390
- expect(entry.format(:quarter)).to eq '2020Q3M2'
391
- end
392
-
393
- context 'with days' do
394
- let(:entry) { subject.parse('2020D201') }
395
-
396
- it 'can do a default format' do
397
- expect(entry.format).to eq '2020H2Q1M1D19'
398
- end
399
- end
400
- end
401
-
402
- context 'relative' do
403
- let(:this_year) { subject.year(2015) }
404
- let(:year) { double }
405
- before(:each) { allow(subject).to receive(:this_year).and_return this_year }
406
-
407
- it 'can get the last year' do
408
- allow(this_year).to receive(:previous).and_return year
409
- expect(subject.last_year).to eq year
410
- end
411
-
412
- it 'can get the next year' do
413
- allow(this_year).to receive(:next).and_return year
414
- expect(subject.next_year).to eq year
415
- end
416
-
417
- it 'can get some number of years' do
418
- years = subject.years(5)
419
- expect(years.length).to eq 5
420
- years.each { |y| expect(y).to be_a TimeBoss::Calendar::Year }
421
- expect(years.map(&:name)).to eq ['2015', '2016', '2017', '2018', '2019']
422
- end
423
-
424
- it 'can get some number of years back' do
425
- years = subject.years_back(5)
426
- expect(years.length).to eq 5
427
- years.each { |y| expect(y).to be_a TimeBoss::Calendar::Year }
428
- expect(years.map(&:name)).to eq ['2011', '2012', '2013', '2014', '2015']
429
- end
430
- end
431
- end
432
-
433
- describe '#parse' do
434
- it 'can parse a year' do
435
- date = subject.parse('2018')
436
- expect(date).to be_a TimeBoss::Calendar::Year
437
- expect(date.name).to eq '2018'
438
- end
439
-
440
- it 'can parse a quarter identifier' do
441
- date = subject.parse('2017Q2')
442
- expect(date).to be_a TimeBoss::Calendar::Quarter
443
- expect(date.name).to eq '2017Q2'
444
- end
445
-
446
- it 'can parse a month identifier' do
447
- date = subject.parse('2017M4')
448
- expect(date).to be_a TimeBoss::Calendar::Month
449
- expect(date.name).to eq '2017M4'
450
- end
451
-
452
- it 'cannot parse a week within a year' do
453
- expect { subject.parse('2018W37') }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
454
- end
455
-
456
- it 'cannot parse a week within a quarter' do
457
- expect { subject.parse('2017Q2W2') }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
458
- end
459
-
460
- it 'cannot parse a week within a month' do
461
- expect { subject.parse('2017M4W1') }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
462
- end
463
-
464
- it 'can parse a date' do
465
- date = subject.parse('2017-04-08')
466
- expect(date).to be_a TimeBoss::Calendar::Day
467
- expect(date.start_date).to eq Date.parse('2017-04-08')
468
- expect(date.end_date).to eq Date.parse('2017-04-08')
469
- end
470
-
471
- it 'can parse an aesthetically displeasing date' do
472
- date = subject.parse('20170408')
473
- expect(date).to be_a TimeBoss::Calendar::Day
474
- expect(date.start_date).to eq Date.parse('2017-04-08')
475
- expect(date.end_date).to eq Date.parse('2017-04-08')
476
- end
477
-
478
- it 'gives you nothing if you give it nothing' do
479
- expect(subject.parse(nil)).to be nil
480
- expect(subject.parse('')).to be nil
481
- end
482
- end
483
-
484
- context 'expressions' do
485
- it 'can parse waypoints' do
486
- result = subject.parse('this_year')
487
- expect(result).to be_a TimeBoss::Calendar::Year
488
- expect(result).to be_current
489
- end
490
-
491
- it 'can parse mathematic expressions' do
492
- result = subject.parse('this_month + 2')
493
- expect(result).to be_a TimeBoss::Calendar::Month
494
- expect(result).to eq subject.months_ahead(2)
495
- end
496
-
497
- context 'ranges' do
498
- before(:each) { allow(subject).to receive(:this_year).and_return subject.year(2018) }
499
- let(:result) { subject.parse('this_year-2 .. this_year') }
500
-
501
- it 'can parse range expressions' do
502
- expect(result).to be_a TimeBoss::Calendar::Period
503
- expect(result.to_s).to eq "2016: 2016-01-01 thru 2016-12-31 .. 2018: 2018-01-01 thru 2018-12-31"
504
- end
505
-
506
- it 'can get an overall start date for a range' do
507
- expect(result.start_date).to eq Date.parse('2016-01-01')
508
- end
509
-
510
- it 'can get an overall end date for a range' do
511
- expect(result.end_date).to eq Date.parse('2018-12-31')
512
- end
513
-
514
- context 'sub-periods' do
515
- it 'can get the months included in a range' do
516
- entries = result.months
517
- entries.each { |e| expect(e).to be_a TimeBoss::Calendar::Month }
518
- expect(entries.map(&:name)).to include('2016M1', '2016M9', '2017M3', '2018M12')
519
- end
520
-
521
- it 'cannot get the weeks included in a range' do
522
- expect { result.weeks }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
523
- end
524
-
525
- it 'can get the days included in a range' do
526
- entries = result.days
527
- entries.each { |e| expect(e).to be_a TimeBoss::Calendar::Day }
528
- expect(entries.map(&:name)).to include('2016-01-01', '2016-05-12', '2017-09-22', '2018-12-31')
529
- end
530
- end
531
- end
532
- end
533
-
534
- context 'shifting' do
535
- context 'from day' do
536
- let(:basis) { subject.parse('2020-04-21') }
537
-
538
- it 'cannot shift to a different week' do
539
- expect { basis.last_week }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
540
- expect { basis.in_week }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
541
- end
542
-
543
- it 'can shift to a different quarter' do
544
- allow(subject).to receive(:this_quarter).and_return subject.parse('2020Q3')
545
- result = basis.quarters_ago(2)
546
- expect(result).to be_a TimeBoss::Calendar::Day
547
- expect(result.to_s).to eq '2020-01-21'
548
- expect(basis.in_quarter).to eq 21
549
- end
550
-
551
- it 'can shift to a different year' do
552
- allow(subject).to receive(:this_year).and_return subject.parse('2019')
553
- result = basis.years_ahead(3)
554
- expect(result).to be_a TimeBoss::Calendar::Day
555
- expect(result.to_s).to eq '2022-04-22'
556
- expect(basis.in_year).to eq 112
557
- end
558
- end
559
-
560
- context 'from month' do
561
- let(:basis) { subject.parse('2017M4') }
562
-
563
- it 'cannot shift to a different week' do
564
- expect { basis.last_week }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
565
- expect { basis.in_week }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
566
- end
567
-
568
- it 'can shift to a different year' do
569
- allow(subject).to receive(:this_year).and_return subject.parse('2020')
570
- result = basis.years_ahead(4)
571
- expect(result).to be_a TimeBoss::Calendar::Month
572
- expect(result.name).to eq '2024M4'
573
- expect(basis.in_year).to eq 4
574
- end
575
- end
576
-
577
- context 'from quarter' do
578
- let(:basis) { subject.parse('2018Q2') }
579
-
580
- it 'cannot shift to a different month' do
581
- expect(basis.months_ago(4)).to be nil
582
- expect(basis.in_month).to be nil
583
- end
584
-
585
- it 'can shift to a different half' do
586
- allow(subject).to receive(:this_half).and_return subject.parse('2020H1')
587
- result = basis.last_half
588
- expect(result).to be_a TimeBoss::Calendar::Quarter
589
- expect(result.name).to eq '2019Q4'
590
- expect(basis.in_half).to eq 2
591
- end
592
- end
593
-
594
- context 'from year' do
595
- let(:basis) { subject.parse('2014') }
596
-
597
- it 'cannot shift to a different half' do
598
- expect(basis.next_half).to be nil
599
- expect(basis.in_half).to be nil
600
- end
601
-
602
- it 'shifts to a different year, but knows how useless that is' do
603
- allow(subject).to receive(:this_year).and_return subject.parse('2020')
604
- result = basis.years_ago(2)
605
- expect(result).to be_a TimeBoss::Calendar::Year
606
- expect(result.name).to eq '2018'
607
- expect(basis.in_year).to eq 1
608
- end
609
- end
610
- end
611
-
612
- context 'units' do
613
- let(:calendar) { described_class.new }
614
-
615
- context 'day' do
616
- let(:start_date) { Date.parse('2019-09-30') }
617
- let(:subject) { TimeBoss::Calendar::Day.new(calendar, start_date) }
618
-
619
- context 'links' do
620
- it 'can get its previous' do
621
- expect(subject.previous.name).to eq '2019-09-29'
622
- end
623
-
624
- it 'can get its next' do
625
- expect(subject.next.name).to eq '2019-10-01'
626
- end
627
-
628
- it 'can offset backwards' do
629
- expect(subject.offset(-3).name).to eq '2019-09-27'
630
- expect((subject - 3).name).to eq '2019-09-27'
631
- end
632
-
633
- it 'can offset forwards' do
634
- expect(subject.offset(4).name).to eq '2019-10-04'
635
- expect((subject + 4).name).to eq '2019-10-04'
636
- end
637
- end
638
- end
639
-
640
- context 'quarter' do
641
- let(:start_date) { Date.parse('2019-10-01') }
642
- let(:end_date) { Date.parse('2019-12-31') }
643
- let(:subject) { TimeBoss::Calendar::Quarter.new(calendar, 2019, 4, start_date, end_date) }
644
-
645
- context 'links' do
646
- it 'can get the next quarter' do
647
- quarter = subject.next
648
- expect(quarter.to_s).to include('2020Q1', '2020-01-01', '2020-03-31')
649
- end
650
-
651
- it 'can get the next next quarter' do
652
- quarter = subject.next.next
653
- expect(quarter.to_s).to include('2020Q2', '2020-04-01', '2020-06-30')
654
- end
655
-
656
- it 'can get the next next previous quarter' do
657
- quarter = subject.next.next.previous
658
- expect(quarter.to_s).to include('2020Q1', '2020-01-01', '2020-03-31')
659
- end
660
-
661
- it 'can get the next previous quarter' do
662
- quarter = subject.next.previous
663
- expect(quarter.to_s).to eq subject.to_s
664
- end
665
-
666
- it 'can get the previous quarter' do
667
- quarter = subject.previous
668
- expect(quarter.to_s).to include('2019Q3', '2019-07-01', '2019-09-30')
669
- end
670
-
671
- it 'can offset backwards' do
672
- expect(subject.offset(-4).name).to eq '2018Q4'
673
- expect((subject - 4).name).to eq '2018Q4'
674
- end
675
-
676
- it 'can offset forwards' do
677
- expect(subject.offset(2).name).to eq '2020Q2'
678
- expect((subject + 2).name).to eq '2020Q2'
679
- end
680
- end
681
- end
682
- end
683
- end
684
- end