timeboss 0.0.8 → 0.2.0

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 (36) 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 +29 -11
  8. data/lib/timeboss.rb +4 -0
  9. data/lib/timeboss/calendar.rb +17 -0
  10. data/lib/timeboss/calendar/day.rb +18 -6
  11. data/lib/timeboss/calendar/half.rb +6 -2
  12. data/lib/timeboss/calendar/month.rb +6 -2
  13. data/lib/timeboss/calendar/period.rb +25 -11
  14. data/lib/timeboss/calendar/quarter.rb +6 -2
  15. data/lib/timeboss/calendar/support/formatter.rb +4 -2
  16. data/lib/timeboss/calendar/support/month_basis.rb +1 -0
  17. data/lib/timeboss/calendar/support/{month_based.rb → monthly_unit.rb} +22 -18
  18. data/lib/timeboss/calendar/support/navigable.rb +72 -0
  19. data/lib/timeboss/calendar/support/shiftable.rb +218 -28
  20. data/lib/timeboss/calendar/support/translatable.rb +92 -0
  21. data/lib/timeboss/calendar/support/unit.rb +29 -0
  22. data/lib/timeboss/calendar/waypoints.rb +5 -80
  23. data/lib/timeboss/calendar/waypoints/absolute.rb +113 -0
  24. data/lib/timeboss/calendar/waypoints/relative.rb +267 -0
  25. data/lib/timeboss/calendar/week.rb +26 -18
  26. data/lib/timeboss/calendar/year.rb +5 -5
  27. data/lib/timeboss/calendars.rb +15 -0
  28. data/lib/timeboss/calendars/broadcast.rb +4 -0
  29. data/lib/timeboss/calendars/gregorian.rb +24 -0
  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} +24 -8
  33. data/spec/calendar/week_spec.rb +11 -14
  34. data/spec/calendars/broadcast_spec.rb +27 -7
  35. data/timeboss.gemspec +1 -0
  36. metadata +28 -5
@@ -1,15 +1,19 @@
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 Quarter < Support::MonthBased
6
+ class Quarter < Support::MonthlyUnit
7
7
  NUM_MONTHS = 3
8
8
 
9
+ # Get a simple representation of this quarter.
10
+ # @return [String] (e.g. "2020Q3")
9
11
  def name
10
12
  "#{year_index}Q#{index}"
11
13
  end
12
14
 
15
+ # Get a "pretty" representation of this quarter.
16
+ # @return [String] (e.g. "Q3 2020")
13
17
  def title
14
18
  "Q#{index} #{year_index}"
15
19
  end
@@ -1,18 +1,20 @@
1
1
  # frozen_string_literal: true
2
- require_relative './shiftable'
2
+ require_relative './translatable'
3
3
 
4
4
  module TimeBoss
5
5
  class Calendar
6
6
  module Support
7
7
  private
8
8
 
9
+ # The formatter is responsible for the implementation of name formatting for a unit.
9
10
  class Formatter
10
- PERIODS = Shiftable::PERIODS.reverse.map(&:to_sym).drop(1)
11
+ PERIODS = Translatable::PERIODS.reverse.map(&:to_sym).drop(1)
11
12
  attr_reader :unit, :periods
12
13
 
13
14
  def initialize(unit, periods)
14
15
  @unit = unit
15
16
  @periods = PERIODS & periods.map(&:to_sym).push(unit.class.type.to_sym)
17
+ @periods -= [:week] unless unit.calendar.supports_weeks?
16
18
  end
17
19
 
18
20
  def to_s
@@ -1,6 +1,7 @@
1
1
  module TimeBoss
2
2
  class Calendar
3
3
  module Support
4
+ # @abstract
4
5
  class MonthBasis
5
6
  attr_reader :year, :month
6
7
 
@@ -4,7 +4,7 @@ require_relative './unit'
4
4
  module TimeBoss
5
5
  class Calendar
6
6
  module Support
7
- class MonthBased < Unit
7
+ class MonthlyUnit < Unit
8
8
  attr_reader :year_index, :index
9
9
 
10
10
  def initialize(calendar, year_index, index, start_date, end_date)
@@ -13,30 +13,18 @@ module TimeBoss
13
13
  @index = index
14
14
  end
15
15
 
16
- def next
17
- if index == max_index
18
- calendar.send(self.class.type, year_index + 1, 1)
19
- else
20
- calendar.send(self.class.type, year_index, index + 1)
21
- end
22
- end
23
-
24
- def previous
25
- if index == 1
26
- calendar.send(self.class.type, year_index - 1, max_index)
27
- else
28
- calendar.send(self.class.type, year_index, index - 1)
29
- end
30
- end
31
-
16
+ # Get a stringified representation of this unit.
17
+ # @return [String] (e.g. "2020Q3: 2020-06-29 thru 2020-09-27")
32
18
  def to_s
