timeboss 0.3.1

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