timeboss 0.0.7 → 0.1.1

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.gitignore +5 -3
  5. data/.yardopts +1 -0
  6. data/CODE_OF_CONDUCT.md +76 -0
  7. data/README.md +30 -18
  8. data/bin/tbsh +15 -0
  9. data/lib/tasks/calendars.rake +5 -0
  10. data/lib/timeboss.rb +4 -0
  11. data/lib/timeboss/calendar.rb +21 -0
  12. data/lib/timeboss/calendar/day.rb +18 -6
  13. data/lib/timeboss/calendar/half.rb +6 -2
  14. data/lib/timeboss/calendar/month.rb +6 -2
  15. data/lib/timeboss/calendar/period.rb +25 -11
  16. data/lib/timeboss/calendar/quarter.rb +6 -2
  17. data/lib/timeboss/calendar/support/formatter.rb +3 -2
  18. data/lib/timeboss/calendar/support/month_basis.rb +1 -0
  19. data/lib/timeboss/calendar/support/{month_based.rb → monthly_unit.rb} +22 -18
  20. data/lib/timeboss/calendar/support/navigable.rb +72 -0
  21. data/lib/timeboss/calendar/support/shiftable.rb +218 -28
  22. data/lib/timeboss/calendar/support/translatable.rb +92 -0
  23. data/lib/timeboss/calendar/support/unit.rb +27 -0
  24. data/lib/timeboss/calendar/waypoints.rb +5 -80
  25. data/lib/timeboss/calendar/waypoints/absolute.rb +113 -0
  26. data/lib/timeboss/calendar/waypoints/relative.rb +267 -0
  27. data/lib/timeboss/calendar/week.rb +25 -18
  28. data/lib/timeboss/calendar/year.rb +5 -5
  29. data/lib/timeboss/calendars.rb +16 -1
  30. data/lib/timeboss/version.rb +1 -1
  31. data/spec/calendar/day_spec.rb +1 -1
  32. data/spec/calendar/support/{month_based_spec.rb → monthly_unit_spec.rb} +18 -8
  33. data/spec/calendar/week_spec.rb +5 -13
  34. data/spec/calendars/broadcast_spec.rb +27 -7
  35. data/spec/calendars_spec.rb +7 -1
  36. data/timeboss.gemspec +1 -0
  37. metadata +32 -7
@@ -4,41 +4,48 @@ require_relative './support/unit'
4
4
  module TimeBoss
5
5
  class Calendar
6
6
  class Week < Support::Unit
7
- attr_reader :year_index, :index
8
-
9
- def initialize(calendar, year_index, index, start_date, end_date)
7
+ def initialize(calendar, start_date, end_date)
10
8
  super(calendar, start_date, end_date)
11
- @year_index = year_index
12
- @index = index
13
9
  end
14
10
 
11
+ # Get a simple representation of this week.
12
+ # @return [String] (e.g. "2020W32")
15
13
  def name
16
14
  "#{year_index}W#{index}"
17
15
  end
18
16
 
17
+ # Get a "pretty" representation of this week.
18
+ # @return [String] (e.g. "Week of August 3, 2020")
19
19
  def title
20
20
  "Week of #{start_date.strftime('%B %-d, %Y')}"
21
21
  end
22
22
 
23
+ # Get a stringified representation of this week.
24
+ # @return [String] (e.g. "2020W32: 2020-08-03 thru 2020-08-09")
23
25
  def to_s
24
26
  "#{name}: #{start_date} thru #{end_date}"
25
27
  end
26
28
 
27
- def previous
28
- if index == 1
29
- (calendar.year_for(start_date) - 1).weeks.last
30
- else
31
- self.class.new(calendar, year_index, index - 1, start_date - 1.week, end_date - 1.week)
32
- end
29
+ # Get the index of this week within its containing year.
30
+ # @return [Integer]
31
+ def index
32
+ @_index ||= (((start_date - year.start_date) + 1) / 7.0).to_i + 1
33
+ end
34
+
35
+ # Get the year number for this week.
36
+ # @return [Integer] (e.g. 2020)
37
+ def year_index
38
+ @_year_index ||= year.year_index
39
+ end
40
+
41
+ private
42
+
43
+ def down
44
+ self.class.new(calendar, start_date - 1.week, end_date - 1.week)
33
45
  end
34
46
 
