sof-cycle 0.1.13 → 0.1.15

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.
data/lib/sof/time_span.rb DELETED
@@ -1,234 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SOF
4
- # This class is not intended to be referenced directly.
5
- # This is an internal implementation of Cycle behavior.
6
- class TimeSpan
7
- extend Forwardable
8
- # TimeSpan objects map Cycle notations to behaviors for their periods
9
- #
10
- # For example:
11
- # 'M' => TimeSpan::DatePeriod::Month
12
- # 'Y' => TimeSpan::DatePeriod::Year
13
- # Read each DatePeriod subclass for more information.
14
- #
15
- class InvalidPeriod < StandardError; end
16
-
17
- class << self
18
- # Return a time_span for the given count and period
19
- def for(count, period)
20
- case count.to_i
21
- when 0
22
- TimeSpanNothing
23
- when 1
24
- TimeSpanOne
25
- else
26
- self
27
- end.new(count, period)
28
- end
29
-
30
- # Return a notation string from a hash
31
- def notation(hash)
32
- return unless hash.key?(:period) && hash[:period].present?
33
-
34
- [
35
- hash.fetch(:period_count) { 1 },
36
- notation_id_from_name(hash[:period])
37
- ].compact.join
38
- end
39
-
40
- # Return the notation character for the given period name
41
- def notation_id_from_name(name)
42
- type = DatePeriod.types.find do |klass|
43
- klass.period.to_s == name.to_s
44
- end
45
-
46
- raise InvalidPeriod, "'#{name}' is not a valid period" unless type
47
-
48
- type.code
49
- end
50
- end
51
-
52
- def notation
53
- [period_count, code].join
54
- end
55
-
56
- # Class used to calculate the windows of time so that
57
- # a TimeSpan object will know the correct end of year,
58
- # quarter, etc.
59
- class DatePeriod
60
- extend Forwardable
61
- class << self
62
- def for(count, period_notation)
63
- @cached_periods ||= {}
64
- @cached_periods[period_notation] ||= {}
65
- @cached_periods[period_notation][count] ||= (for_notation(period_notation) || self).new(count)
66
- @cached_periods[period_notation][count]
67
- end
68
-
69
- def for_notation(notation)
70
- DatePeriod.types.find do |klass|
71
- klass.code == notation.to_s.upcase
72
- end
73
- end
74
-
75
- def types = @types ||= Set.new
76
-
77
- def inherited(klass)
78
- DatePeriod.types << klass
79
- end
80
-
81
- @period = nil
82
- @code = nil
83
- @interval = nil
84
- attr_reader :period, :code, :interval
85
- end
86
-
87
- delegate [:period, :code, :interval] => "self.class"
88
-
89
- def initialize(count)
90
- @count = count
91
- end
92
- attr_reader :count
93
-
94
- def end_date(date)
95
- @end_date ||= {}
96
- @end_date[date] ||= date + duration
97
- end
98
-
99
- def begin_date(date)
100
- @begin_date ||= {}
101
- @begin_date[date] ||= date - duration
102
- end
103
-
104
- def duration = count.send(period)
105
-
106
- def end_of_period(_) = nil
107
-
108
- def humanized_period
109
- return period if count == 1
110
-
111
- "#{period}s"
112
- end
113
-
114
- class Year < self
115
- @period = :year
116
- @code = "Y"
117
- @interval = "years"
118
-
119
- def end_of_period(date)
120
- date.end_of_year
121
- end
122
-
123
- def beginning_of_period(date)
124
- date.beginning_of_year
125
- end
126
- end
127
-
128
- class Quarter < self
129
- @period = :quarter
130
- @code = "Q"
131
- @interval = "quarters"
132
-
133
- def duration
134
- (count * 3).months
135
- end
136
-
137
- def end_of_period(date)
138
- date.end_of_quarter
139
- end
140
-
141
- def beginning_of_period(date)
142
- date.beginning_of_quarter
143
- end
144
- end
145
-
146
- class Month < self
147
- @period = :month
148
- @code = "M"
149
- @interval = "months"
150
-
151
- def end_of_period(date)
152
- date.end_of_month
153
- end
154
-
155
- def beginning_of_period(date)
156
- date.beginning_of_month
157
- end
158
- end
159
-
160
- class Week < self
161
- @period = :week
162
- @code = "W"
163
- @interval = "weeks"
164
-
165
- def end_of_period(date)
166
- date.end_of_week
167
- end
168
-
169
- def beginning_of_period(date)
170
- date.beginning_of_week
171
- end
172
- end
173
-
174
- class Day < self
175
- @period = :day
176
- @code = "D"
177
- @interval = "days"
178
-
179
- def end_of_period(date)
180
- date
181
- end
182
-
183
- def beginning_of_period(date)
184
- date
185
- end
186
- end
187
- end
188
- private_constant :DatePeriod
189
-
190
- def initialize(count, period_id)
191
- @count = Integer(count, exception: false)
192
- @window = DatePeriod.for(period_count, period_id)
193
- end
194
- attr_reader :window
195
-
196
- delegate [:end_date, :begin_date, :code] => :window
197
-
198
- def end_date_of_period(date)
199
- window.end_of_period(date)
200
- end
201
-
202
- def begin_date_of_period(date)
203
- window.beginning_of_period(date)
204
- end
205
-
206
- # Integer value for the period count or nil
207
- def period_count
208
- @count
209
- end
210
-
211
- delegate [:period, :duration, :interval, :humanized_period] => :window
212
-
213
- # Return a date according to the rules of the time_span
214
- def final_date(date)
215
- return unless period
216
-
217
- window.end_date(date.to_date)
218
- end
219
-
220
- def to_h
221
- {
222
- period:,
223
- period_count:
224
- }
225
- end
226
-
227
- class TimeSpanNothing < self
228
- end
229
-
230
- class TimeSpanOne < self
231
- def interval = humanized_period
232
- end
233
- end
234
- end