timeboss 1.0.1 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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