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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/gem-push.yml +31 -0
  3. data/.github/workflows/ruby.yml +6 -4
  4. data/.travis.yml +11 -1
  5. data/Gemfile +2 -1
  6. data/README.md +1 -1
  7. data/Rakefile +3 -1
  8. data/lib/tasks/calendars.rake +4 -4
  9. data/lib/tasks/timeboss.rake +2 -2
  10. data/lib/timeboss.rb +1 -0
  11. data/lib/timeboss/calendar.rb +5 -4
  12. data/lib/timeboss/calendar/day.rb +3 -2
  13. data/lib/timeboss/calendar/half.rb +2 -1
  14. data/lib/timeboss/calendar/month.rb +2 -1
  15. data/lib/timeboss/calendar/parser.rb +9 -8
  16. data/lib/timeboss/calendar/period.rb +6 -5
  17. data/lib/timeboss/calendar/quarter.rb +2 -1
  18. data/lib/timeboss/calendar/support/formatter.rb +5 -4
  19. data/lib/timeboss/calendar/support/month_basis.rb +1 -1
  20. data/lib/timeboss/calendar/support/monthly_unit.rb +7 -6
  21. data/lib/timeboss/calendar/support/navigable.rb +2 -1
  22. data/lib/timeboss/calendar/support/shiftable.rb +12 -11
  23. data/lib/timeboss/calendar/support/translatable.rb +3 -2
  24. data/lib/timeboss/calendar/support/unit.rb +14 -13
  25. data/lib/timeboss/calendar/waypoints/absolute.rb +4 -3
  26. data/lib/timeboss/calendar/waypoints/relative.rb +14 -13
  27. data/lib/timeboss/calendar/week.rb +3 -2
  28. data/lib/timeboss/calendar/year.rb +2 -1
  29. data/lib/timeboss/calendars.rb +3 -2
  30. data/lib/timeboss/calendars/broadcast.rb +8 -7
  31. data/lib/timeboss/calendars/gregorian.rb +2 -1
  32. data/lib/timeboss/version.rb +2 -1
  33. data/spec/calendar/day_spec.rb +14 -14
  34. data/spec/calendar/quarter_spec.rb +9 -9
  35. data/spec/calendar/support/monthly_unit_spec.rb +36 -35
  36. data/spec/calendar/support/unit_spec.rb +23 -22
  37. data/spec/calendar/week_spec.rb +20 -20
  38. data/spec/calendars/broadcast_spec.rb +310 -310
  39. data/spec/calendars/gregorian_spec.rb +258 -258
  40. data/spec/calendars_spec.rb +19 -19
  41. data/spec/spec_helper.rb +2 -2
  42. data/timeboss.gemspec +15 -14
  43. metadata +21 -7
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  module Support
@@ -8,10 +9,10 @@ module TimeBoss
8
9
  PERIODS.each do |period|
9
10
  periods = period.pluralize
10
11
 
11
- define_method(periods) { calendar.send("#{periods}_for", self) }
12
+ define_method(periods) { calendar.public_send("#{periods}_for", self) }
12
13
 
13
14
  define_method(period) do |index = nil|
14
- entries = send(periods)
15
+ entries = public_send(periods)
15
16
  return entries[index - 1] unless index.nil?
16
17
  return nil unless entries.length == 1
17
18
  entries.first
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
- require_relative './navigable'
3
- require_relative './translatable'
4
- require_relative './shiftable'
5
- require_relative './formatter'
2
+
3
+ require_relative "./navigable"
4
+ require_relative "./translatable"
5
+ require_relative "./shiftable"
6
+ require_relative "./formatter"
6
7
 
7
8
  module TimeBoss
8
9
  class Calendar
@@ -16,7 +17,7 @@ module TimeBoss
16
17
  UnsupportedUnitError = Class.new(StandardError)
17
18
 
18
19
  def self.type
19
- self.name.demodulize.underscore
20
+ name.demodulize.underscore
20
21
  end
21
22
 
22
23
  def initialize(calendar, start_date, end_date)