33
19
  "#{name}: #{start_date} thru #{end_date}"
34
20
  end
35
21
 
22
+ # Get a list of weeks contained within this period.
23
+ # @return [Array<Week>]
36
24
  def weeks
37
25
  base = calendar.year(year_index)
38
26
  num_weeks = (((base.end_date - base.start_date) + 1) / 7.0).to_i
39
- num_weeks.times.map { |i| Week.new(calendar, year_index, i + 1, base.start_date + (i * 7).days, base.start_date + ((i * 7) + 6).days) }
27
+ num_weeks.times.map { |i| Week.new(calendar, base.start_date + (i * 7).days, base.start_date + ((i * 7) + 6).days) }
40
28
  .select { |w| w.start_date.between?(start_date, end_date) }
41
29
  end
42
30
 
@@ -45,6 +33,22 @@ module TimeBoss
45
33
  def max_index
46
34
  12 / self.class::NUM_MONTHS
47
35
  end
36
+
37
+ def up
38
+ if index == max_index
39
+ calendar.send(self.class.type, year_index + 1, 1)
40
+ else
41
+ calendar.send(self.class.type, year_index, index + 1)
42
+ end
43
+ end
44
+
45
+ def down
46
+ if index == 1
47
+ calendar.send(self.class.type, year_index - 1, max_index)
48
+ else
49
+ calendar.send(self.class.type, year_index, index - 1)
50
+ end
51
+ end
48
52
  end
49
53
  end
50
54
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+ module TimeBoss
3
+ class Calendar
4
+ module Support
5
+ module Navigable
6
+ # @overload previous
7
+ # Fetch the previous unit relative to this unit.
8
+ # @return [Unit]
9
+ # @overload previous(value)
10
+ # Fetch some previous number of units relative to this unit
11
+ # @param quantity [Integer]
12
+ # @return [Array<Unit>]
13
+ def previous(quantity = nil)
14
+ return down if quantity.nil?
15
+ gather(:previous, quantity).reverse
16
+ end
17
+
18
+ # @overload next
19
+ # Fetch the next unit relative to this unit.
20
+ # @return [Unit]
21
+ # @overload next(value)
22
+ # Fetch some next number of units relative to this unit
23
+ # @param quantity [Integer]
24
+ # @return [Array<Unit>]
25
+ def next(quantity = nil)
26
+ return up if quantity.nil?
27
+ gather(:next, quantity)
28
+ end
29
+
30
+ # Fetch the unit some number of units prior to this unit.
31
+ # @param quantity [Integer]
32
+ # @return [Unit]
33
+ def ago(quantity)
34
+ previous(quantity + 1).first
35
+ end
36
+
37
+ # Fetch the unit some number of units after this unit.
38
+ # @param quantity [Integer]
39
+ # @return [Unit]
40
+ def ahead(quantity)
41
+ self.next(quantity + 1).last
42
+ end
43
+
44
+ # Fetch a list of units from this unit until some date.
45
+ # @param end_date [Date]
46
+ # @return [Array<Unit>]
47
+ def until(end_date)
48
+ entry = self
49
+ [entry].tap do |entries|
50
+ until entry.end_date >= end_date
51
+ entry = entry.next
52
+ entries << entry
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def gather(navigator, quantity)
60
+ [].tap do |entries|
61
+ entry = self
62
+ while quantity > 0
63
+ entries << entry
64
+ entry = entry.send(navigator)
65
+ quantity -= 1
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -3,48 +3,238 @@ module TimeBoss
3
3
  class Calendar
4
4
  module Support
5
5
  module Shiftable
6
- PERIODS = %w[day week month quarter half year]
7
-
8
- PERIODS.each do |period|
6
+ Support::Translatable::PERIODS.each do |period|
9
7
  periods = period.pluralize
10
8
 
11
- define_method periods do
12
- calendar.send("#{periods}_for", self)
13
- end
14
-
15
- define_method period do
16
- entries = send(periods)
17
- return nil unless entries.length == 1
18
- entries.first
19
- end
20
-
21
- define_method "in_#{period}" do
9
+ define_method("in_#{period}") do
22
10
  base = send(periods)
23
11
  return unless base.length == 1
24
12
  base.first.send(self.class.type.to_s.pluralize).find_index { |p| p == self } + 1
25
13
  end
26
14
 
27
- define_method "#{periods}_ago" do |offset|
15
+ define_method("#{periods}_ago") do |offset|
28
16
  base_offset = send("in_#{period}") or return
