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.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +5 -0
- data/.replit +2 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +76 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +233 -0
- data/Rakefile +5 -0
- data/bin/tbsh +15 -0
- data/lib/tasks/calendars.rake +22 -0
- data/lib/tasks/timeboss.rake +6 -0
- data/lib/timeboss.rb +6 -0
- data/lib/timeboss/calendar.rb +64 -0
- data/lib/timeboss/calendar/day.rb +48 -0
- data/lib/timeboss/calendar/half.rb +22 -0
- data/lib/timeboss/calendar/month.rb +22 -0
- data/lib/timeboss/calendar/parser.rb +53 -0
- data/lib/timeboss/calendar/period.rb +154 -0
- data/lib/timeboss/calendar/quarter.rb +22 -0
- data/lib/timeboss/calendar/support/formatter.rb +33 -0
- data/lib/timeboss/calendar/support/month_basis.rb +21 -0
- data/lib/timeboss/calendar/support/monthly_unit.rb +55 -0
- data/lib/timeboss/calendar/support/navigable.rb +72 -0
- data/lib/timeboss/calendar/support/shiftable.rb +241 -0
- data/lib/timeboss/calendar/support/translatable.rb +93 -0
- data/lib/timeboss/calendar/support/unit.rb +88 -0
- data/lib/timeboss/calendar/waypoints.rb +12 -0
- data/lib/timeboss/calendar/waypoints/absolute.rb +113 -0
- data/lib/timeboss/calendar/waypoints/relative.rb +267 -0
- data/lib/timeboss/calendar/week.rb +53 -0
- data/lib/timeboss/calendar/year.rb +18 -0
- data/lib/timeboss/calendars.rb +53 -0
- data/lib/timeboss/calendars/broadcast.rb +32 -0
- data/lib/timeboss/calendars/gregorian.rb +30 -0
- data/lib/timeboss/support/shellable.rb +17 -0
- data/lib/timeboss/version.rb +4 -0
- data/spec/calendar/day_spec.rb +60 -0
- data/spec/calendar/quarter_spec.rb +32 -0
- data/spec/calendar/support/monthly_unit_spec.rb +85 -0
- data/spec/calendar/support/unit_spec.rb +90 -0
- data/spec/calendar/week_spec.rb +80 -0
- data/spec/calendars/broadcast_spec.rb +796 -0
- data/spec/calendars/gregorian_spec.rb +684 -0
- data/spec/calendars_spec.rb +50 -0
- data/spec/spec_helper.rb +12 -0
- data/timeboss.gemspec +31 -0
- metadata +215 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module TimeBoss
|
2
|
+
class Calendar
|
3
|
+
module Support
|
4
|
+
# @abstract
|
5
|
+
# A MonthBasis must define a `#start_date` and `#end_date` method.
|
6
|
+
# These methods should be calculated based on the incoming `#year` and `#month` values.
|
7
|
+
class MonthBasis
|
8
|
+
attr_reader :year, :month
|
9
|
+
|
10
|
+
def initialize(year, month)
|
11
|
+
@year = year
|
12
|
+
@month = month
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_range
|
16
|
+
@_to_range ||= start_date .. end_date
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative './unit'
|
3
|
+
|
4
|
+
module TimeBoss
|
5
|
+
class Calendar
|
6
|
+
module Support
|
7
|
+
class MonthlyUnit < Unit
|
8
|
+
attr_reader :year_index, :index
|
9
|
+
|
10
|
+
def initialize(calendar, year_index, index, start_date, end_date)
|
11
|
+
super(calendar, start_date, end_date)
|
12
|
+
@year_index = year_index
|
13
|
+
@index = index
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get a stringified representation of this unit.
|
17
|
+
# @return [String] (e.g. "2020Q3: 2020-06-29 thru 2020-09-27")
|
18
|
+
def to_s
|
19
|
+
"#{name}: #{start_date} thru #{end_date}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get a list of weeks contained within this period.
|
23
|
+
# @return [Array<Week>]
|
24
|
+
def weeks
|
25
|
+
base = calendar.year(year_index)
|
26
|
+
num_weeks = (((base.end_date - base.start_date) + 1) / 7.0).to_i
|
27
|
+
num_weeks.times.map { |i| Week.new(calendar, base.start_date + (i * 7).days, base.start_date + ((i * 7) + 6).days) }
|
28
|
+
.select { |w| w.start_date.between?(start_date, end_date) }
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def max_index
|
34
|
+
12 / self.class::NUM_MONTHS
|
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
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
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
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module TimeBoss
|
3
|
+
class Calendar
|
4
|
+
module Support
|
5
|
+
module Shiftable
|
6
|
+
Support::Translatable::PERIODS.each do |period|
|
7
|
+
periods = period.pluralize
|
8
|
+
|
9
|
+
define_method("in_#{period}") do
|
10
|
+
base = send(periods)
|
11
|
+
return unless base.length == 1
|
12
|
+
base.first.send(self.class.type.to_s.pluralize).find_index { |p| p == self } + 1
|
13
|
+
end
|
14
|
+
|
15
|
+
define_method("#{periods}_ago") do |offset|
|
16
|
+
base_offset = send("in_#{period}") or return
|
17
|
+
(calendar.send("this_#{period}") - offset).send(self.class.type.to_s.pluralize)[base_offset - 1]
|
18
|
+
end
|
19
|
+
|
20
|
+
define_method("#{periods}_ahead") { |o| send("#{periods}_ago", o * -1) }
|
21
|
+
|
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
|
26
|
+
|
27
|
+
alias_method :yesterday, :last_day
|
28
|
+
alias_method :today, :this_day
|
29
|
+
alias_method :tomorrow, :next_day
|
30
|
+
|
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]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module TimeBoss
|
3
|
+
class Calendar
|
4
|
+
module Support
|
5
|
+
module Translatable
|
6
|
+
PERIODS = %w[day week month quarter half year]
|
7
|
+
|
8
|
+
PERIODS.each do |period|
|
9
|
+
periods = period.pluralize
|
10
|
+
|
11
|
+
define_method(periods) { calendar.send("#{periods}_for", self) }
|
12
|
+
|
13
|
+
define_method(period) do |index = nil|
|
14
|
+
entries = send(periods)
|
15
|
+
return entries[index - 1] unless index.nil?
|
16
|
+
return nil unless entries.length == 1
|
17
|
+
entries.first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# i hate this
|
23
|
+
#
|
24
|
+
|
25
|
+
### Days
|
26
|
+
|
27
|
+
# @!method days
|
28
|
+
# Get a list of days that fall within this unit.
|
29
|
+
# @return [Array<Calendar::Day>]
|
30
|
+
|
31
|
+
# @!method day(index = nil)
|
32
|
+
# Get the day this unit represents.
|
33
|
+
# Returns nil if no single day can be identified.
|
34
|
+
# @return [Array<Calendar::Day>, nil]
|
35
|
+
|
36
|
+
### Weeks
|
37
|
+
|
38
|
+
# @!method weeks
|
39
|
+
# Get a list of weeks that fall within this unit.
|
40
|
+
# @return [Array<Calendar::Week>]
|
41
|
+
|
42
|
+
# @!method week(index = nil)
|
43
|
+
# Get the week this unit represents.
|
44
|
+
# Returns nil if no single week can be identified.
|
45
|
+
# @return [Array<Calendar::Week>, nil]
|
46
|
+
|
47
|
+
### Months
|
48
|
+
|
49
|
+
# @!method months
|
50
|
+
# Get a list of months that fall within this unit.
|
51
|
+
# @return [Array<Calendar::Month>]
|
52
|
+
|
53
|
+
# @!method month(index = nil)
|
54
|
+
# Get the month this unit represents.
|
55
|
+
# Returns nil if no single month can be identified.
|
56
|
+
# @return [Array<Calendar::Month>, nil]
|
57
|
+
|
58
|
+
### Quarters
|
59
|
+
|
60
|
+
# @!method quarters
|
61
|
+
# Get a list of quarters that fall within this unit.
|
62
|
+
# @return [Array<Calendar::Quarter>]
|
63
|
+
|
64
|
+
# @!method quarter(index = nil)
|
65
|
+
# Get the quarter this unit represents.
|
66
|
+
# Returns nil if no single quarter can be identified.
|
67
|
+
# @return [Array<Calendar::Quarter>, nil]
|
68
|
+
|
69
|
+
### Halves
|
70
|
+
|
71
|
+
# @!method halves
|
72
|
+
# Get a list of halves that fall within this unit.
|
73
|
+
# @return [Array<Calendar::Half>]
|
74
|
+
|
75
|
+
# @!method half(index = nil)
|
76
|
+
# Get the half this unit represents.
|
77
|
+
# Returns nil if no single half can be identified.
|
78
|
+
# @return [Array<Calendar::Half>, nil]
|
79
|
+
|
80
|
+
### Years
|
81
|
+
|
82
|
+
# @!method years
|
83
|
+
# Get a list of years that fall within this unit.
|
84
|
+
# @return [Array<Calendar::Year>]
|
85
|
+
|
86
|
+
# @!method year(index = nil)
|
87
|
+
# Get the year this unit represents.
|
88
|
+
# Returns nil if no single year can be identified.
|
89
|
+
# @return [Array<Calendar::Year>, nil]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|