@@ -28,8 +29,8 @@ module TimeBoss
28
29
  # Is the specified unit equal to this one, based on its unit type and date range?
29
30
  # @param entry [Unit] the unit to compare
30
31
  # @return [Boolean] true when periods are equal
31
- def ==(entry)
32
- self.class == entry.class && self.start_date == entry.start_date && self.end_date == entry.end_date
32
+ def ==(other)
33
+ self.class == other.class && start_date == other.start_date && end_date == other.end_date
33
34
  end
34
35
 
35
36
  # Format this period based on specified granularities.
@@ -59,28 +60,28 @@ module TimeBoss
59
60
  def offset(value)
60
61
  method = value.negative? ? :previous : :next
61
62
  base = self
62
- value.abs.times { base = base.send(method) }
63
+ value.abs.times { base = base.public_send(method) }
63
64
  base
64
65
  end
65
66
 
66
67
  # Move some number of units forward from this unit.
67
68
  # @param value [Integer]
68
69
  # @return [Unit]
69
- def +(value)
70
- offset(value)
70
+ def +(other)
71
+ offset(other)
71
72
  end
72
73
 
73
74
  # Move some number of units backward from this unit.
74
75
  # @param value [Integer]
75
76
  # @return [Unit]
76
- def -(value)
77
- offset(-value)
77
+ def -(other)
78
+ offset(-other)
78
79
  end
79
80
 
80
81
  # Express this period as a date range.
81
82
  # @return [Range<Date, Date>]
82
83
  def to_range
83
- @_to_range ||= start_date .. end_date
84
+ @_to_range ||= start_date..end_date
84
85
  end
85
86
 
86
87
  def inspect
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  module Waypoints
@@ -9,13 +10,13 @@ module TimeBoss
9
10
 
10
11
  define_method type do |year_index, index = 1|
11
12
  month = (index * size) - size + 1
12
- months = (month .. month + size - 1).map { |i| basis.new(year_index, i) }
13
+ months = (month..month + size - 1).map { |i| basis.new(year_index, i) }
13
14
  klass.new(self, year_index, index, months.first.start_date, months.last.end_date)
14
15
  end
15
16
 
16
17
  define_method "#{type}_for" do |date|
17
- window = send(type, date.year - 1, 1)
18
- while true
18
+ window = public_send(type, date.year - 1, 1)
19
+ loop do
19
20
  break window if window.to_range.include?(date)
20
21
  window = window.next
21
22
  end
@@ -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}") { send("#{type}_for", Date.today) }
10
- define_method("last_#{type}") { send("this_#{type}").previous }
11
- define_method("next_#{type}") { send("this_#{type}").next }
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| send("#{type}_for", p.start_date).until(p.end_date) }
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| send("this_#{type}").previous(q) }
16
- define_method("#{types}_ago") { |q| send("this_#{type}").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| send("this_#{type}").next(q) }
19
- define_method("#{types}_ahead") { |q| send("this_#{type}").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
- require_relative './support/unit'
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('%B %-d, %Y')}"
22
+ "Week of #{start_date.strftime("%B %-d, %Y")}"
22
23
  end
23
24
 
24
25
  # Get a stringified representation of this week.
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative './support/monthly_unit'
2
+
3
+ require_relative "./support/monthly_unit"
3
4
 
4
5
  module TimeBoss
5
6
  class Calendar
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'calendar'
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('../calendars/*.rb', __FILE__)].each { |f| require f }
54
+ Dir[File.expand_path("../calendars/*.rb", __FILE__)].each { |f| require f }
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative '../calendar'
2
+
3
+ require_relative "../calendar"
3
4
 
4
5
  module TimeBoss
5
6
  module Calendars
@@ -15,16 +16,16 @@ module TimeBoss
15
16
  class Basis < Calendar::Support::MonthBasis
16
17
  def start_date
17
18
  @_start_date ||= begin
18
- date = Date.civil(year, month, 1)
19
- date - (date.wday + 6) % 7
20
- end
19
+ date = Date.civil(year, month, 1)
20
+ date - (date.wday + 6) % 7
21
+ end
21
22
  end