35
- def next
36
- weeks = calendar.year_for(start_date).weeks
37
- if index == weeks.last.index
38
- self.class.new(calendar, year_index + 1, 1, start_date + 1.week, end_date + 1.week)
39
- else
40
- weeks[index]
41
- end
47
+ def up
48
+ self.class.new(calendar, start_date + 1.week, end_date + 1.week)
42
49
  end
43
50
  end
44
51
  end
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
- require_relative './support/month_based'
2
+ require_relative './support/monthly_unit'
3
3
 
4
4
  module TimeBoss
5
5
  class Calendar
6
- class Year < Support::MonthBased
6
+ class Year < Support::MonthlyUnit
7
7
  NUM_MONTHS = 12
8
8
 
9
+ # Get a simple representation of this year.
10
+ # @return [String] (e.g. "2020")
9
11
  def name
10
12
  year_index.to_s
11
13
  end
12
14
 
13
- def title
14
- name
15
- end
15
+ alias_method :title, :name
16
16
  end
17
17
  end
18
18
  end
@@ -10,19 +10,34 @@ module TimeBoss
10
10
  extend Enumerable
11
11
  delegate :each, :length, to: :all
12
12
 
13
+ # Retrieve a list of all registered calendars.
14
+ # @return [Array<Entry>]
13
15
  def all
14
16
  @_all ||= TimeBoss::Calendar.subclasses.map do |klass|
15
17
  Entry.new(klass.to_s.demodulize.underscore.to_sym, klass)
16
18
  end
17
19
  end
18
20
 
21
+ # Retrieve an instance of the specified named calendar.
22
+ # @param name [String, Symbol] the name of the calendar to retrieve.
23
+ # @return [Calendar]
19
24
  def [](name)
20
- find { |e| e.name == name.to_sym }&.calendar
25
+ find { |e| e.name == name&.to_sym }&.calendar
21
26
  end
22
27
 
23
28
  private
24
29
 
25
30
  Entry = Struct.new(:name, :klass) do
31
+ # @!method name
32
+ # Get the name of the calendar referenced in this entry.
33
+ # @return [Symbol]
34
+
35
+ # @!method klass
36
+ # The class implementing this calendar.
37
+ # @return [Class<Calendar>]
38
+
39
+ # Get an instance of the calendar referenced in this entry.
40
+ # @return [Calendar]
26
41
  def calendar
27
42
  @_calendar ||= klass.new
28
43
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module TimeBoss
3
- VERSION = "0.0.7"
3
+ VERSION = "0.1.1"
4
4
  end
@@ -24,7 +24,7 @@ module TimeBoss
24
24
  end
25
25
 
26
26
  describe '#index' do
27
- before(:each) { allow(calendar).to receive(:year_for).with(start_date).and_return double(start_date: start_date - 3) }
27
+ before(:each) { allow(subject).to receive(:year).and_return double(start_date: start_date - 3) }
28
28
 
29
29
  it 'gets its index within the year' do
30
30
  expect(subject.index).to eq 4
@@ -1,15 +1,15 @@
1
1
  module TimeBoss
2
2
  class Calendar
3
3
  module Support
4
- describe MonthBased do
5
- class ChunkMonthBased < described_class
4
+ describe MonthlyUnit do
5
+ class MonthBasedChunk < described_class
6
6
  NUM_MONTHS = 2
7
7
 
8
8
  def name
9
9
  "#{year_index}C#{index}"
10
10
  end
11
11
  end
12
- let(:described_class) { ChunkMonthBased }
12
+ let(:described_class) { MonthBasedChunk }
13
13
  let(:calendar) { double }
14
14
  let(:start_date) { Date.parse('2018-06-25') }
15
15
  let(:end_date) { Date.parse('2018-08-26') }
@@ -32,7 +32,17 @@ module TimeBoss
32
32
  it 'can get the relevant weeks for the period' do
33
33
  result = subject.weeks
34
34
  result.each { |w| expect(w).to be_instance_of TimeBoss::Calendar::Week }
35
- expect(result.map(&:name)).to eq %w[2018W26 2018W27 2018W28 2018W29 2018W30 2018W31 2018W32 2018W33 2018W34]
35
+ expect(result.map { |w| w.start_date.to_s }).to eq [
36
+ '2018-06-25',
37
+ '2018-07-02',
38
+ '2018-07-09',
39
+ '2018-07-16',
40
+ '2018-07-23',
41
+ '2018-07-30',
42
+ '2018-08-06',
43
+ '2018-08-13',
44
+ '2018-08-20'
45
+ ]
36
46
  end