29
17
  (calendar.send("this_#{period}") - offset).send(self.class.type.to_s.pluralize)[base_offset - 1]
30
18
  end
31
19
 
32
- define_method "last_#{period}" do
33
- send("#{periods}_ago", 1)
34
- end
20
+ define_method("#{periods}_ahead") { |o| send("#{periods}_ago", o * -1) }
35
21
 
36
- define_method "this_#{period}" do
37
- send("#{periods}_ago", 0)
38
- end
22
+ define_method("last_#{period}") { send("#{periods}_ago", 1) }
23
+ define_method("this_#{period}") { send("#{periods}_ago", 0) }
24
+ define_method("next_#{period}") { send("#{periods}_ahead", 1) }
25
+ end
39
26
 
40
- define_method "#{periods}_hence" do |offset|
41
- send("#{periods}_ago", offset * -1)
42
- end
27
+ alias_method :yesterday, :last_day
28
+ alias_method :today, :this_day
29
+ alias_method :tomorrow, :next_day
43
30
 
44
- define_method "next_#{period}" do
45
- send("#{periods}_hence", 1)
46
- end
47
- end
31
+ #
32
+ # i hate this
33
+ #
34
+
35
+ ### Days
36
+
37
+ # @!method in_day
38
+ # Get the index within the day that this unit falls in.
39
+ # Returns nil if no single day can be identified.
40
+ # @return [Integer, nil]
41
+
42
+ # @!method days_ago
43
+ # Get the index-relative day some number of days ago.
44
+ # Returns nil if no single day can be identified.
45
+ # @param offset [Integer] the number of days back to shift this period
46
+ # @return [Calendar::Day, nil]
47
+
48
+ # @!method days_ahead
49
+ # Get the index-relative day some number of days ahead.
50
+ # Returns nil if no single day can be identified.
51
+ # @param offset [Integer] the number of days forward to shift this period
52
+ # @return [Calendar::Day, nil]
53
+
54
+ # @!method last_day
55
+ # Get the index-relative day 1 day ago.
56
+ # Returns nil if no single day can be identified.
57
+ # @return [Calendar::Day, nil]
58
+
59
+ # @!method this_day
60
+ # Get the index-relative day for this day.
61
+ # Returns nil if no single day can be identified.
62
+ # @return [Calendar::Day, nil]
63
+
64
+ # @!method next_day
65
+ # Get the index-relative day 1 day forward.
66
+ # Returns nil if no single day can be identified.
67
+ # @return [Calendar::Day, nil]
68
+
69
+ ### Weeks
70
+
71
+ # @!method in_week
72
+ # Get the index within the week that this unit falls in.
73
+ # Returns nil if no single week can be identified.
74
+ # @return [Integer, nil]
75
+
76
+ # @!method weeks_ago
77
+ # Get the index-relative week some number of weeks ago.
78
+ # Returns nil if no single week can be identified.
79
+ # @param offset [Integer] the number of weeks back to shift this period
80
+ # @return [Calendar::Week, nil]
81
+
82
+ # @!method weeks_ahead
83
+ # Get the index-relative week some number of weeks ahead.
84
+ # Returns nil if no single week can be identified.
85
+ # @param offset [Integer] the number of weeks forward to shift this period
86
+ # @return [Calendar::Week, nil]
87
+
88
+ # @!method last_week
89
+ # Get the index-relative week 1 week ago.
90
+ # Returns nil if no single week can be identified.
91
+ # @return [Calendar::Week, nil]
92
+
93
+ # @!method this_week
94
+ # Get the index-relative week for this week.
95
+ # Returns nil if no single week can be identified.
96
+ # @return [Calendar::Week, nil]
97
+
98
+ # @!method next_week
99
+ # Get the index-relative week 1 week forward.
100
+ # Returns nil if no single week can be identified.
101
+ # @return [Calendar::Week, nil]
102
+
103
+ ### Months
104
+
105
+ # @!method in_month
106
+ # Get the index within the month that this unit falls in.
107
+ # Returns nil if no single month can be identified.
108
+ # @return [Integer, nil]
109
+
110
+ # @!method months_ago
111
+ # Get the index-relative month some number of months ago.
112
+ # Returns nil if no single month can be identified.
113
+ # @param offset [Integer] the number of months back to shift this period
114
+ # @return [Calendar::Month, nil]
115
+
116
+ # @!method months_ahead
117
+ # Get the index-relative month some number of months ahead.
118
+ # Returns nil if no single month can be identified.
119
+ # @param offset [Integer] the number of months forward to shift this period
120
+ # @return [Calendar::Month, nil]
121
+
122
+ # @!method last_month
123
+ # Get the index-relative month 1 month ago.
124
+ # Returns nil if no single month can be identified.
125
+ # @return [Calendar::Month, nil]
126
+
127
+ # @!method this_month
128
+ # Get the index-relative month for this month.
129
+ # Returns nil if no single month can be identified.
130
+ # @return [Calendar::Month, nil]
131
+
132
+ # @!method next_month
133
+ # Get the index-relative month 1 month forward.
134
+ # Returns nil if no single month can be identified.
135
+ # @return [Calendar::Month, nil]
136
+
137
+ ### Quarters
138
+
139
+ # @!method in_quarter
140
+ # Get the index within the quarter that this unit falls in.
141
+ # Returns nil if no single quarter can be identified.
142
+ # @return [Integer, nil]
143
+
144
+ # @!method quarters_ago
145
+ # Get the index-relative quarter some number of quarters ago.
146
+ # Returns nil if no single quarter can be identified.
147
+ # @param offset [Integer] the number of quarters back to shift this period
148
+ # @return [Calendar::Quarter, nil]
149
+
150
+ # @!method quarters_ahead
151
+ # Get the index-relative quarter some number of quarters ahead.
152
+ # Returns nil if no single quarter can be identified.
153
+ # @param offset [Integer] the number of quarters forward to shift this period
154
+ # @return [Calendar::Quarter, nil]
155
+
156
+ # @!method last_quarter
157
+ # Get the index-relative quarter 1 quarter ago.
158
+ # Returns nil if no single quarter can be identified.
159
+ # @return [Calendar::Quarter, nil]
160
+
161
+ # @!method this_quarter
162
+ # Get the index-relative quarter for this quarter.
163
+ # Returns nil if no single quarter can be identified.
164
+ # @return [Calendar::Quarter, nil]
165
+
166
+ # @!method next_quarter
167
+ # Get the index-relative quarter 1 quarter forward.
168
+ # Returns nil if no single quarter can be identified.
169
+ # @return [Calendar::Quarter, nil]
170
+
171
+ ### Halves
172
+
173
+ # @!method in_half
174
+ # Get the index within the half that this unit falls in.
175
+ # Returns nil if no single half can be identified.
176
+ # @return [Integer, nil]
177
+
178
+ # @!method halves_ago
179
+ # Get the index-relative half some number of halves ago.
180
+ # Returns nil if no single half can be identified.
181
+ # @param offset [Integer] the number of halves back to shift this period
182
+ # @return [Calendar::Half, nil]
183
+
184
+ # @!method halves_ahead
185
+ # Get the index-relative half some number of halves ahead.
186
+ # Returns nil if no single half can be identified.
187
+ # @param offset [Integer] the number of halves forward to shift this period
188
+ # @return [Calendar::Half, nil]
189
+
190
+ # @!method last_half
191
+ # Get the index-relative half 1 half ago.
192
+ # Returns nil if no single half can be identified.
193
+ # @return [Calendar::Half, nil]
194
+
195
+ # @!method this_half
196
+ # Get the index-relative half for this half.
197
+ # Returns nil if no single half can be identified.
198
+ # @return [Calendar::Half, nil]
199
+
200
+ # @!method next_half
201
+ # Get the index-relative half 1 half forward.
202
+ # Returns nil if no single half can be identified.
203
+ # @return [Calendar::Half, nil]
204
+
205
+ ### Years
206
+
207
+ # @!method in_year
208
+ # Get the index within the year that this unit falls in.
209
+ # Returns nil if no single year can be identified.
210
+ # @return [Integer, nil]
211
+
212
+ # @!method years_ago
213
+ # Get the index-relative year some number of years ago.
214
+ # Returns nil if no single year can be identified.
215
+ # @param offset [Integer] the number of years back to shift this period
216
+ # @return [Calendar::Year, nil]
217
+
218
+ # @!method years_ahead
219
+ # Get the index-relative year some number of years ahead.
220
+ # Returns nil if no single year can be identified.
221
+ # @param offset [Integer] the number of years forward to shift this period
222
+ # @return [Calendar::Year, nil]
223
+
224
+ # @!method last_year
225
+ # Get the index-relative year 1 year ago.
226
+ # Returns nil if no single year can be identified.
227
+ # @return [Calendar::Year, nil]
228
+
229
+ # @!method this_year
230
+ # Get the index-relative year for this year.
231
+ # Returns nil if no single year can be identified.
232
+ # @return [Calendar::Year, nil]
233
+
234
+ # @!method next_year
235
+ # Get the index-relative year 1 year forward.
236
+ # Returns nil if no single year can be identified.
237
+ # @return [Calendar::Year, nil]
48
238
  end
49
239
  end
50
240
  end