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