37
47
  end
38
48
 
@@ -41,24 +51,24 @@ module TimeBoss
41
51
 
42
52
  describe '#previous' do
43
53
  it 'moves easily within itself' do
44
- expect(calendar).to receive(:chunk_month_based).with(48, 3).and_return result
54
+ expect(calendar).to receive(:month_based_chunk).with(48, 3).and_return result
45
55
  expect(described_class.new(calendar, 48, 4, nil, nil).previous).to eq result
46
56
  end
47
57
 
48
58
  it 'flips to the previous container' do
49
- expect(calendar).to receive(:chunk_month_based).with(47, 6).and_return result
59
+ expect(calendar).to receive(:month_based_chunk).with(47, 6).and_return result
50
60
  expect(described_class.new(calendar, 48, 1, nil, nil).previous).to eq result
51
61
  end
52
62
  end
53
63
 
54
64
  describe '#next' do
55
65
  it 'moves easily within itself' do
56
- expect(calendar).to receive(:chunk_month_based).with(48, 3).and_return result
66
+ expect(calendar).to receive(:month_based_chunk).with(48, 3).and_return result
57
67
  expect(described_class.new(calendar, 48, 2, nil, nil).next).to eq result
58
68
  end
59
69
 
60
70
  it 'flips to the previous container' do
61
- expect(calendar).to receive(:chunk_month_based).with(48, 1).and_return result
71
+ expect(calendar).to receive(:month_based_chunk).with(48, 1).and_return result
62
72
  expect(described_class.new(calendar, 47, 6, nil, nil).next).to eq result
63
73
  end
64
74
  end
@@ -4,7 +4,7 @@ module TimeBoss
4
4
  let(:calendar) { instance_double(TimeBoss::Calendar) }
5
5
  let(:start_date) { Date.parse('2048-04-06') }
6
6
  let(:end_date) { Date.parse('2048-04-12') }
7
- let(:subject) { described_class.new(calendar, 2048, 15, start_date, end_date) }
7
+ let(:subject) { described_class.new(calendar, start_date, end_date) }
8
8
 
9
9
  it 'knows its stuff' do
10
10
  expect(subject.start_date).to eq start_date
@@ -12,18 +12,10 @@ module TimeBoss
12
12
  expect(subject.to_range).to eq start_date..end_date
13
13
  end
14
14
 
15
- it 'knows its name' do
16
- expect(subject.name).to eq '2048W15'
17
- end
18
-
19
15
  it 'knows its title' do
20
16
  expect(subject.title).to eq "Week of April 6, 2048"
21
17
  end
22
18
 
23
- it 'can stringify itself' do
24
- expect(subject.to_s).to include(subject.name, start_date.to_s, end_date.to_s)
25
- end
26
-
27
19
  describe '#current?' do
28
20
  it 'knows when it is' do
29
21
  allow(Date).to receive(:today).and_return start_date
@@ -46,13 +38,13 @@ module TimeBoss
46
38
  end
47
39
 
48
40
  it 'can wrap to the previous 52-week year' do
49
- result = described_class.new(calendar, 2022, 1, Date.parse('2021-12-27'), Date.parse('2022-01-02')).previous
41
+ result = described_class.new(calendar, Date.parse('2021-12-27'), Date.parse('2022-01-02')).previous
50
42
  expect(result).to be_a described_class
51
43
  expect(result.to_s).to eq "2021W52: 2021-12-20 thru 2021-12-26"
52
44
  end
53
45
 
54
46
  it 'can wrap to the previous 53-week year' do
55
- result = described_class.new(calendar, 2024, 1, Date.parse('2024-01-01'), Date.parse('2024-01-07')).previous
47
+ result = described_class.new(calendar, Date.parse('2024-01-01'), Date.parse('2024-01-07')).previous
56
48
  expect(result).to be_a described_class
57
49
  expect(result.to_s).to eq "2023W53: 2023-12-25 thru 2023-12-31"
58
50
  end
@@ -66,13 +58,13 @@ module TimeBoss
66
58
  end
67
59
 
68
60
  it 'can wrap from week 52 to the next year' do
