timeboss 1.0.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +7 -2
- data/Rakefile +3 -1
- data/bin/tbsh +7 -6
- data/lib/tasks/calendars.rake +4 -4
- data/lib/tasks/timeboss.rake +2 -2
- 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 +9 -6
- data/lib/timeboss/calendar/quarter.rb +2 -1
- data/lib/timeboss/calendar/support/formatter.rb +5 -4
- data/lib/timeboss/calendar/support/has_fiscal_weeks.rb +17 -0
- data/lib/timeboss/calendar/support/has_iso_weeks.rb +30 -0
- data/lib/timeboss/calendar/support/month_basis.rb +1 -1
- data/lib/timeboss/calendar/support/monthly_unit.rb +8 -8
- 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 +20 -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/calendar.rb +8 -7
- data/lib/timeboss/calendars/broadcast.rb +10 -7
- data/lib/timeboss/calendars/gregorian.rb +4 -5
- data/lib/timeboss/calendars.rb +3 -2
- data/lib/timeboss/version.rb +2 -1
- data/lib/timeboss.rb +2 -0
- data/spec/{calendar → lib/timeboss/calendar}/day_spec.rb +14 -14
- data/spec/{calendar → lib/timeboss/calendar}/quarter_spec.rb +9 -9
- data/spec/lib/timeboss/calendar/support/monthly_unit_spec.rb +91 -0
- data/spec/{calendar → lib/timeboss/calendar}/support/unit_spec.rb +23 -22
- data/spec/{calendar → lib/timeboss/calendar}/week_spec.rb +20 -20
- data/spec/lib/timeboss/calendars/broadcast_spec.rb +796 -0
- data/spec/lib/timeboss/calendars/gregorian_spec.rb +793 -0
- data/spec/{calendars_spec.rb → lib/timeboss/calendars_spec.rb} +19 -19
- data/spec/spec_helper.rb +2 -2
- data/timeboss.gemspec +17 -14
- metadata +53 -23
- data/spec/calendar/support/monthly_unit_spec.rb +0 -85
- data/spec/calendars/broadcast_spec.rb +0 -796
- data/spec/calendars/gregorian_spec.rb +0 -684
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module TimeBoss
|
3
4
|
class Calendar
|
4
5
|
module Waypoints
|
@@ -6,17 +7,17 @@ module TimeBoss
|
|
6
7
|
%i[day week month quarter half year].each do |type|
|
7
8
|
types = type.to_s.pluralize
|
8
9
|
|
9
|
-
define_method("this_#{type}") {
|
10
|
-
define_method("last_#{type}") {
|
11
|
-
define_method("next_#{type}") {
|
10
|
+
define_method("this_#{type}") { public_send("#{type}_for", Date.today) }
|
11
|
+
define_method("last_#{type}") { public_send("this_#{type}").previous }
|
12
|
+
define_method("next_#{type}") { public_send("this_#{type}").next }
|
12
13
|
|
13
|
-
define_method("#{types}_for") { |p|
|
14
|
+
define_method("#{types}_for") { |p| public_send("#{type}_for", p.start_date).until(p.end_date) }
|
14
15
|
|
15
|
-
define_method("#{types}_back") { |q|
|
16
|
-
define_method("#{types}_ago") { |q|
|
16
|
+
define_method("#{types}_back") { |q| public_send("this_#{type}").previous(q) }
|
17
|
+
define_method("#{types}_ago") { |q| public_send("this_#{type}").ago(q) }
|
17
18
|
|
18
|
-
define_method("#{types}_forward") { |q|
|
19
|
-
define_method("#{types}_ahead") { |q|
|
19
|
+
define_method("#{types}_forward") { |q| public_send("this_#{type}").next(q) }
|
20
|
+
define_method("#{types}_ahead") { |q| public_send("this_#{type}").ahead(q) }
|
20
21
|
alias_method types.to_sym, "#{types}_forward".to_sym
|
21
22
|
end
|
22
23
|
|
@@ -66,7 +67,7 @@ module TimeBoss
|
|
66
67
|
# Get the day that occurred the specified number of days ahead.
|
67
68
|
# @param quantity [Integer] the number of days after today
|
68
69
|
# @return [Calendar::Day]
|
69
|
-
|
70
|
+
|
70
71
|
### Weeks
|
71
72
|
|
72
73
|
# @!method this_week
|
@@ -105,7 +106,7 @@ module TimeBoss
|
|
105
106
|
# Get the week that occurred the specified number of weeks ahead.
|
106
107
|
# @param quantity [Integer] the number of weeks after this week
|
107
108
|
# @return [Calendar::Week]
|
108
|
-
|
109
|
+
|
109
110
|
### Months
|
110
111
|
|
111
112
|
# @!method this_month
|
@@ -144,7 +145,7 @@ module TimeBoss
|
|
144
145
|
# Get the month that occurred the specified number of months ahead.
|
145
146
|
# @param quantity [Integer] the number of months after this month
|
146
147
|
# @return [Calendar::Month]
|
147
|
-
|
148
|
+
|
148
149
|
### Quarters
|
149
150
|
|
150
151
|
# @!method this_quarter
|
@@ -183,7 +184,7 @@ module TimeBoss
|
|
183
184
|
# Get the quarter that occurred the specified number of days ahead.
|
184
185
|
# @param quantity [Integer] the number of quarters after this quarter
|
185
186
|
# @return [Calendar::Quarter]
|
186
|
-
|
187
|
+
|
187
188
|
### Halves
|
188
189
|
|
189
190
|
# @!method this_half
|
@@ -222,7 +223,7 @@ module TimeBoss
|
|
222
223
|
# Get the half that occurred the specified number of halves ahead.
|
223
224
|
# @param quantity [Integer] the number of halves after this half
|
224
225
|
# @return [Calendar::Half]
|
225
|
-
|
226
|
+
|
226
227
|
### Years
|
227
228
|
|
228
229
|
# @!method this_year
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require_relative "./support/unit"
|
3
4
|
|
4
5
|
module TimeBoss
|
5
6
|
class Calendar
|
@@ -18,7 +19,7 @@ module TimeBoss
|
|
18
19
|
# Get a "pretty" representation of this week.
|
19
20
|
# @return [String] (e.g. "Week of August 3, 2020")
|
20
21
|
def title
|
21
|
-
"Week of #{start_date.strftime(
|
22
|
+
"Week of #{start_date.strftime("%B %-d, %Y")}"
|
22
23
|
end
|
23
24
|
|
24
25
|
# Get a stringified representation of this week.
|
data/lib/timeboss/calendar.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "active_support/inflector"
|
4
|
+
require "active_support/core_ext/numeric/time"
|
4
5
|
|
5
6
|
%w[day week month quarter half year].each { |f| require_relative "./calendar/#{f}" }
|
6
7
|
%w[waypoints period parser].each { |f| require_relative "./calendar/#{f}" }
|
7
|
-
require_relative
|
8
|
+
require_relative "./calendar/support/month_basis"
|
8
9
|
|
9
10
|
module TimeBoss
|
10
11
|
class Calendar
|
@@ -34,16 +35,16 @@ module TimeBoss
|
|
34
35
|
end
|
35
36
|
|
36
37
|
# Can this calendar support weeks?
|
37
|
-
#
|
38
|
-
#
|
38
|
+
# To support weeks, a calendar must implement a `#weeks_in(year:)` method that returns an array of
|
39
|
+
# `Calendar::Week` objects.
|
39
40
|
# @return [Boolean]
|
40
41
|
def supports_weeks?
|
41
|
-
|
42
|
+
respond_to?(:weeks_in)
|
42
43
|
end
|
43
44
|
|
44
45
|
def self.register!
|
45
46
|
return unless TimeBoss::Calendars.method_defined?(:register)
|
46
|
-
TimeBoss::Calendars.register(
|
47
|
+
TimeBoss::Calendars.register(name.to_s.demodulize.underscore, self)
|
47
48
|
end
|
48
49
|
private_class_method :register!
|
49
50
|
|
@@ -1,9 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require_relative "../calendar"
|
4
|
+
require_relative "../calendar/support/has_fiscal_weeks"
|
3
5
|
|
4
6
|
module TimeBoss
|
5
7
|
module Calendars
|
6
8
|
class Broadcast < Calendar
|
9
|
+
include Support::HasFiscalWeeks
|
7
10
|
register!
|
8
11
|
|
9
12
|
def initialize
|
@@ -15,16 +18,16 @@ module TimeBoss
|
|
15
18
|
class Basis < Calendar::Support::MonthBasis
|
16
19
|
def start_date
|
17
20
|
@_start_date ||= begin
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
date = Date.civil(year, month, 1)
|
22
|
+
date - (date.wday + 6) % 7
|
23
|
+
end
|
21
24
|
end
|
22
25
|
|
23
26
|
def end_date
|
24
27
|
@_end_date ||= begin
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
date = Date.civil(year, month, -1)
|
29
|
+
date - date.wday
|
30
|
+
end
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -1,19 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require_relative "../calendar"
|
4
|
+
require_relative "../calendar/support/has_iso_weeks"
|
3
5
|
|
4
6
|
module TimeBoss
|
5
7
|
module Calendars
|
6
8
|
class Gregorian < Calendar
|
9
|
+
include Support::HasIsoWeeks
|
7
10
|
register!
|
8
11
|
|
9
12
|
def initialize
|
10
13
|
super(basis: Basis)
|
11
14
|
end
|
12
15
|
|
13
|
-
def supports_weeks?
|
14
|
-
false
|
15
|
-
end
|
16
|
-
|
17
16
|
private
|
18
17
|
|
19
18
|
class Basis < Calendar::Support::MonthBasis
|
data/lib/timeboss/calendars.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require_relative "calendar"
|
3
4
|
|
4
5
|
module TimeBoss
|
5
6
|
module Calendars
|
@@ -50,4 +51,4 @@ module TimeBoss
|
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
Dir[File.expand_path(
|
54
|
+
Dir[File.expand_path("../calendars/*.rb", __FILE__)].each { |f| require f }
|
data/lib/timeboss/version.rb
CHANGED
data/lib/timeboss.rb
CHANGED
@@ -2,54 +2,54 @@ module TimeBoss
|
|
2
2
|
class Calendar
|
3
3
|
describe Day do
|
4
4
|
let(:calendar) { instance_double(TimeBoss::Calendar) }
|
5
|
-
let(:start_date) { Date.parse(
|
5
|
+
let(:start_date) { Date.parse("2019-09-30") }
|
6
6
|
let(:subject) { described_class.new(calendar, start_date) }
|
7
7
|
|
8
|
-
it
|
8
|
+
it "knows its stuff" do
|
9
9
|
expect(subject.start_date).to eq start_date
|
10
10
|
expect(subject.end_date).to eq start_date
|
11
11
|
expect(subject.to_range).to eq start_date..start_date
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it "knows its name" do
|
15
15
|
expect(subject.name).to eq start_date.to_s
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
19
|
-
expect(subject.title).to eq
|
18
|
+
it "knows its title" do
|
19
|
+
expect(subject.title).to eq "September 30, 2019"
|
20
20
|
end
|
21
21
|
|
22
|
-
it
|
22
|
+
it "can stringify itself" do
|
23
23
|
expect(subject.to_s).to eq subject.name
|
24
24
|
end
|
25
25
|
|
26
|
-
describe
|
26
|
+
describe "#index" do
|
27
27
|
before(:each) { allow(subject).to receive(:year).and_return double(start_date: start_date - 3) }
|
28
28
|
|
29
|
-
it
|
29
|
+
it "gets its index within the year" do
|
30
30
|
expect(subject.index).to eq 4
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe
|
35
|
-
it
|
34
|
+
describe "#current?" do
|
35
|
+
it "knows when it is" do
|
36
36
|
allow(Date).to receive(:today).and_return start_date
|
37
37
|
expect(subject).to be_current
|
38
38
|
end
|
39
39
|
|
40
|
-
it
|
40
|
+
it "knows when it is not" do
|
41
41
|
expect(subject).not_to be_current
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
context
|
46
|
-
it
|
45
|
+
context "navigation" do
|
46
|
+
it "can get the previous date" do
|
47
47
|
result = subject.previous
|
48
48
|
expect(result).to be_a described_class
|
49
49
|
expect(result.start_date).to eq start_date - 1.day
|
50
50
|
end
|
51
51
|
|
52
|
-
it
|
52
|
+
it "can get the next date" do
|
53
53
|
result = subject.next
|
54
54
|
expect(result).to be_a described_class
|
55
55
|
expect(result.start_date).to eq start_date + 1.day
|
@@ -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
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module TimeBoss
|
2
|
+
class Calendar
|
3
|
+
module Support
|
4
|
+
class TestMonthBasedChunk < MonthlyUnit
|
5
|
+
NUM_MONTHS = 2
|
6
|
+
|
7
|
+
def name
|
8
|
+
"#{year_index}C#{index}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe MonthlyUnit do
|
13
|
+
let(:described_class) { TestMonthBasedChunk }
|
14
|
+
let(:calendar) { double(supports_weeks?: false, weeks_in: nil) }
|
15
|
+
let(:start_date) { Date.parse("2018-06-25") }
|
16
|
+
let(:end_date) { Date.parse("2018-08-26") }
|
17
|
+
let(:subject) { described_class.new(calendar, 2018, 4, start_date, end_date) }
|
18
|
+
|
19
|
+
it "knows its stuff" do
|
20
|
+
expect(subject.start_date).to eq start_date
|
21
|
+
expect(subject.end_date).to eq end_date
|
22
|
+
expect(subject.to_range).to eq start_date..end_date
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can stringify itself" do
|
26
|
+
expect(subject.to_s).to eq "2018C4: 2018-06-25 thru 2018-08-26"
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#weeks" do
|
30
|
+
let(:supports_weeks) { false }
|
31
|
+
before(:each) { allow(calendar).to receive(:supports_weeks?).and_return supports_weeks }
|
32
|
+
|
33
|
+
context "unsupported" do
|
34
|
+
it "blows up when weeks are not supported" do
|
35
|
+
expect { subject.weeks }.to raise_error TimeBoss::Calendar::Support::Unit::UnsupportedUnitError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "supported" do
|
40
|
+
let(:supports_weeks) { true }
|
41
|
+
let(:base) { double(start_date: Date.parse("2018-01-01"), end_date: Date.parse("2018-12-30")) }
|
42
|
+
let(:weeks) do
|
43
|
+
["2018-04-19", "2018-06-25", "2018-07-16", "2018-08-20", "2018-09-30"].map do |date|
|
44
|
+
start_date = Date.parse(date)
|
45
|
+
TimeBoss::Calendar::Week.new(calendar, start_date, start_date + 6.days)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
before(:each) do
|
49
|
+
allow(calendar).to receive(:year).with(2018).and_return base
|
50
|
+
allow(calendar).to receive(:weeks_in).with(year: base).and_return weeks
|
51
|
+
end
|
52
|
+
|
53
|
+
it "can get the relevant weeks for the period" do
|
54
|
+
result = subject.weeks
|
55
|
+
result.each { |w| expect(w).to be_instance_of TimeBoss::Calendar::Week }
|
56
|
+
expect(result.map { |w| w.start_date.to_s }).to eq ["2018-06-25", "2018-07-16", "2018-08-20"]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "navigation" do
|
62
|
+
let(:result) { double }
|
63
|
+
|
64
|
+
describe "#previous" do
|
65
|
+
it "moves easily within itself" do
|
66
|
+
expect(calendar).to receive(:test_month_based_chunk).with(48, 3).and_return result
|
67
|
+
expect(described_class.new(calendar, 48, 4, nil, nil).previous).to eq result
|
68
|
+
end
|
69
|
+
|
70
|
+
it "flips to the previous container" do
|
71
|
+
expect(calendar).to receive(:test_month_based_chunk).with(47, 6).and_return result
|
72
|
+
expect(described_class.new(calendar, 48, 1, nil, nil).previous).to eq result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#next" do
|
77
|
+
it "moves easily within itself" do
|
78
|
+
expect(calendar).to receive(:test_month_based_chunk).with(48, 3).and_return result
|
79
|
+
expect(described_class.new(calendar, 48, 2, nil, nil).next).to eq result
|
80
|
+
end
|
81
|
+
|
82
|
+
it "flips to the previous container" do
|
83
|
+
expect(calendar).to receive(:test_month_based_chunk).with(48, 1).and_return result
|
84
|
+
expect(described_class.new(calendar, 47, 6, nil, nil).next).to eq result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
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
|
@@ -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
|