timeboss 0.3.0 → 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 +4 -4
- data/.github/workflows/gem-push.yml +31 -0
- data/.github/workflows/ruby.yml +35 -0
- data/.travis.yml +3 -2
- data/Gemfile +2 -1
- data/README.md +17 -7
- data/Rakefile +3 -1
- data/bin/tbsh +2 -2
- data/lib/tasks/calendars.rake +5 -5
- 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 +88 -12
- 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 +18 -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 +16 -14
- metadata +33 -5
- data/lib/timeboss/support/shellable.rb +0 -17
@@ -2,28 +2,28 @@ module TimeBoss
|
|
2
2
|
class Calendar
|
3
3
|
describe Quarter do
|
4
4
|
let(:calendar) { instance_double(TimeBoss::Calendar) }
|
5
|
-
let(:start_date) { Date.parse(
|
6
|
-
let(:end_date) { Date.parse(
|
5
|
+
let(:start_date) { Date.parse("2019-09-30") }
|
6
|
+
let(:end_date) { Date.parse("2019-12-29") }
|
7
7
|
let(:subject) { described_class.new(calendar, 2019, 4, start_date, end_date) }
|
8
8
|
|
9
|
-
it
|
10
|
-
expect(subject.name).to eq
|
9
|
+
it "knows its stuff" do
|
10
|
+
expect(subject.name).to eq "2019Q4"
|
11
11
|
expect(subject.start_date).to eq start_date
|
12
12
|
expect(subject.end_date).to eq end_date
|
13
13
|
expect(subject.to_range).to eq start_date..end_date
|
14
14
|
end
|
15
15
|
|
16
|
-
it
|
17
|
-
expect(subject.to_s).to include(
|
16
|
+
it "can stringify itself" do
|
17
|
+
expect(subject.to_s).to include("2019Q4", start_date.to_s, end_date.to_s)
|
18
18
|
end
|
19
19
|
|
20
|
-
describe
|
21
|
-
it
|
20
|
+
describe "#current?" do
|
21
|
+
it "knows when it is" do
|
22
22
|
allow(Date).to receive(:today).and_return start_date
|
23
23
|
expect(subject).to be_current
|
24
24
|
end
|
25
25
|
|
26
|
-
it
|
26
|
+
it "knows when it is not" do
|
27
27
|
expect(subject).not_to be_current
|
28
28
|
end
|
29
29
|
end
|
@@ -1,80 +1,81 @@
|
|
1
1
|
module TimeBoss
|
2
2
|
class Calendar
|
3
3
|
module Support
|
4
|
-
|
5
|
-
|
6
|
-
NUM_MONTHS = 2
|
4
|
+
class TestMonthBasedChunk < MonthlyUnit
|
5
|
+
NUM_MONTHS = 2
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
def name
|
8
|
+
"#{year_index}C#{index}"
|
11
9
|
end
|
12
|
-
|
10
|
+
end
|
11
|
+
|
12
|
+
describe MonthlyUnit do
|
13
|
+
let(:described_class) { TestMonthBasedChunk }
|
13
14
|
let(:calendar) { double }
|
14
|
-
let(:start_date) { Date.parse(
|
15
|
-
let(:end_date) { Date.parse(
|
15
|
+
let(:start_date) { Date.parse("2018-06-25") }
|
16
|
+
let(:end_date) { Date.parse("2018-08-26") }
|
16
17
|
let(:subject) { described_class.new(calendar, 2018, 4, start_date, end_date) }
|
17
18
|
|
18
|
-
it
|
19
|
+
it "knows its stuff" do
|
19
20
|
expect(subject.start_date).to eq start_date
|
20
21
|
expect(subject.end_date).to eq end_date
|
21
22
|
expect(subject.to_range).to eq start_date..end_date
|
22
23
|
end
|
23
24
|
|
24
|
-
it
|
25
|
+
it "can stringify itself" do
|
25
26
|
expect(subject.to_s).to eq "2018C4: 2018-06-25 thru 2018-08-26"
|
26
27
|
end
|
27
28
|
|
28
|
-
describe
|
29
|
-
let(:base) { double(start_date: Date.parse(
|
29
|
+
describe "#weeks" do
|
30
|
+
let(:base) { double(start_date: Date.parse("2018-01-01"), end_date: Date.parse("2018-12-30")) }
|
30
31
|
before(:each) { allow(calendar).to receive(:year).with(2018).and_return base }
|
31
32
|
|
32
|
-
it
|
33
|
+
it "can get the relevant weeks for the period" do
|
33
34
|
allow(calendar).to receive(:supports_weeks?).and_return true
|
34
35
|
result = subject.weeks
|
35
36
|
result.each { |w| expect(w).to be_instance_of TimeBoss::Calendar::Week }
|
36
37
|
expect(result.map { |w| w.start_date.to_s }).to eq [
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
38
|
+
"2018-06-25",
|
39
|
+
"2018-07-02",
|
40
|
+
"2018-07-09",
|
41
|
+
"2018-07-16",
|
42
|
+
"2018-07-23",
|
43
|
+
"2018-07-30",
|
44
|
+
"2018-08-06",
|
45
|
+
"2018-08-13",
|
46
|
+
"2018-08-20"
|
46
47
|
]
|
47
48
|
end
|
48
49
|
|
49
|
-
it
|
50
|
+
it "blows up when weeks are not supported" do
|
50
51
|
allow(calendar).to receive(:supports_weeks?).and_return false
|
51
52
|
expect { subject.weeks }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
|
-
context
|
56
|
+
context "navigation" do
|
56
57
|
let(:result) { double }
|
57
58
|
|
58
|
-
describe
|
59
|
-
it
|
60
|
-
expect(calendar).to receive(:
|
59
|
+
describe "#previous" do
|
60
|
+
it "moves easily within itself" do
|
61
|
+
expect(calendar).to receive(:test_month_based_chunk).with(48, 3).and_return result
|
61
62
|
expect(described_class.new(calendar, 48, 4, nil, nil).previous).to eq result
|
62
63
|
end
|
63
64
|
|
64
|
-
it
|
65
|
-
expect(calendar).to receive(:
|
65
|
+
it "flips to the previous container" do
|
66
|
+
expect(calendar).to receive(:test_month_based_chunk).with(47, 6).and_return result
|
66
67
|
expect(described_class.new(calendar, 48, 1, nil, nil).previous).to eq result
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
70
|
-
describe
|
71
|
-
it
|
72
|
-
expect(calendar).to receive(:
|
71
|
+
describe "#next" do
|
72
|
+
it "moves easily within itself" do
|
73
|
+
expect(calendar).to receive(:test_month_based_chunk).with(48, 3).and_return result
|
73
74
|
expect(described_class.new(calendar, 48, 2, nil, nil).next).to eq result
|
74
75
|
end
|
75
76
|
|
76
|
-
it
|
77
|
-
expect(calendar).to receive(:
|
77
|
+
it "flips to the previous container" do
|
78
|
+
expect(calendar).to receive(:test_month_based_chunk).with(48, 1).and_return result
|
78
79
|
expect(described_class.new(calendar, 47, 6, nil, nil).next).to eq result
|
79
80
|
end
|
80
81
|
end
|
@@ -1,33 +1,34 @@
|
|
1
1
|
module TimeBoss
|
2
2
|
class Calendar
|
3
3
|
module Support
|
4
|
+
class TestChunkUnit < Unit
|
5
|
+
end
|
6
|
+
|
4
7
|
describe Unit do
|
5
|
-
|
6
|
-
end
|
7
|
-
let(:described_class) { ChunkUnit }
|
8
|
+
let(:described_class) { TestChunkUnit }
|
8
9
|
let(:calendar) { double }
|
9
|
-
let(:start_date) { Date.parse(
|
10
|
-
let(:end_date) { Date.parse(
|
10
|
+
let(:start_date) { Date.parse("2018-06-25") }
|
11
|
+
let(:end_date) { Date.parse("2018-08-26") }
|
11
12
|
let(:subject) { described_class.new(calendar, start_date, end_date) }
|
12
13
|
|
13
|
-
it
|
14
|
+
it "knows its stuff" do
|
14
15
|
expect(subject.start_date).to eq start_date
|
15
16
|
expect(subject.end_date).to eq end_date
|
16
17
|
expect(subject.to_range).to eq start_date..end_date
|
17
18
|
end
|
18
19
|
|
19
|
-
describe
|
20
|
-
it
|
20
|
+
describe "#current?" do
|
21
|
+
it "is not current right now" do
|
21
22
|
expect(subject).not_to be_current
|
22
23
|
end
|
23
24
|
|
24
|
-
it
|
25
|
+
it "is current when today falls in the middle" do
|
25
26
|
allow(Date).to receive(:today).and_return start_date + 3.days
|
26
27
|
expect(subject).to be_current
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
context
|
31
|
+
context "periods" do
|
31
32
|
before(:each) do
|
32
33
|
allow(calendar).to receive(:days_for).with(subject).and_return %w[D1 D2 D3 D4 D5 D6 D7 D8]
|
33
34
|
allow(calendar).to receive(:weeks_for).with(subject).and_return %w[W1 W2 W3 W4]
|
@@ -37,49 +38,49 @@ module TimeBoss
|
|
37
38
|
allow(calendar).to receive(:years_for).with(subject).and_return %w[Y1]
|
38
39
|
end
|
39
40
|
|
40
|
-
it
|
41
|
+
it "knows about its days" do
|
41
42
|
expect(subject.days).to eq %w[D1 D2 D3 D4 D5 D6 D7 D8]
|
42
43
|
expect(subject.day).to be nil
|
43
44
|
end
|
44
45
|
|
45
|
-
it
|
46
|
+
it "knows about its weeks" do
|
46
47
|
expect(subject.weeks).to eq %w[W1 W2 W3 W4]
|
47
48
|
expect(subject.week).to be nil
|
48
49
|
end
|
49
50
|
|
50
|
-
it
|
51
|
+
it "knows about its months" do
|
51
52
|
expect(subject.months).to eq %w[M1 M2 M3]
|
52
53
|
expect(subject.month).to be nil
|
53
54
|
end
|
54
55
|
|
55
|
-
it
|
56
|
+
it "knows about its quarters" do
|
56
57
|
expect(subject.quarters).to eq %w[Q1 Q2]
|
57
58
|
expect(subject.quarter).to be nil
|
58
59
|
end
|
59
60
|
|
60
|
-
it
|
61
|
+
it "knows about its halves" do
|
61
62
|
expect(subject.halves).to eq %w[H1]
|
62
|
-
expect(subject.half).to eq
|
63
|
+
expect(subject.half).to eq "H1"
|
63
64
|
end
|
64
65
|
|
65
|
-
it
|
66
|
+
it "knows about its years" do
|
66
67
|
expect(subject.years).to eq %w[Y1]
|
67
|
-
expect(subject.year).to eq
|
68
|
+
expect(subject.year).to eq "Y1"
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
context
|
72
|
+
context "navigation" do
|
72
73
|
let(:result) { double }
|
73
74
|
|
74
|
-
describe
|
75
|
+
describe "#offset" do
|
75
76
|
end
|
76
77
|
|
77
|
-
it
|
78
|
+
it "can increment" do
|
78
79
|
expect(subject).to receive(:offset).with(7).and_return result
|
79
80
|
expect(subject + 7).to eq result
|
80
81
|
end
|
81
82
|
|
82
|
-
it
|
83
|
+
it "can decrement" do
|
83
84
|
expect(subject).to receive(:offset).with(-23).and_return result
|
84
85
|
expect(subject - 23).to eq result
|
85
86
|
end
|
data/spec/calendar/week_spec.rb
CHANGED
@@ -2,8 +2,8 @@ module TimeBoss
|
|
2
2
|
class Calendar
|
3
3
|
describe Week do
|
4
4
|
let(:calendar) { instance_double(TimeBoss::Calendar, supports_weeks?: true) }
|
5
|
-
let(:start_date) { Date.parse(
|
6
|
-
let(:end_date) { Date.parse(
|
5
|
+
let(:start_date) { Date.parse("2048-04-06") }
|
6
|
+
let(:end_date) { Date.parse("2048-04-12") }
|
7
7
|
let(:subject) { described_class.new(calendar, start_date, end_date) }
|
8
8
|
|
9
9
|
it "doesn't even exist if its calendar doesn't support weeks" do
|
@@ -11,65 +11,65 @@ module TimeBoss
|
|
11
11
|
expect { subject }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it "knows its stuff" do
|
15
15
|
expect(subject.start_date).to eq start_date
|
16
16
|
expect(subject.end_date).to eq end_date
|
17
17
|
expect(subject.to_range).to eq start_date..end_date
|
18
18
|
end
|
19
19
|
|
20
|
-
it
|
20
|
+
it "knows its title" do
|
21
21
|
expect(subject.title).to eq "Week of April 6, 2048"
|
22
22
|
end
|
23
23
|
|
24
|
-
describe
|
25
|
-
it
|
24
|
+
describe "#current?" do
|
25
|
+
it "knows when it is" do
|
26
26
|
allow(Date).to receive(:today).and_return start_date
|
27
27
|
expect(subject).to be_current
|
28
28
|
end
|
29
29
|
|
30
|
-
it
|
30
|
+
it "knows when it is not" do
|
31
31
|
expect(subject).not_to be_current
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
context
|
35
|
+
context "navigation" do
|
36
36
|
let(:calendar) { TimeBoss::Calendars::Broadcast.new }
|
37
37
|
|
38
|
-
describe
|
39
|
-
it
|
38
|
+
describe "#previous" do
|
39
|
+
it "can back up simply" do
|
40
40
|
result = subject.previous
|
41
41
|
expect(result).to be_a described_class
|
42
42
|
expect(result.to_s).to eq "2048W14: 2048-03-30 thru 2048-04-05"
|
43
43
|
end
|
44
44
|
|
45
|
-
it
|
46
|
-
result = described_class.new(calendar, Date.parse(
|
45
|
+
it "can wrap to the previous 52-week year" do
|
46
|
+
result = described_class.new(calendar, Date.parse("2021-12-27"), Date.parse("2022-01-02")).previous
|
47
47
|
expect(result).to be_a described_class
|
48
48
|
expect(result.to_s).to eq "2021W52: 2021-12-20 thru 2021-12-26"
|
49
49
|
end
|
50
50
|
|
51
|
-
it
|
52
|
-
result = described_class.new(calendar, Date.parse(
|
51
|
+
it "can wrap to the previous 53-week year" do
|
52
|
+
result = described_class.new(calendar, Date.parse("2024-01-01"), Date.parse("2024-01-07")).previous
|
53
53
|
expect(result).to be_a described_class
|
54
54
|
expect(result.to_s).to eq "2023W53: 2023-12-25 thru 2023-12-31"
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
describe
|
59
|
-
it
|
58
|
+
describe "#next" do
|
59
|
+
it "can move forward simply" do
|
60
60
|
result = subject.next
|
61
61
|
expect(result).to be_a described_class
|
62
62
|
expect(result.to_s).to eq "2048W16: 2048-04-13 thru 2048-04-19"
|
63
63
|
end
|
64
64
|
|
65
|
-
it
|
66
|
-
result = described_class.new(calendar, Date.parse(
|
65
|
+
it "can wrap from week 52 to the next year" do
|
66
|
+
result = described_class.new(calendar, Date.parse("2021-12-20"), Date.parse("2021-12-26")).next
|
67
67
|
expect(result).to be_a described_class
|
68
68
|
expect(result.to_s).to eq "2022W1: 2021-12-27 thru 2022-01-02"
|
69
69
|
end
|
70
70
|
|
71
|
-
it
|
72
|
-
result = described_class.new(calendar, Date.parse(
|
71
|
+
it "can wrap from week 53 to the next year" do
|
72
|
+
result = described_class.new(calendar, Date.parse("2023-12-25"), Date.parse("2023-12-31")).next
|
73
73
|
expect(result).to be_a described_class
|
74
74
|
expect(result.to_s).to eq "2024W1: 2024-01-01 thru 2024-01-07"
|
75
75
|
end
|
@@ -2,792 +2,792 @@ module TimeBoss
|
|
2
2
|
describe Calendars::Broadcast 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-03-27")
|
34
|
+
expect(quarter.end_date).to eq Date.parse("2017-06-25")
|
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-06-25")
|
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-09-30")
|
56
|
+
expect(quarter.end_date).to eq Date.parse("2019-12-29")
|
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-06-27 is in" do
|
63
|
+
quarter = subject.quarter_for(Date.parse("2018-06-27"))
|
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-01-30")
|
166
|
+
expect(month.end_date).to eq Date.parse("2017-02-26")
|
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-02-26")
|
177
|
+
expect(month.end_date).to eq Date.parse("2018-03-25")
|
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-10-28")
|
188
|
+
expect(month.end_date).to eq Date.parse("2019-11-24")
|
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-06-27 is in" do
|
195
|
+
month = subject.month_for(Date.parse("2018-06-27"))
|
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
|
-
before(:each) { allow(Date).to receive(:today).and_return Date.parse(
|
295
|
+
context "weeks" do
|
296
|
+
before(:each) { allow(Date).to receive(:today).and_return Date.parse("2019-08-23") }
|
297
297
|
|
298
|
-
it
|
299
|
-
expect(subject.this_week.name).to eq
|
300
|
-
expect(subject.this_week.title).to eq
|
298
|
+
it "knows this week " do
|
299
|
+
expect(subject.this_week.name).to eq "2019W34"
|
300
|
+
expect(subject.this_week.title).to eq "Week of August 19, 2019"
|
301
301
|
end
|
302
302
|
|
303
|
-
it
|
304
|
-
expect(subject.last_week.name).to eq
|
305
|
-
expect(subject.last_week.title).to eq
|
303
|
+
it "knows last week" do
|
304
|
+
expect(subject.last_week.name).to eq "2019W33"
|
305
|
+
expect(subject.last_week.title).to eq "Week of August 12, 2019"
|
306
306
|
end
|
307
307
|
|
308
|
-
it
|
309
|
-
expect(subject.next_week.name).to eq
|
310
|
-
expect(subject.next_week.title).to eq
|
308
|
+
it "knows next week" do
|
309
|
+
expect(subject.next_week.name).to eq "2019W35"
|
310
|
+
expect(subject.next_week.title).to eq "Week of August 26, 2019"
|
311
311
|
end
|
312
312
|
end
|
313
313
|
|
314
|
-
context
|
315
|
-
describe
|
316
|
-
it
|
314
|
+
context "years" do
|
315
|
+
describe "#year" do
|
316
|
+
it "knows 2016" do
|
317
317
|
year = subject.year(2016)
|
318
|
-
expect(year.name).to eq
|
319
|
-
expect(year.title).to eq
|
318
|
+
expect(year.name).to eq "2016"
|
319
|
+
expect(year.title).to eq "2016"
|
320
320
|
expect(year.year_index).to eq 2016
|
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("2015-12-28")
|
323
|
+
expect(year.end_date).to eq Date.parse("2016-12-25")
|
324
324
|
expect(year.to_range).to eq year.start_date..year.end_date
|
325
325
|
end
|
326
326
|
|
327
|
-
it
|
327
|
+
it "knows 2017" do
|
328
328
|
year = subject.year(2017)
|
329
|
-
expect(year.name).to eq
|
330
|
-
expect(year.title).to eq
|
329
|
+
expect(year.name).to eq "2017"
|
330
|
+
expect(year.title).to eq "2017"
|
331
331
|
expect(year.year_index).to eq 2017
|
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("2016-12-26")
|
334
|
+
expect(year.end_date).to eq Date.parse("2017-12-31")
|
335
335
|
expect(year.to_range).to eq year.start_date..year.end_date
|
336
336
|
end
|
337
337
|
|
338
|
-
it
|
338
|
+
it "knows 2018" do
|
339
339
|
year = subject.year(2018)
|
340
|
-
expect(year.name).to eq
|
341
|
-
expect(year.title).to eq
|
340
|
+
expect(year.name).to eq "2018"
|
341
|
+
expect(year.title).to eq "2018"
|
342
342
|
expect(year.year_index).to eq 2018
|
343
343
|
expect(year.index).to eq 1
|
344
|
-
expect(year.start_date).to eq Date.parse(
|
345
|
-
expect(year.end_date).to eq Date.parse(
|
344
|
+
expect(year.start_date).to eq Date.parse("2018-01-01")
|
345
|
+
expect(year.end_date).to eq Date.parse("2018-12-30")
|
346
346
|
expect(year.to_range).to eq year.start_date..year.end_date
|
347
347
|
end
|
348
348
|
end
|
349
349
|
|
350
|
-
describe
|
351
|
-
it
|
352
|
-
year = subject.year_for(Date.parse(
|
353
|
-
expect(year.name).to eq
|
350
|
+
describe "#year_for" do
|
351
|
+
it "knows what year 2018-04-07 is in" do
|
352
|
+
year = subject.year_for(Date.parse("2018-04-07"))
|
353
|
+
expect(year.name).to eq "2018"
|
354
354
|
end
|
355
355
|
|
356
|
-
it
|
357
|
-
year = subject.year_for(Date.parse(
|
358
|
-
expect(year.name).to eq
|
356
|
+
it "knows what year 2016-12-27 is in" do
|
357
|
+
year = subject.year_for(Date.parse("2016-12-27"))
|
358
|
+
expect(year.name).to eq "2017"
|
359
359
|
end
|
360
360
|
end
|
361
361
|
|
362
|
-
describe
|
363
|
-
it
|
362
|
+
describe "#years_for" do
|
363
|
+
it "knows what years are in 2020 (duh)" do
|
364
364
|
basis = subject.year(2020)
|
365
365
|
periods = subject.years_for(basis)
|
366
366
|
expect(periods.map(&:name)).to eq %w[2020]
|
367
367
|
end
|
368
368
|
|
369
|
-
it
|
370
|
-
basis = subject.parse(
|
369
|
+
it "knows what year 2018Q2 is in" do
|
370
|
+
basis = subject.parse("2018Q2")
|
371
371
|
periods = subject.years_for(basis)
|
372
372
|
expect(periods.map(&:name)).to eq %w[2018]
|
373
373
|
end
|
374
374
|
|
375
|
-
it
|
376
|
-
basis = subject.parse(
|
375
|
+
it "knows what years 2019-12-12 is in" do
|
376
|
+
basis = subject.parse("2019-12-12")
|
377
377
|
periods = subject.years_for(basis)
|
378
378
|
expect(periods.map(&:name)).to eq %w[2019]
|
379
379
|
end
|
380
380
|
end
|
381
381
|
|
382
|
-
describe
|
382
|
+
describe "#this_year" do
|
383
383
|
let(:today) { double }
|
384
384
|
let(:year) { double }
|
385
385
|
|
386
|
-
it
|
386
|
+
it "gets the year for today" do
|
387
387
|
allow(Date).to receive(:today).and_return today
|
388
388
|
expect(subject).to receive(:year_for).with(today).and_return year
|
389
389
|
expect(subject.this_year).to eq year
|
390
390
|
end
|
391
391
|
end
|
392
392
|
|
393
|
-
describe
|
394
|
-
let(:entry) { subject.parse(
|
393
|
+
describe "#format" do
|
394
|
+
let(:entry) { subject.parse("2020W24") }
|
395
395
|
|
396
|
-
it
|
397
|
-
expect(entry.format).to eq
|
396
|
+
it "can do a default format" do
|
397
|
+
expect(entry.format).to eq "2020H1Q2M3W2"
|
398
398
|
end
|
399
399
|
|
400
|
-
it
|
401
|
-
expect(entry.format(:quarter)).to eq
|
400
|
+
it "can format with only the quarter" do
|
401
|
+
expect(entry.format(:quarter)).to eq "2020Q2W11"
|
402
402
|
end
|
403
403
|
|
404
|
-
it
|
405
|
-
expect(entry.format(:quarter, :month)).to eq
|
406
|
-
expect(entry.format(:month, :quarter)).to eq
|
404
|
+
it "can format with only the quarter + month" do
|
405
|
+
expect(entry.format(:quarter, :month)).to eq "2020Q2M3W2"
|
406
|
+
expect(entry.format(:month, :quarter)).to eq "2020Q2M3W2"
|
407
407
|
end
|
408
408
|
|
409
|
-
it
|
410
|
-
expect(entry.format(:day, :month, :banana)).to eq
|
409
|
+
it "ignores stupidity" do
|
410
|
+
expect(entry.format(:day, :month, :banana)).to eq "2020M6W2"
|
411
411
|
end
|
412
412
|
end
|
413
413
|
|
414
|
-
context
|
414
|
+
context "relative" do
|
415
415
|
let(:this_year) { subject.year(2015) }
|
416
416
|
let(:year) { double }
|
417
417
|
before(:each) { allow(subject).to receive(:this_year).and_return this_year }
|
418
418
|
|
419
|
-
it
|
419
|
+
it "can get the last year" do
|
420
420
|
allow(this_year).to receive(:previous).and_return year
|
421
421
|
expect(subject.last_year).to eq year
|
422
422
|
end
|
423
423
|
|
424
|
-
it
|
424
|
+
it "can get the next year" do
|
425
425
|
allow(this_year).to receive(:next).and_return year
|
426
426
|
expect(subject.next_year).to eq year
|
427
427
|
end
|
428
428
|
|
429
|
-
it
|
429
|
+
it "can get some number of years" do
|
430
430
|
years = subject.years(5)
|
431
431
|
expect(years.length).to eq 5
|
432
432
|
years.each { |y| expect(y).to be_a TimeBoss::Calendar::Year }
|
433
|
-
expect(years.map(&:name)).to eq [
|
433
|
+
expect(years.map(&:name)).to eq ["2015", "2016", "2017", "2018", "2019"]
|
434
434
|
end
|
435
435
|
|
436
|
-
it
|
436
|
+
it "can get some number of years back" do
|
437
437
|
years = subject.years_back(5)
|
438
438
|
expect(years.length).to eq 5
|
439
439
|
years.each { |y| expect(y).to be_a TimeBoss::Calendar::Year }
|
440
|
-
expect(years.map(&:name)).to eq [
|
440
|
+
expect(years.map(&:name)).to eq ["2011", "2012", "2013", "2014", "2015"]
|
441
441
|
end
|
442
442
|
end
|
443
443
|
end
|
444
444
|
|
445
|
-
describe
|
446
|
-
it
|
447
|
-
date = subject.parse(
|
445
|
+
describe "#parse" do
|
446
|
+
it "can parse a year" do
|
447
|
+
date = subject.parse("2018")
|
448
448
|
expect(date).to be_a TimeBoss::Calendar::Year
|
449
|
-
expect(date.name).to eq
|
449
|
+
expect(date.name).to eq "2018"
|
450
450
|
end
|
451
451
|
|
452
|
-
it
|
453
|
-
date = subject.parse(
|
452
|
+
it "can parse a quarter identifier" do
|
453
|
+
date = subject.parse("2017Q2")
|
454
454
|
expect(date).to be_a TimeBoss::Calendar::Quarter
|
455
|
-
expect(date.name).to eq
|
455
|
+
expect(date.name).to eq "2017Q2"
|
456
456
|
end
|
457
457
|
|
458
|
-
it
|
459
|
-
date = subject.parse(
|
458
|
+
it "can parse a month identifier" do
|
459
|
+
date = subject.parse("2017M4")
|
460
460
|
expect(date).to be_a TimeBoss::Calendar::Month
|
461
|
-
expect(date.name).to eq
|
461
|
+
expect(date.name).to eq "2017M4"
|
462
462
|
end
|
463
463
|
|
464
|
-
it
|
465
|
-
date = subject.parse(
|
464
|
+
it "can parse a week within a year" do
|
465
|
+
date = subject.parse("2018W37")
|
466
466
|
expect(date).to be_a TimeBoss::Calendar::Week
|
467
|
-
expect(date.name).to eq
|
467
|
+
expect(date.name).to eq "2018W37"
|
468
468
|
end
|
469
469
|
|
470
|
-
it
|
471
|
-
date = subject.parse(
|
470
|
+
it "can parse a week within a quarter" do
|
471
|
+
date = subject.parse("2017Q2W2")
|
472
472
|
expect(date).to be_a TimeBoss::Calendar::Week
|
473
|
-
expect(date.name).to eq
|
473
|
+
expect(date.name).to eq "2017W15"
|
474
474
|
end
|
475
475
|
|
476
|
-
it
|
477
|
-
date = subject.parse(
|
476
|
+
it "can parse a week within a month" do
|
477
|
+
date = subject.parse("2017M4W1")
|
478
478
|
expect(date).to be_a TimeBoss::Calendar::Week
|
479
|
-
expect(date.name).to eq
|
479
|
+
expect(date.name).to eq "2017W14"
|
480
480
|
end
|
481
481
|
|
482
|
-
it
|
483
|
-
date = subject.parse(
|
482
|
+
it "can parse a date" do
|
483
|
+
date = subject.parse("2017-04-08")
|
484
484
|
expect(date).to be_a TimeBoss::Calendar::Day
|
485
|
-
expect(date.start_date).to eq Date.parse(
|
486
|
-
expect(date.end_date).to eq Date.parse(
|
485
|
+
expect(date.start_date).to eq Date.parse("2017-04-08")
|
486
|
+
expect(date.end_date).to eq Date.parse("2017-04-08")
|
487
487
|
end
|
488
488
|
|
489
|
-
it
|
490
|
-
date = subject.parse(
|
489
|
+
it "can parse an aesthetically displeasing date" do
|
490
|
+
date = subject.parse("20170408")
|
491
491
|
expect(date).to be_a TimeBoss::Calendar::Day
|
492
|
-
expect(date.start_date).to eq Date.parse(
|
493
|
-
expect(date.end_date).to eq Date.parse(
|
492
|
+
expect(date.start_date).to eq Date.parse("2017-04-08")
|
493
|
+
expect(date.end_date).to eq Date.parse("2017-04-08")
|
494
494
|
end
|
495
495
|
|
496
|
-
it
|
496
|
+
it "gives you nothing if you give it nothing" do
|
497
497
|
expect(subject.parse(nil)).to be nil
|
498
|
-
expect(subject.parse(
|
498
|
+
expect(subject.parse("")).to be nil
|
499
499
|
end
|
500
500
|
end
|
501
501
|
|
502
|
-
context
|
503
|
-
it
|
504
|
-
result = subject.parse(
|
502
|
+
context "expressions" do
|
503
|
+
it "can parse waypoints" do
|
504
|
+
result = subject.parse("this_year")
|
505
505
|
expect(result).to be_a TimeBoss::Calendar::Year
|
506
506
|
expect(result).to be_current
|
507
507
|
end
|
508
508
|
|
509
|
-
it
|
510
|
-
result = subject.parse(
|
509
|
+
it "can parse mathematic expressions" do
|
510
|
+
result = subject.parse("this_month + 2")
|
511
511
|
expect(result).to be_a TimeBoss::Calendar::Month
|
512
512
|
expect(result).to eq subject.months_ahead(2)
|
513
513
|
end
|
514
514
|
|
515
|
-
context
|
515
|
+
context "ranges" do
|
516
516
|
before(:each) { allow(subject).to receive(:this_year).and_return subject.year(2018) }
|
517
|
-
let(:result) { subject.parse(
|
517
|
+
let(:result) { subject.parse("this_year-2 .. this_year") }
|
518
518
|
|
519
|
-
it
|
519
|
+
it "can parse range expressions" do
|
520
520
|
expect(result).to be_a TimeBoss::Calendar::Period
|
521
521
|
expect(result.to_s).to eq "2016: 2015-12-28 thru 2016-12-25 .. 2018: 2018-01-01 thru 2018-12-30"
|
522
522
|
end
|
523
523
|
|
524
|
-
it
|
525
|
-
expect(result.start_date).to eq Date.parse(
|
524
|
+
it "can get an overall start date for a range" do
|
525
|
+
expect(result.start_date).to eq Date.parse("2015-12-28")
|
526
526
|
end
|
527
527
|
|
528
|
-
it
|
529
|
-
expect(result.end_date).to eq Date.parse(
|
528
|
+
it "can get an overall end date for a range" do
|
529
|
+
expect(result.end_date).to eq Date.parse("2018-12-30")
|
530
530
|
end
|
531
531
|
|
532
|
-
context
|
533
|
-
it
|
532
|
+
context "sub-periods" do
|
533
|
+
it "can get the months included in a range" do
|
534
534
|
entries = result.months
|
535
535
|
entries.each { |e| expect(e).to be_a TimeBoss::Calendar::Month }
|
536
|
-
expect(entries.map(&:name)).to include(
|
536
|
+
expect(entries.map(&:name)).to include("2016M1", "2016M9", "2017M3", "2018M12")
|
537
537
|
end
|
538
538
|
|
539
|
-
it
|
539
|
+
it "can get the weeks included in a range" do
|
540
540
|
entries = result.weeks
|
541
541
|
entries.each { |e| expect(e).to be_a TimeBoss::Calendar::Week }
|
542
|
-
expect(entries.map(&:name)).to include(
|
542
|
+
expect(entries.map(&:name)).to include("2016W1", "2016W38", "2017W15", "2017W53", "2018W52")
|
543
543
|
end
|
544
544
|
|
545
|
-
it
|
545
|
+
it "can get the days included in a range" do
|
546
546
|
entries = result.days
|
547
547
|
entries.each { |e| expect(e).to be_a TimeBoss::Calendar::Day }
|
548
|
-
expect(entries.map(&:name)).to include(
|
548
|
+
expect(entries.map(&:name)).to include("2015-12-28", "2016-04-30", "2017-09-22", "2018-12-30")
|
549
549
|
end
|
550
550
|
end
|
551
551
|
end
|
552
552
|
end
|
553
553
|
|
554
|
-
context
|
555
|
-
context
|
556
|
-
let(:basis) { subject.parse(
|
554
|
+
context "shifting" do
|
555
|
+
context "from day" do
|
556
|
+
let(:basis) { subject.parse("2020-04-21") }
|
557
557
|
|
558
|
-
it
|
559
|
-
allow(subject).to receive(:this_week).and_return subject.parse(
|
558
|
+
it "can shift to a different week" do
|
559
|
+
allow(subject).to receive(:this_week).and_return subject.parse("2020W23")
|
560
560
|
result = basis.last_week
|
561
561
|
expect(result).to be_a TimeBoss::Calendar::Day
|
562
|
-
expect(result.to_s).to eq
|
562
|
+
expect(result.to_s).to eq "2020-05-26"
|
563
563
|
expect(basis.in_week).to eq 2
|
564
564
|
end
|
565
565
|
|
566
|
-
it
|
567
|
-
allow(subject).to receive(:this_quarter).and_return subject.parse(
|
566
|
+
it "can shift to a different quarter" do
|
567
|
+
allow(subject).to receive(:this_quarter).and_return subject.parse("2020Q3")
|
568
568
|
result = basis.quarters_ago(2)
|
569
569
|
expect(result).to be_a TimeBoss::Calendar::Day
|
570
|
-
expect(result.to_s).to eq
|
570
|
+
expect(result.to_s).to eq "2020-01-21"
|
571
571
|
expect(basis.in_quarter).to eq 23
|
572
572
|
end
|
573
573
|
|
574
|
-
it
|
575
|
-
allow(subject).to receive(:this_year).and_return subject.parse(
|
574
|
+
it "can shift to a different year" do
|
575
|
+
allow(subject).to receive(:this_year).and_return subject.parse("2019")
|
576
576
|
result = basis.years_ahead(3)
|
577
577
|
expect(result).to be_a TimeBoss::Calendar::Day
|
578
|
-
expect(result.to_s).to eq
|
578
|
+
expect(result.to_s).to eq "2022-04-19"
|
579
579
|
expect(basis.in_year).to eq 114
|
580
580
|
end
|
581
581
|
end
|
582
582
|
|
583
|
-
context
|
584
|
-
let(:basis) { subject.parse(
|
583
|
+
context "from week" do
|
584
|
+
let(:basis) { subject.parse("2017W8") }
|
585
585
|
|
586
|
-
it
|
586
|
+
it "cannot shift to a different day" do
|
587
587
|
expect(basis.last_day).to be nil
|
588
588
|
expect(basis.in_day).to be nil
|
589
589
|
end
|
590
590
|
|
591
|
-
it
|
592
|
-
allow(subject).to receive(:this_month).and_return subject.parse(
|
591
|
+
it "can shift to a different month" do
|
592
|
+
allow(subject).to receive(:this_month).and_return subject.parse("2020M4")
|
593
593
|
result = basis.next_month
|
594
594
|
expect(result).to be_a TimeBoss::Calendar::Week
|
595
|
-
expect(result.to_s).to eq
|
595
|
+
expect(result.to_s).to eq "2020W20: 2020-05-11 thru 2020-05-17"
|
596
596
|
expect(basis.in_month).to eq 3
|
597
597
|
end
|
598
598
|
|
599
|
-
it
|
600
|
-
allow(subject).to receive(:this_half).and_return subject.parse(
|
599
|
+
it "can shift to a different half" do
|
600
|
+
allow(subject).to receive(:this_half).and_return subject.parse("2019H1")
|
601
601
|
result = basis.last_half
|
602
602
|
expect(result).to be_a TimeBoss::Calendar::Week
|
603
|
-
expect(result.to_s).to eq
|
603
|
+
expect(result.to_s).to eq "2018W33: 2018-08-13 thru 2018-08-19"
|
604
604
|
expect(basis.in_half).to eq 8
|
605
605
|
end
|
606
606
|
end
|
607
607
|
|
608
|
-
context
|
609
|
-
let(:basis) { subject.parse(
|
608
|
+
context "from month" do
|
609
|
+
let(:basis) { subject.parse("2017M4") }
|
610
610
|
|
611
|
-
it
|
611
|
+
it "cannot shift to a different week" do
|
612
612
|
expect(basis.last_week).to be nil
|
613
613
|
expect(basis.in_week).to be nil
|
614
614
|
end
|
615
615
|
|
616
|
-
it
|
617
|
-
allow(subject).to receive(:this_year).and_return subject.parse(
|
616
|
+
it "can shift to a different year" do
|
617
|
+
allow(subject).to receive(:this_year).and_return subject.parse("2020")
|
618
618
|
result = basis.years_ahead(4)
|
619
619
|
expect(result).to be_a TimeBoss::Calendar::Month
|
620
|
-
expect(result.name).to eq
|
620
|
+
expect(result.name).to eq "2024M4"
|
621
621
|
expect(basis.in_year).to eq 4
|
622
622
|
end
|
623
623
|
end
|
624
624
|
|
625
|
-
context
|
626
|
-
let(:basis) { subject.parse(
|
625
|
+
context "from quarter" do
|
626
|
+
let(:basis) { subject.parse("2018Q2") }
|
627
627
|
|
628
|
-
it
|
628
|
+
it "cannot shift to a different month" do
|
629
629
|
expect(basis.months_ago(4)).to be nil
|
630
630
|
expect(basis.in_month).to be nil
|
631
631
|
end
|
632
632
|
|
633
|
-
it
|
634
|
-
allow(subject).to receive(:this_half).and_return subject.parse(
|
633
|
+
it "can shift to a different half" do
|
634
|
+
allow(subject).to receive(:this_half).and_return subject.parse("2020H1")
|
635
635
|
result = basis.last_half
|
636
636
|
expect(result).to be_a TimeBoss::Calendar::Quarter
|
637
|
-
expect(result.name).to eq
|
637
|
+
expect(result.name).to eq "2019Q4"
|
638
638
|
expect(basis.in_half).to eq 2
|
639
639
|
end
|
640
640
|
end
|
641
641
|
|
642
|
-
context
|
643
|
-
let(:basis) { subject.parse(
|
642
|
+
context "from year" do
|
643
|
+
let(:basis) { subject.parse("2014") }
|
644
644
|
|
645
|
-
it
|
645
|
+
it "cannot shift to a different half" do
|
646
646
|
expect(basis.next_half).to be nil
|
647
647
|
expect(basis.in_half).to be nil
|
648
648
|
end
|
649
649
|
|
650
|
-
it
|
651
|
-
allow(subject).to receive(:this_year).and_return subject.parse(
|
650
|
+
it "shifts to a different year, but knows how useless that is" do
|
651
|
+
allow(subject).to receive(:this_year).and_return subject.parse("2020")
|
652
652
|
result = basis.years_ago(2)
|
653
653
|
expect(result).to be_a TimeBoss::Calendar::Year
|
654
|
-
expect(result.name).to eq
|
654
|
+
expect(result.name).to eq "2018"
|
655
655
|
expect(basis.in_year).to eq 1
|
656
656
|
end
|
657
657
|
end
|
658
658
|
end
|
659
659
|
|
660
|
-
context
|
660
|
+
context "units" do
|
661
661
|
let(:calendar) { described_class.new }
|
662
662
|
|
663
|
-
context
|
664
|
-
let(:start_date) { Date.parse(
|
663
|
+
context "day" do
|
664
|
+
let(:start_date) { Date.parse("2019-09-30") }
|
665
665
|
let(:subject) { TimeBoss::Calendar::Day.new(calendar, start_date) }
|
666
666
|
|
667
|
-
context
|
668
|
-
it
|
669
|
-
expect(subject.previous.name).to eq
|
667
|
+
context "links" do
|
668
|
+
it "can get its previous" do
|
669
|
+
expect(subject.previous.name).to eq "2019-09-29"
|
670
670
|
end
|
671
671
|
|
672
|
-
it
|
673
|
-
expect(subject.next.name).to eq
|
672
|
+
it "can get its next" do
|
673
|
+
expect(subject.next.name).to eq "2019-10-01"
|
674
674
|
end
|
675
675
|
|
676
|
-
it
|
677
|
-
expect(subject.offset(-3).name).to eq
|
678
|
-
expect((subject - 3).name).to eq
|
676
|
+
it "can offset backwards" do
|
677
|
+
expect(subject.offset(-3).name).to eq "2019-09-27"
|
678
|
+
expect((subject - 3).name).to eq "2019-09-27"
|
679
679
|
end
|
680
680
|
|
681
|
-
it
|
682
|
-
expect(subject.offset(4).name).to eq
|
683
|
-
expect((subject + 4).name).to eq
|
681
|
+
it "can offset forwards" do
|
682
|
+
expect(subject.offset(4).name).to eq "2019-10-04"
|
683
|
+
expect((subject + 4).name).to eq "2019-10-04"
|
684
684
|
end
|
685
685
|
end
|
686
686
|
end
|
687
687
|
|
688
|
-
context
|
689
|
-
context
|
690
|
-
context
|
691
|
-
let(:parent) { calendar.parse(
|
688
|
+
context "week" do
|
689
|
+
context "links" do
|
690
|
+
context "within year" do
|
691
|
+
let(:parent) { calendar.parse("2020") }
|
692
692
|
let(:week) { parent.weeks.first }
|
693
693
|
|
694
|
-
it
|
695
|
-
expect(week.to_s).to include(
|
694
|
+
it "knows itself first" do
|
695
|
+
expect(week.to_s).to include("2020W1", "2019-12-30", "2020-01-05")
|
696
696
|
end
|
697
697
|
|
698
|
-
it
|
698
|
+
it "can get its next week" do
|
699
699
|
subject = week.next
|
700
700
|
expect(subject).to be_a TimeBoss::Calendar::Week
|
701
|
-
expect(subject.to_s).to include(
|
701
|
+
expect(subject.to_s).to include("2020W2", "2020-01-06", "2020-01-12")
|
702
702
|
end
|
703
703
|
|
704
|
-
it
|
704
|
+
it "can get its previous week" do
|
705
705
|
subject = week.previous
|
706
706
|
expect(subject).to be_a TimeBoss::Calendar::Week
|
707
|
-
expect(subject.to_s).to include(
|
707
|
+
expect(subject.to_s).to include("2019W52", "2019-12-23", "2019-12-29")
|
708
708
|
end
|
709
709
|
|
710
|
-
it
|
711
|
-
expect(week.offset(-4).name).to eq
|
712
|
-
expect((week - 4).name).to eq
|
710
|
+
it "can offset backwards" do
|
711
|
+
expect(week.offset(-4).name).to eq "2019W49"
|
712
|
+
expect((week - 4).name).to eq "2019W49"
|
713
713
|
end
|
714
714
|
|
715
|
-
it
|
716
|
-
expect((week + 2).name).to eq
|
715
|
+
it "can offset forwards" do
|
716
|
+
expect((week + 2).name).to eq "2020W3"
|
717
717
|
end
|
718
718
|
end
|
719
719
|
|
720
|
-
context
|
721
|
-
let(:parent) { calendar.parse(
|
720
|
+
context "within quarter" do
|
721
|
+
let(:parent) { calendar.parse("2019Q3") }
|
722
722
|
let(:week) { parent.weeks.last }
|
723
723
|
|
724
|
-
it
|
725
|
-
expect(week.to_s).to include(
|
724
|
+
it "knows itself first" do
|
725
|
+
expect(week.to_s).to include("2019W39", "2019-09-23", "2019-09-29")
|
726
726
|
end
|
727
727
|
|
728
|
-
it
|
728
|
+
it "can get its next week" do
|
729
729
|
subject = week.next
|
730
730
|
expect(subject).to be_a TimeBoss::Calendar::Week
|
731
|
-
expect(subject.to_s).to include(
|
731
|
+
expect(subject.to_s).to include("2019W40", "2019-09-30", "2019-10-06")
|
732
732
|
end
|
733
733
|
|
734
|
-
it
|
734
|
+
it "can get its previous week" do
|
735
735
|
subject = week.previous
|
736
736
|
expect(subject).to be_a TimeBoss::Calendar::Week
|
737
|
-
expect(subject.to_s).to include(
|
737
|
+
expect(subject.to_s).to include("2019W38", "2019-09-16", "2019-09-22")
|
738
738
|
end
|
739
739
|
|
740
|
-
it
|
741
|
-
expect(week.offset(-4).name).to eq
|
742
|
-
expect((week - 4).name).to eq
|
740
|
+
it "can offset backwards" do
|
741
|
+
expect(week.offset(-4).name).to eq "2019W35"
|
742
|
+
expect((week - 4).name).to eq "2019W35"
|
743
743
|
end
|
744
744
|
|
745
|
-
it
|
746
|
-
expect((week + 2).name).to eq
|
745
|
+
it "can offset forwards" do
|
746
|
+
expect((week + 2).name).to eq "2019W41"
|
747
747
|
end
|
748
748
|
end
|
749
749
|
end
|
750
750
|
end
|
751
751
|
|
752
|
-
context
|
753
|
-
let(:start_date) { Date.parse(
|
754
|
-
let(:end_date) { Date.parse(
|
752
|
+
context "quarter" do
|
753
|
+
let(:start_date) { Date.parse("2019-09-30") }
|
754
|
+
let(:end_date) { Date.parse("2019-12-29") }
|
755
755
|
let(:subject) { TimeBoss::Calendar::Quarter.new(calendar, 2019, 4, start_date, end_date) }
|
756
756
|
|
757
|
-
context
|
758
|
-
it
|
757
|
+
context "links" do
|
758
|
+
it "can get the next quarter" do
|
759
759
|
quarter = subject.next
|
760
|
-
expect(quarter.to_s).to include(
|
760
|
+
expect(quarter.to_s).to include("2020Q1", "2019-12-30", "2020-03-29")
|
761
761
|
end
|
762
762
|
|
763
|
-
it
|
763
|
+
it "can get the next next quarter" do
|
764
764
|
quarter = subject.next.next
|
765
|
-
expect(quarter.to_s).to include(
|
765
|
+
expect(quarter.to_s).to include("2020Q2", "2020-03-30", "2020-06-28")
|
766
766
|
end
|
767
767
|
|
768
|
-
it
|
768
|
+
it "can get the next next previous quarter" do
|
769
769
|
quarter = subject.next.next.previous
|
770
|
-
expect(quarter.to_s).to include(
|
770
|
+
expect(quarter.to_s).to include("2020Q1", "2019-12-30", "2020-03-29")
|
771
771
|
end
|
772
772
|
|
773
|
-
it
|
773
|
+
it "can get the next previous quarter" do
|
774
774
|
quarter = subject.next.previous
|
775
775
|
expect(quarter.to_s).to eq subject.to_s
|
776
776
|
end
|
777
777
|
|
778
|
-
it
|
778
|
+
it "can get the previous quarter" do
|
779
779
|
quarter = subject.previous
|
780
|
-
expect(quarter.to_s).to include(
|
780
|
+
expect(quarter.to_s).to include("2019Q3", "2019-07-01", "2019-09-29")
|
781
781
|
end
|
782
782
|
|
783
|
-
it
|
784
|
-
expect(subject.offset(-4).name).to eq
|
785
|
-
expect((subject - 4).name).to eq
|
783
|
+
it "can offset backwards" do
|
784
|
+
expect(subject.offset(-4).name).to eq "2018Q4"
|
785
|
+
expect((subject - 4).name).to eq "2018Q4"
|
786
786
|
end
|
787
787
|
|
788
|
-
it
|
789
|
-
expect(subject.offset(2).name).to eq
|
790
|
-
expect((subject + 2).name).to eq
|
788
|
+
it "can offset forwards" do
|
789
|
+
expect(subject.offset(2).name).to eq "2020Q2"
|
790
|
+
expect((subject + 2).name).to eq "2020Q2"
|
791
791
|
end
|
792
792
|
end
|
793
793
|
end
|