69
- result = described_class.new(calendar, 2021, 52, Date.parse('2021-12-20'), Date.parse('2021-12-26')).next
61
+ result = described_class.new(calendar, Date.parse('2021-12-20'), Date.parse('2021-12-26')).next
70
62
  expect(result).to be_a described_class
71
63
  expect(result.to_s).to eq "2022W1: 2021-12-27 thru 2022-01-02"
72
64
  end
73
65
 
74
66
  it 'can wrap from week 53 to the next year' do
75
- result = described_class.new(calendar, 2023, 53, Date.parse('2023-12-25'), Date.parse('2023-12-31')).next
67
+ result = described_class.new(calendar, Date.parse('2023-12-25'), Date.parse('2023-12-31')).next
76
68
  expect(result).to be_a described_class
77
69
  expect(result.to_s).to eq "2024W1: 2024-01-01 thru 2024-01-07"
78
70
  end
@@ -2,6 +2,26 @@ module TimeBoss
2
2
  describe Calendars::Broadcast do
3
3
  let(:subject) { described_class.new }
4
4
 
5
+ context 'days' do
6
+ it 'can get today' do
7
+ day = subject.today
8
+ expect(day).to be_instance_of(TimeBoss::Calendar::Day)
9
+ expect(day.start_date).to eq Date.today
10
+ end
11
+
12
+ it 'can get yesterday' do
13
+ day = subject.yesterday
14
+ expect(day).to be_instance_of(TimeBoss::Calendar::Day)
15
+ expect(day.start_date).to eq Date.yesterday
16
+ end
17
+
18
+ it 'can get tomorrow' do
19
+ day = subject.tomorrow
20
+ expect(day).to be_instance_of(TimeBoss::Calendar::Day)
21
+ expect(day.start_date).to eq Date.tomorrow
22
+ end
23
+ end
24
+
5
25
  context 'quarters' do
6
26
  describe '#quarter' do
7
27
  it 'knows 2017Q2' do
@@ -113,8 +133,8 @@ module TimeBoss
113
133
  expect(quarters.map(&:name)).to eq ['2015Q3', '2015Q4', '2016Q1', '2016Q2', '2016Q3']
114
134
  end
115
135
 
116
- it 'can get a quarter hence' do
117
- quarter = subject.quarters_hence(4)
136
+ it 'can get a quarter ahead' do
137
+ quarter = subject.quarters_ahead(4)
118
138
  expect(quarter).to be_a TimeBoss::Calendar::Quarter
119
139
  expect(quarter.name).to eq '2016Q3'
120
140
  end
@@ -251,8 +271,8 @@ module TimeBoss
251
271
  expect(months.map(&:name)).to eq ['2015M3', '2015M4', '2015M5', '2015M6', '2015M7']
252
272
  end
253
273
 
254
- it 'can get a month hence' do
255
- month = subject.months_hence(4)
274
+ it 'can get a month ahead' do
275
+ month = subject.months_ahead(4)
256
276
  expect(month).to be_a TimeBoss::Calendar::Month
257
277
  expect(month.name).to eq '2015M7'
258
278
  end
@@ -490,7 +510,7 @@ module TimeBoss
490
510
  it 'can parse mathematic expressions' do
491
511
  result = subject.parse('this_month + 2')
492
512
  expect(result).to be_a TimeBoss::Calendar::Month
493
- expect(result).to eq subject.months_hence(2)
513
+ expect(result).to eq subject.months_ahead(2)
494
514
  end
495
515
 
496
516
  context 'ranges' do
@@ -554,7 +574,7 @@ module TimeBoss
554
574
 
555
575
  it 'can shift to a different year' do
556
576
  allow(subject).to receive(:this_year).and_return subject.parse('2019')
557
- result = basis.years_hence(3)
577
+ result = basis.years_ahead(3)
558
578
  expect(result).to be_a TimeBoss::Calendar::Day
559
579
  expect(result.to_s).to eq '2022-04-19'
560
580
  expect(basis.in_year).to eq 114
@@ -596,7 +616,7 @@ module TimeBoss
596
616
 
597
617
  it 'can shift to a different year' do
598
618
  allow(subject).to receive(:this_year).and_return subject.parse('2020')
599
- result = basis.years_hence(4)
619
+ result = basis.years_ahead(4)
600
620
  expect(result).to be_a TimeBoss::Calendar::Month
601
621
  expect(result.name).to eq '2024M4'
602
622
  expect(basis.in_year).to eq 4
