timeboss 0.3.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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.gitignore +5 -0
  5. data/.replit +2 -0
  6. data/.rspec +2 -0
  7. data/.travis.yml +16 -0
  8. data/.yardopts +1 -0
  9. data/CODE_OF_CONDUCT.md +76 -0
  10. data/Gemfile +3 -0
  11. data/LICENSE.txt +22 -0
  12. data/README.md +233 -0
  13. data/Rakefile +5 -0
  14. data/bin/tbsh +15 -0
  15. data/lib/tasks/calendars.rake +22 -0
  16. data/lib/tasks/timeboss.rake +6 -0
  17. data/lib/timeboss.rb +6 -0
  18. data/lib/timeboss/calendar.rb +64 -0
  19. data/lib/timeboss/calendar/day.rb +48 -0
  20. data/lib/timeboss/calendar/half.rb +22 -0
  21. data/lib/timeboss/calendar/month.rb +22 -0
  22. data/lib/timeboss/calendar/parser.rb +53 -0
  23. data/lib/timeboss/calendar/period.rb +154 -0
  24. data/lib/timeboss/calendar/quarter.rb +22 -0
  25. data/lib/timeboss/calendar/support/formatter.rb +33 -0
  26. data/lib/timeboss/calendar/support/month_basis.rb +21 -0
  27. data/lib/timeboss/calendar/support/monthly_unit.rb +55 -0
  28. data/lib/timeboss/calendar/support/navigable.rb +72 -0
  29. data/lib/timeboss/calendar/support/shiftable.rb +241 -0
  30. data/lib/timeboss/calendar/support/translatable.rb +93 -0
  31. data/lib/timeboss/calendar/support/unit.rb +88 -0
  32. data/lib/timeboss/calendar/waypoints.rb +12 -0
  33. data/lib/timeboss/calendar/waypoints/absolute.rb +113 -0
  34. data/lib/timeboss/calendar/waypoints/relative.rb +267 -0
  35. data/lib/timeboss/calendar/week.rb +53 -0
  36. data/lib/timeboss/calendar/year.rb +18 -0
  37. data/lib/timeboss/calendars.rb +53 -0
  38. data/lib/timeboss/calendars/broadcast.rb +32 -0
  39. data/lib/timeboss/calendars/gregorian.rb +30 -0
  40. data/lib/timeboss/support/shellable.rb +17 -0
  41. data/lib/timeboss/version.rb +4 -0
  42. data/spec/calendar/day_spec.rb +60 -0
  43. data/spec/calendar/quarter_spec.rb +32 -0
  44. data/spec/calendar/support/monthly_unit_spec.rb +85 -0
  45. data/spec/calendar/support/unit_spec.rb +90 -0
  46. data/spec/calendar/week_spec.rb +80 -0
  47. data/spec/calendars/broadcast_spec.rb +796 -0
  48. data/spec/calendars/gregorian_spec.rb +684 -0
  49. data/spec/calendars_spec.rb +50 -0
  50. data/spec/spec_helper.rb +12 -0
  51. data/timeboss.gemspec +31 -0
  52. metadata +215 -0
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ require_relative './navigable'
3
+ require_relative './translatable'
4
+ require_relative './shiftable'
5
+ require_relative './formatter'
6
+
7
+ module TimeBoss
8
+ class Calendar
9
+ module Support
10
+ class Unit
11
+ include Navigable
12
+ include Translatable
13
+ include Shiftable
14
+ attr_reader :calendar, :start_date, :end_date
15
+
16
+ UnsupportedUnitError = Class.new(StandardError)
17
+
18
+ def self.type
19
+ self.name.demodulize.underscore
20
+ end
21
+
22
+ def initialize(calendar, start_date, end_date)
23
+ @calendar = calendar
24
+ @start_date = start_date
25
+ @end_date = end_date
26
+ end
27
+
28
+ # Is the specified unit equal to this one, based on its unit type and date range?
29
+ # @param entry [Unit] the unit to compare
30
+ # @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
33
+ end
34
+
35
+ # Format this period based on specified granularities.
36
+ # @param periods [Array<Symbol, String>] the periods to include (`half, week`, or `quarter`)
37
+ # @return [String] (e.g. "2020H2W7" or "2020Q3")
38
+ def format(*periods)
39
+ Formatter.new(self, periods.presence || Formatter::PERIODS).to_s
40
+ end
41
+
42
+ # Starting from this unit of time, build a period extending through the specified time unit.
43
+ # @param unit [Unit] the period to extend through
44
+ # @return [Period]
45
+ def thru(unit)
46
+ Period.new(calendar, self, unit)
47
+ end
48
+
49
+ # Does this period cover the current date?
50
+ # @return [Boolean]
51
+ def current?
52
+ Date.today.between?(start_date, end_date)
53
+ end
54
+
55
+ # Return the unit relative to this one by the specified offset.
56
+ # Offset values can be positive or negative.
57
+ # @param value [Integer]
58
+ # @return [Unit]
59
+ def offset(value)
60
+ method = value.negative? ? :previous : :next
61
+ base = self
62
+ value.abs.times { base = base.send(method) }
63
+ base
64
+ end
65
+
66
+ # Move some number of units forward from this unit.
67
+ # @param value [Integer]
68
+ # @return [Unit]
69
+ def +(value)
70
+ offset(value)
71
+ end
72
+
73
+ # Move some number of units backward from this unit.
74
+ # @param value [Integer]
75
+ # @return [Unit]
76
+ def -(value)
77
+ offset(-value)
78
+ end
79
+
80
+ # Express this period as a date range.
81
+ # @return [Range<Date, Date>]
82
+ def to_range
83
+ @_to_range ||= start_date .. end_date
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ %w[absolute relative].each { |f| require_relative "./waypoints/#{f}" }
4
+
5
+ module TimeBoss
6
+ class Calendar
7
+ module Waypoints
8
+ include Absolute
9
+ include Relative
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+ module TimeBoss
3
+ class Calendar
4
+ module Waypoints
5
+ module Absolute
6
+ %i[month quarter half year].each do |type|
7
+ klass = TimeBoss::Calendar.const_get(type.to_s.classify)
8
+ size = klass.const_get("NUM_MONTHS")
9
+
10
+ define_method type do |year_index, index = 1|
11
+ month = (index * size) - size + 1
12
+ months = (month .. month + size - 1).map { |i| basis.new(year_index, i) }
13
+ klass.new(self, year_index, index, months.first.start_date, months.last.end_date)
14
+ end
15
+
16
+ define_method "#{type}_for" do |date|
17
+ window = send(type, date.year - 1, 1)
18
+ while true
19
+ break window if window.to_range.include?(date)
20
+ window = window.next
21
+ end
22
+ end
23
+ end
24
+
25
+ # Get the specified week by index within the specified year.
26
+ # @param year_index [Integer] the year to examine
27
+ # @param index [Integer] the index of the week within the year
28
+ # @return [Calendar::Week]
29
+ def week(year_index, index)
30
+ year(year_index).weeks[index - 1]
31
+ end
32
+
33
+ # Get the week that contains the specified date.
34
+ # @param date [Date] the date for which to locate the calendar week
35
+ # @return [Calendar::Week]
36
+ def week_for(date)
37
+ year_for(date).weeks.find { |w| w.to_range.include?(date) }
38
+ end
39
+
40
+ # Get the specified day by index within the specified year.
41
+ # @param year_index [Integer] the year to examine
42
+ # @param index [Integer] the index of the day within the year
43
+ # @return [Calendar::Day]
44
+ def day(year_index, index)
45
+ year(year_index).days[index - 1]
46
+ end
47
+
48
+ # Get the day that contains the specified date.
49
+ # @param date [Date] the date for which to locate the calendar day
50
+ # @return [Calendar::Day]
51
+ def day_for(date)
52
+ Day.new(self, date)
53
+ end
54
+
55
+ #
56
+ # i hate this
57
+ #
58
+
59
+ ### Month
60
+
61
+ # @!method month
62
+ # Get the specified month by index within the specified year
63
+ # @param year_index [Integer] the year to examine
64
+ # @param index [Integer] the index of the month within the year
65
+ # @return [Calendar::Month]
66
+
67
+ # @!method month_for
68
+ # Get the month that contains the specified date.
69
+ # @param date [Date] the date for which to locate the calendar month
70
+ # @return [Calendar::Month]
71
+
72
+ ### Quarter
73
+
74
+ # @!method quarter
75
+ # Get the specified quarter by index within the specified year
76
+ # @param year_index [Integer] the year to examine
77
+ # @param index [Integer] the index of the quarter within the year
78
+ # @return [Calendar::Quarter]
79
+
80
+ # @!method quarter_for
81
+ # Get the quarter that contains the specified date.
82
+ # @param date [Date] the date for which to locate the calendar quarter
83
+ # @return [Calendar::Quarter]
84
+
85
+ ### Half
86
+
87
+ # @!method half
88
+ # Get the specified half by index within the specified year
89
+ # @param year_index [Integer] the year to examine
90
+ # @param index [Integer] the index of the half within the year
91
+ # @return [Calendar::Half]
92
+
93
+ # @!method half_for
94
+ # Get the half that contains the specified date.
95
+ # @param date [Date] the date for which to locate the calendar half
96
+ # @return [Calendar::Half]
97
+
98
+ ### Year
99
+
100
+ # @!method year
101
+ # Get the specified year by index within the specified year
102
+ # @param year_index [Integer] the year to examine
103
+ # @param index [Integer] the index of the year within the year
104
+ # @return [Calendar::Year]
105
+
106
+ # @!method year_for
107
+ # Get the year that contains the specified date.
108
+ # @param date [Date] the date for which to locate the calendar year
109
+ # @return [Calendar::Year]
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,267 @@
1
+ # frozen_string_literal: true
2
+ module TimeBoss
3
+ class Calendar
4
+ module Waypoints
5
+ module Relative
6
+ %i[day week month quarter half year].each do |type|
7
+ types = type.to_s.pluralize
8
+
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 }
12
+
13
+ define_method("#{types}_for") { |p| send("#{type}_for", p.start_date).until(p.end_date) }
14
+
15
+ define_method("#{types}_back") { |q| send("this_#{type}").previous(q) }
16
+ define_method("#{types}_ago") { |q| send("this_#{type}").ago(q) }
17
+
18
+ define_method("#{types}_forward") { |q| send("this_#{type}").next(q) }
19
+ define_method("#{types}_ahead") { |q| send("this_#{type}").ahead(q) }
20
+ alias_method types.to_sym, "#{types}_forward".to_sym
21
+ end
22
+
23
+ alias_method :yesterday, :last_day
24
+ alias_method :today, :this_day
25
+ alias_method :tomorrow, :next_day
26
+
27
+ #
28
+ # i hate this
29
+ #
30
+
31
+ ### Days
32
+
33
+ # @!method this_day
34
+ # Get the current day within the active calendar.
35
+ # @return [Calendar::Day]
36
+
37
+ # @!method last_day
38
+ # Get the previous day within the active calendar.
39
+ # @return [Calendar::Day]
40
+
41
+ # @!method next_day
42
+ # Get the next day within the active calendar.
43
+ # @return [Calendar::Day]
44
+
45
+ # @!method days_for
46
+ # Get a list of days within the specified period unit.
47
+ # @param period [Calendar::Support::Unit] the containing period unit
48
+ # @return [Array<Calendar::Day>]
49
+
50
+ # @!method days_back
51
+ # Get a quantity of days back from today.
52
+ # @param quantity [Integer] the number of days requested
53
+ # @return [Array<Calendar::Day>]
54
+
55
+ # @!method days_ago
56
+ # Get the day that occurred the specified number of days ago.
57
+ # @param quantity [Integer] the number of days before today
58
+ # @return [Calendar::Day]
59
+
60
+ # @!method days_forward
61
+ # Get a quantity of days forward from today.
62
+ # @param quantity [Integer] the number of days requested
63
+ # @return [Array<Calendar::Day>]
64
+
65
+ # @!method days_ahead
66
+ # Get the day that occurred the specified number of days ahead.
67
+ # @param quantity [Integer] the number of days after today
68
+ # @return [Calendar::Day]
69
+
70
+ ### Weeks
71
+
72
+ # @!method this_week
73
+ # Get the current week within the active calendar.
74
+ # @return [Calendar::Week]
75
+
76
+ # @!method last_week
77
+ # Get the previous week within the active calendar.
78
+ # @return [Calendar::Week]
79
+
80
+ # @!method next_week
81
+ # Get the next week within the active calendar.
82
+ # @return [Calendar::Week]
83
+
84
+ # @!method weeks_for
85
+ # Get a list of weeks within the specified period unit.
86
+ # @param period [Calendar::Support::Unit] the containing period unit
87
+ # @return [Array<Calendar::Week>]
88
+
89
+ # @!method weeks_back
90
+ # Get a quantity of weeks back from this week.
91
+ # @param quantity [Integer] the number of weeks requested
92
+ # @return [Array<Calendar::Week>]
93
+
94
+ # @!method weeks_ago
95
+ # Get the week that occurred the specified number of weeks ago.
96
+ # @param quantity [Integer] the number of weeks before this week
97
+ # @return [Calendar::Week]
98
+
99
+ # @!method weeks_forward
100
+ # Get a quantity of weeks forward from this week.
101
+ # @param quantity [Integer] the number of weeks requested
102
+ # @return [Array<Calendar::Week>]
103
+
104
+ # @!method weeks_ahead
105
+ # Get the week that occurred the specified number of weeks ahead.
106
+ # @param quantity [Integer] the number of weeks after this week
107
+ # @return [Calendar::Week]
108
+
109
+ ### Months
110
+
111
+ # @!method this_month
112
+ # Get the current month within the active calendar.
113
+ # @return [Calendar::Month]
114
+
115
+ # @!method last_month
116
+ # Get the previous month within the active calendar.
117
+ # @return [Calendar::Month]
118
+
119
+ # @!method next_month
120
+ # Get the next month within the active calendar.
121
+ # @return [Calendar::Month]
122
+
123
+ # @!method months_for
124
+ # Get a list of months within the specified period unit.
125
+ # @param period [Calendar::Support::Unit] the containing period unit
126
+ # @return [Array<Calendar::Month>]
127
+
128
+ # @!method months_back
129
+ # Get a quantity of months back from this month.
130
+ # @param quantity [Integer] the number of months requested
131
+ # @return [Array<Calendar::Month>]
132
+
133
+ # @!method months_ago
134
+ # Get the month that occurred the specified number of months ago.
135
+ # @param quantity [Integer] the number of months before this month
136
+ # @return [Calendar::Month]
137
+
138
+ # @!method months_forward
139
+ # Get a quantity of months forward from this month.
140
+ # @param quantity [Integer] the number of months requested
141
+ # @return [Array<Calendar::Month>]
142
+
143
+ # @!method months_ahead
144
+ # Get the month that occurred the specified number of months ahead.
145
+ # @param quantity [Integer] the number of months after this month
146
+ # @return [Calendar::Month]
147
+
148
+ ### Quarters
149
+
150
+ # @!method this_quarter
151
+ # Get the current quarter within the active calendar.
152
+ # @return [Calendar::Quarter]
153
+
154
+ # @!method last_quarter
155
+ # Get the previous quarter within the active calendar.
156
+ # @return [Calendar::Quarter]
157
+
158
+ # @!method next_quarter
159
+ # Get the next quarter within the active calendar.
160
+ # @return [Calendar::Quarter]
161
+
162
+ # @!method quarters_for
163
+ # Get a list of quarters within the specified period unit.
164
+ # @param period [Calendar::Support::Unit] the containing period unit
165
+ # @return [Array<Calendar::Quarter>]
166
+
167
+ # @!method quarters_back
168
+ # Get a quantity of quarters back from this quarter.
169
+ # @param quantity [Integer] the number of quarters requested
170
+ # @return [Array<Calendar::Quarter>]
171
+
172
+ # @!method quarters_ago
173
+ # Get the quarter that occurred the specified number of quarters ago.
174
+ # @param quantity [Integer] the number of quarters before this quarter
175
+ # @return [Calendar::Quarter]
176
+
177
+ # @!method quarters_forward
178
+ # Get a quantity of quarters forward from this quarter.
179
+ # @param quantity [Integer] the number of quarters requested
180
+ # @return [Array<Calendar::Quarter>]
181
+
182
+ # @!method quarters_ahead
183
+ # Get the quarter that occurred the specified number of days ahead.
184
+ # @param quantity [Integer] the number of quarters after this quarter
185
+ # @return [Calendar::Quarter]
186
+
187
+ ### Halves
188
+
189
+ # @!method this_half
190
+ # Get the current half within the active calendar.
191
+ # @return [Calendar::Half]
192
+
193
+ # @!method last_half
194
+ # Get the previous half within the active calendar.
195
+ # @return [Calendar::Half]
196
+
197
+ # @!method next_half
198
+ # Get the next half within the active calendar.
199
+ # @return [Calendar::Half]
200
+
201
+ # @!method halves_for
202
+ # Get a list of halves within the specified period unit.
203
+ # @param period [Calendar::Support::Unit] the containing period unit
204
+ # @return [Array<Calendar::Half>]
205
+
206
+ # @!method halves_back
207
+ # Get a quantity of halves back from this half.
208
+ # @param quantity [Integer] the number of halves requested
209
+ # @return [Array<Calendar::Half>]
210
+
211
+ # @!method halves_ago
212
+ # Get the half that occurred the specified number of halves ago.
213
+ # @param quantity [Integer] the number of halves before this half
214
+ # @return [Calendar::Half]
215
+
216
+ # @!method halves_forward
217
+ # Get a quantity of halves forward from this half.
218
+ # @param quantity [Integer] the number of halves requested
219
+ # @return [Array<Calendar::Half>]
220
+
221
+ # @!method halves_ahead
222
+ # Get the half that occurred the specified number of halves ahead.
223
+ # @param quantity [Integer] the number of halves after this half
224
+ # @return [Calendar::Half]
225
+
226
+ ### Years
227
+
228
+ # @!method this_year
229
+ # Get the current year within the active calendar.
230
+ # @return [Calendar::Year]
231
+
232
+ # @!method last_year
233
+ # Get the previous year within the active calendar.
234
+ # @return [Calendar::Year]
235
+
236
+ # @!method next_year
237
+ # Get the next year within the active calendar.
238
+ # @return [Calendar::Year]
239
+
240
+ # @!method years_for
241
+ # Get a list of years within the specified period unit.
242
+ # @param period [Calendar::Support::Unit] the containing period unit
243
+ # @return [Array<Calendar::Year>]
244
+
245
+ # @!method years_back
246
+ # Get a quantity of years back from this year.
247
+ # @param quantity [Integer] the number of years requested
248
+ # @return [Array<Calendar::Year>]
249
+
250
+ # @!method years_ago
251
+ # Get the year that occurred the specified number of years ago.
252
+ # @param quantity [Integer] the number of years before this year
253
+ # @return [Calendar::Year]
254
+
255
+ # @!method years_forward
256
+ # Get a quantity of years forward from this year.
257
+ # @param quantity [Integer] the number of years requested
258
+ # @return [Array<Calendar::Year>]
259
+
260
+ # @!method years_ahead
261
+ # Get the year that occurred the specified number of years ahead.
262
+ # @param quantity [Integer] the number of years after this year
263
+ # @return [Calendar::Year]
264
+ end
265
+ end
266
+ end
267
+ end