22
23
 
23
24
  def end_date
24
25
  @_end_date ||= begin
25
- date = Date.civil(year, month, -1)
26
- date - date.wday
27
- end
26
+ date = Date.civil(year, month, -1)
27
+ date - date.wday
28
+ end
28
29
  end
29
30
  end
30
31
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative '../calendar'
2
+
3
+ require_relative "../calendar"
3
4
 
4
5
  module TimeBoss
5
6
  module Calendars
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
- VERSION = "1.0.1"
4
+ VERSION = "1.0.5"
4
5
  end
@@ -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('2019-09-30') }
5
+ let(:start_date) { Date.parse("2019-09-30") }
6
6
  let(:subject) { described_class.new(calendar, start_date) }
7
7
 
8
- it 'knows its stuff' do
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 'knows its name' do
14
+ it "knows its name" do
15
15
  expect(subject.name).to eq start_date.to_s
16
16
  end
17
17
 
18
- it 'knows its title' do
19
- expect(subject.title).to eq 'September 30, 2019'
18
+ it "knows its title" do
19
+ expect(subject.title).to eq "September 30, 2019"
20
20
  end
21
21
 
22
- it 'can stringify itself' do
22
+ it "can stringify itself" do
23
23
  expect(subject.to_s).to eq subject.name
24
24
  end
25
25
 
26
- describe '#index' do
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 'gets its index within the year' do
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 '#current?' do
35
- it 'knows when it is' do
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 'knows when it is not' do
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 'navigation' do
46
- it 'can get the previous date' do
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 'can get the next date' do
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('2019-09-30') }
6
- let(:end_date) { Date.parse('2019-12-29') }
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 'knows its stuff' do
10
- expect(subject.name).to eq '2019Q4'
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 'can stringify itself' do
17
- expect(subject.to_s).to include('2019Q4', start_date.to_s, end_date.to_s)
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 '#current?' do
21
- it 'knows when it is' do
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 'knows when it is not' do
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
- describe MonthlyUnit do
5
- class MonthBasedChunk < described_class
6
- NUM_MONTHS = 2
4
+ class TestMonthBasedChunk < MonthlyUnit
5
+ NUM_MONTHS = 2
7
6
 
8
- def name
9
- "#{year_index}C#{index}"
10
- end
7
+ def name
8
+ "#{year_index}C#{index}"
11
9
  end
12
- let(:described_class) { MonthBasedChunk }
10
+ end
11
+
12
+ describe MonthlyUnit do
13
+ let(:described_class) { TestMonthBasedChunk }
13
14
  let(:calendar) { double }
14
- let(:start_date) { Date.parse('2018-06-25') }
15
- let(:end_date) { Date.parse('2018-08-26') }
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 'knows its stuff' do
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 'can stringify itself' do
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 '#weeks' do
29
- let(:base) { double(start_date: Date.parse('2018-01-01'), end_date: Date.parse('2018-12-30')) }
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 'can get the relevant weeks for the period' do
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
- '2018-06-25',
38
- '2018-07-02',
39
- '2018-07-09',
40
- '2018-07-16',
41
- '2018-07-23',
42
- '2018-07-30',
43
- '2018-08-06',
44
- '2018-08-13',
45
- '2018-08-20'
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 'blows up when weeks are not supported' do
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 'navigation' do
56
+ context "navigation" do
56
57
  let(:result) { double }
57
58
 
58
- describe '#previous' do
59
- it 'moves easily within itself' do
60
- expect(calendar).to receive(:month_based_chunk).with(48, 3).and_return result
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 'flips to the previous container' do
65
- expect(calendar).to receive(:month_based_chunk).with(47, 6).and_return result
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 '#next' do
71
- it 'moves easily within itself' do
72
- expect(calendar).to receive(:month_based_chunk).with(48, 3).and_return result
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 'flips to the previous container' do
77
- expect(calendar).to receive(:month_based_chunk).with(48, 1).and_return result
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