Skip to content

Commit 0d32139

Browse files
committed
Refactor BYSETPOS validation to apply to all frequencies
1 parent 7d5bc51 commit 0d32139

File tree

7 files changed

+132
-184
lines changed

7 files changed

+132
-184
lines changed

lib/ice_cube.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ module Validations
5050
autoload :YearlyInterval, 'ice_cube/validations/yearly_interval'
5151
autoload :HourlyInterval, 'ice_cube/validations/hourly_interval'
5252

53-
autoload :MonthlyBySetPos, 'ice_cube/validations/monthly_by_set_pos'
54-
autoload :YearlyBySetPos, 'ice_cube/validations/yearly_by_set_pos'
53+
autoload :BySetPos, 'ice_cube/validations/by_set_pos'
5554

5655
autoload :HourOfDay, 'ice_cube/validations/hour_of_day'
5756
autoload :MonthOfYear, 'ice_cube/validations/month_of_year'

lib/ice_cube/rules/monthly_rule.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class MonthlyRule < ValidatedRule
1212
# include Validations::DayOfYear # n/a
1313

1414
include Validations::MonthlyInterval
15-
include Validations::MonthlyBySetPos
1615

1716
def initialize(interval = 1)
1817
super

lib/ice_cube/rules/yearly_rule.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class YearlyRule < ValidatedRule
1212
include Validations::DayOfYear
1313

1414
include Validations::YearlyInterval
15-
include Validations::YearlyBySetPos
1615

1716
def initialize(interval = 1)
1817
super

lib/ice_cube/validated_rule.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class ValidatedRule < Rule
88

99
include Validations::Count
1010
include Validations::Until
11+
include Validations::BySetPos
1112

1213
# Validations ordered for efficiency in sequence of:
1314
# * descending intervals
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
require "active_support/core_ext/date/calculations"
2+
require "active_support/core_ext/date_time/calculations"
3+
require "active_support/core_ext/time/calculations"
4+
5+
require "active_support/core_ext/hash/except"
6+
7+
module IceCube
8+
9+
module Validations::BySetPos
10+
11+
def by_set_pos(*bysplist)
12+
bysplist.flatten.each do |set_pos_day|
13+
unless set_pos_day.is_a?(Integer) && (-366..366).include?(set_pos_day) && set_pos_day != 0
14+
raise ArgumentError, "expecting Integer value in [-366, -1] or [1, 366] for setposday, got #{set_pos_day} (#{bysplist})"
15+
end
16+
17+
validations_for(:by_set_pos) << Validation.new(set_pos_day, self)
18+
end
19+
20+
self
21+
end
22+
23+
class Validation
24+
25+
attr_reader :source_rule, :set_pos_day
26+
27+
def initialize(set_pos_day, source_rule)
28+
@set_pos_day = set_pos_day
29+
@source_rule = source_rule
30+
end
31+
32+
def type
33+
:day
34+
end
35+
36+
def dst_adjust?
37+
true
38+
end
39+
40+
def validate(step_time, _start_time)
41+
@step_time = step_time
42+
43+
if step_time == occurrences_this_period[zero_indexed_position]
44+
0
45+
else
46+
1
47+
end
48+
end
49+
50+
def build_s(builder)
51+
builder.piece(:by_set_pos) << set_pos_day
52+
end
53+
54+
def build_hash(builder)
55+
builder.validations_array(:by_set_pos) << set_pos_day
56+
end
57+
58+
def build_ical(builder)
59+
builder['BYSETPOS'] << set_pos_day
60+
end
61+
62+
private
63+
64+
attr_reader :step_time
65+
66+
def zero_indexed_position
67+
if set_pos_day > 0
68+
set_pos_day - 1
69+
else
70+
set_pos_day
71+
end
72+
end
73+
74+
def occurrences_this_period
75+
schedule_for_rule.occurrences_between(
76+
beginning_of_period,
77+
end_of_period
78+
)
79+
end
80+
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
97+
end
98+
end
99+
100+
def beginning_of_period
101+
step_time.public_send("beginning_of_#{period_type}")
102+
end
103+
104+
def end_of_period
105+
step_time.public_send("end_of_#{period_type}")
106+
end
107+
108+
def last_period
109+
step_time.public_send("last_#{period_type}")
110+
end
111+
112+
def schedule_for_rule
113+
IceCube::Schedule.new(last_period) do |s|
114+
s.add_recurrence_rule Rule.from_hash(rule_hash_for_all_occurrences)
115+
end
116+
end
117+
118+
def rule_hash_for_all_occurrences
119+
source_rule.to_hash.except(:count, :until).tap do |hash|
120+
if hash[:validations]
121+
hash[:validations].delete(:by_set_pos)
122+
end
123+
end
124+
end
125+
126+
end
127+
128+
end
129+
130+
end

lib/ice_cube/validations/monthly_by_set_pos.rb

Lines changed: 0 additions & 88 deletions
This file was deleted.

lib/ice_cube/validations/yearly_by_set_pos.rb

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)