Skip to content

Commit 39bc6fe

Browse files
committed
Refactor BYSETPOS module to be more generic and more readable
1 parent 0d32139 commit 39bc6fe

File tree

4 files changed

+93
-19
lines changed

4 files changed

+93
-19
lines changed

lib/ice_cube/rule.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ def on?(time, schedule)
5858
next_time(time, schedule, time).to_i == time.to_i
5959
end
6060

61+
def interval_type
62+
self.class.interval_type
63+
end
64+
6165
class << self
6266

6367
# Convert from a hash and create a rule
@@ -90,6 +94,10 @@ def from_hash(original_hash)
9094
rule
9195
end
9296

97+
def interval_type
98+
@_interval_type ||= self.name.split('::').last.sub(/Rule$/, '').downcase
99+
end
100+
93101
private
94102

95103
def apply_validation(rule, name, args)

lib/ice_cube/validations/by_set_pos.rb

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,35 +78,43 @@ def occurrences_this_period
7878
)
7979
end
8080

81-
def period_type
82-
case source_rule
83-
when SecondlyRule
84-
:second
85-
when MinutelyRule
86-
:minute
87-
when HourlyRule
88-
:hour
89-
when DailyRule
90-
:day
91-
when WeeklyRule
92-
:week
93-
when MonthlyRule
94-
:month
95-
when YearlyRule
96-
:year
81+
def interval_type
82+
if source_rule.interval_type == 'daily'
83+
'day'
84+
else
85+
source_rule.interval_type.sub(/ly$/, '')
9786
end
9887
end
9988

10089
def beginning_of_period
101-
step_time.public_send("beginning_of_#{period_type}")
90+
if interval_type == 'second'
91+
fail 'boo'
92+
else
93+
step_time.public_send("beginning_of_#{interval_type}")
94+
end
10295
end
10396

10497
def end_of_period
105-
step_time.public_send("end_of_#{period_type}")
98+
if interval_type == 'second'
99+
fail 'boo'
100+
else
101+
step_time.public_send("end_of_#{interval_type}")
102+
end
106103
end
107104

108105
def last_period
109-
step_time.public_send("last_#{period_type}")
106+
case interval_type
107+
when 'second'
108+
fail 'boo'
109+
when 'minute'
110+
step_time - ONE_MINUTE
111+
when 'hour'
112+
step_time - ONE_HOUR
113+
when 'day'
114+
step_time.yesterday
115+
when 'week', 'month', 'year'
116+
step_time.public_send("last_#{interval_type}")
117+
end
110118
end
111119

112120
def schedule_for_rule

spec/examples/from_ical_spec.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,16 @@ def sorted_ical(ical)
190190
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
191191
end
192192

193+
it 'handles bysetpos' do
194+
start_time = Time.now
195+
196+
schedule = IceCube::Schedule.new(start_time)
197+
schedule.add_recurrence_rule(IceCube::Rule.weekly.day(:monday).by_set_pos(1, -1))
198+
199+
ical = schedule.to_ical
200+
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
201+
end
202+
193203
end
194204

195205
describe 'weekly frequency' do
@@ -242,6 +252,16 @@ def sorted_ical(ical)
242252
ical = schedule.to_ical
243253
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
244254
end
255+
256+
it 'handles bysetpos' do
257+
start_time = Time.now
258+
259+
schedule = IceCube::Schedule.new(start_time)
260+
schedule.add_recurrence_rule(IceCube::Rule.weekly.day(:monday).by_set_pos(1, -1))
261+
262+
ical = schedule.to_ical
263+
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
264+
end
245265
end
246266

247267
describe 'monthly frequency' do
@@ -284,6 +304,16 @@ def sorted_ical(ical)
284304
ical = schedule.to_ical
285305
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
286306
end
307+
308+
it 'handles bysetpos' do
309+
start_time = Time.now
310+
311+
schedule = IceCube::Schedule.new(start_time)
312+
schedule.add_recurrence_rule(IceCube::Rule.monthly.day(:monday).by_set_pos(1, -1))
313+
314+
ical = schedule.to_ical
315+
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
316+
end
287317
end
288318

289319
describe 'yearly frequency' do
@@ -337,6 +367,16 @@ def sorted_ical(ical)
337367
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
338368
end
339369

370+
it 'handles bysetpos' do
371+
start_time = Time.now
372+
373+
schedule = IceCube::Schedule.new(start_time)
374+
schedule.add_recurrence_rule(IceCube::Rule.yearly.month_of_year(:february).day(:monday).by_set_pos(1, -1))
375+
376+
ical = schedule.to_ical
377+
expect(sorted_ical(IceCube::Schedule.from_ical(ical).to_ical)).to eq(sorted_ical(ical))
378+
end
379+
340380
it 'handles specific months' do
341381
start_time = Time.now
342382

spec/examples/rfc_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,24 @@
325325
expect(dates).to eq(expecation)
326326
end
327327

328+
it 'should ~ third instance into the month of one of Tuesday, Wednesday, or Thursday, for the next 3 months' do
329+
start_time = Time.utc(1997, 9, 4, 9, 0, 0)
330+
schedule = IceCube::Schedule.new(start_time)
331+
schedule.add_recurrence_rule IceCube::Rule.monthly.count(3).day(:tuesday , :wednesday , :thursday).by_set_pos(3)
332+
dates = schedule.all_occurrences
333+
expectation = [Time.utc(1997, 9, 4, 9), Time.utc(1997, 10, 7, 9), Time.utc(1997, 11, 6, 9)]
334+
expect(dates).to eq(expectation)
335+
end
336+
337+
it 'should ~ second-to-last weekday of the month' do
338+
start_time = Time.utc(1997, 9, 29, 9, 0, 0)
339+
schedule = IceCube::Schedule.new(start_time)
340+
schedule.add_recurrence_rule IceCube::Rule.monthly.day(:monday, :tuesday , :wednesday , :thursday, :friday).by_set_pos(-2)
341+
next_dates = schedule.occurrences(Time.utc(1997, 12, 31))
342+
expectation = [Time.utc(1997, 9, 29, 9), Time.utc(1997, 10, 30, 9), Time.utc(1997, 11, 27, 9), Time.utc(1997, 12, 30, 9)]
343+
expect(next_dates).to eq(expectation)
344+
end
345+
328346
end
329347

330348
def test_expectations(schedule, dates_array)

0 commit comments

Comments
 (0)