@@ -28,10 +28,16 @@ module TimeBoss
28
28
  c2 = described_class[:broadcast]
29
29
  expect(c1).to be_instance_of TimeBoss::Calendars::Broadcast
30
30
  expect(c1).to be c2
31
+
32
+ expect(c1.name).to eq 'broadcast'
33
+ expect(c1.title).to eq 'Broadcast'
31
34
  end
32
35
 
33
36
  it 'can return a new calendar' do
34
- expect(described_class[:my_test_calendar]).to be_instance_of MyTestCalendar
37
+ c1 = described_class[:my_test_calendar]
38
+ expect(c1).to be_instance_of MyTestCalendar
39
+ expect(c1.name).to eq 'my_test_calendar'
40
+ expect(c1.title).to eq 'My Test Calendar'
35
41
  end
36
42
 
37
43
  it 'can graceully give you nothing' do
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rack-test"
28
28
  spec.add_development_dependency "rake"
29
29
  spec.add_development_dependency "rspec"
30
+ spec.add_development_dependency "yard"
30
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeboss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin McDonald
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-16 00:00:00.000000000 Z
11
+ date: 2020-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,20 +108,40 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Broadcast Calendar navigation in Ruby made simple
112
126
  email:
113
127
  - kevinstuffandthings@gmail.com
114
- executables: []
128
+ executables:
129
+ - tbsh
115
130
  extensions: []
116
131
  extra_rdoc_files: []
117
132
  files:
133
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
134
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
118
135
  - ".gitignore"
119
136
  - ".rspec"
120
137
  - ".travis.yml"
138
+ - ".yardopts"
139
+ - CODE_OF_CONDUCT.md
121
140
  - Gemfile
122
141
  - LICENSE.txt
123
142
  - README.md
124
143
  - Rakefile
144
+ - bin/tbsh
125
145
  - lib/tasks/calendars.rake
126
146
  - lib/tasks/timeboss.rake
127
147
  - lib/timeboss.rb
@@ -133,11 +153,15 @@ files:
133
153
  - lib/timeboss/calendar/period.rb
134
154
  - lib/timeboss/calendar/quarter.rb
135
155
  - lib/timeboss/calendar/support/formatter.rb
136
- - lib/timeboss/calendar/support/month_based.rb
137
156
  - lib/timeboss/calendar/support/month_basis.rb
157
+ - lib/timeboss/calendar/support/monthly_unit.rb
158
+ - lib/timeboss/calendar/support/navigable.rb
138
159
  - lib/timeboss/calendar/support/shiftable.rb
160
+ - lib/timeboss/calendar/support/translatable.rb
139
161
  - lib/timeboss/calendar/support/unit.rb
140
162
  - lib/timeboss/calendar/waypoints.rb
163
+ - lib/timeboss/calendar/waypoints/absolute.rb
164
+ - lib/timeboss/calendar/waypoints/relative.rb
141
165
  - lib/timeboss/calendar/week.rb
142
166
  - lib/timeboss/calendar/year.rb
143
167
  - lib/timeboss/calendars.rb
@@ -146,7 +170,7 @@ files:
146
170
  - lib/timeboss/version.rb
147
171
  - spec/calendar/day_spec.rb
148
172
  - spec/calendar/quarter_spec.rb
149
- - spec/calendar/support/month_based_spec.rb
173
+ - spec/calendar/support/monthly_unit_spec.rb
150
174
  - spec/calendar/support/unit_spec.rb
151
175
  - spec/calendar/week_spec.rb
152
176
  - spec/calendars/broadcast_spec.rb
@@ -172,14 +196,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
196
  - !ruby/object:Gem::Version
173
197
  version: '0'
174
198
  requirements: []
175
- rubygems_version: 3.0.8
199
+ rubyforge_project:
200
+ rubygems_version: 2.7.7
176
201
  signing_key:
177
202
  specification_version: 4
178
203
  summary: Broadcast Calendar navigation in Ruby made simple
179
204
  test_files:
180
205
  - spec/calendar/day_spec.rb
181
206
  - spec/calendar/quarter_spec.rb
182
- - spec/calendar/support/month_based_spec.rb
207
+ - spec/calendar/support/monthly_unit_spec.rb
183
208
  - spec/calendar/support/unit_spec.rb
184
209
  - spec/calendar/week_spec.rb
185
210
  - spec/calendars/broadcast_spec.rb