timeboss 0.0.7 → 0.1.1

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