ice_cube_chosko 0.1.0 → 0.1.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 +4 -4
- data/config/locales/de.yml +178 -0
- data/config/locales/fr.yml +173 -0
- data/config/locales/ru.yml +195 -0
- data/config/locales/sv.yml +169 -0
- data/lib/ice_cube.rb +1 -0
- data/lib/ice_cube/parsers/ical_parser.rb +17 -25
- data/lib/ice_cube/rule.rb +56 -15
- data/lib/ice_cube/schedule.rb +52 -24
- data/lib/ice_cube/single_occurrence_rule.rb +5 -0
- data/lib/ice_cube/time_util.rb +11 -3
- data/lib/ice_cube/validated_rule.rb +3 -1
- data/lib/ice_cube/validations/day.rb +2 -0
- data/lib/ice_cube/validations/override_duration.rb +53 -0
- data/lib/ice_cube/validations/until.rb +2 -2
- data/lib/ice_cube/version.rb +2 -2
- data/spec/spec_helper.rb +5 -21
- metadata +11 -48
@@ -0,0 +1,169 @@
|
|
1
|
+
sv:
|
2
|
+
ice_cube:
|
3
|
+
pieces_connector: ' / '
|
4
|
+
not: 'inte %{target}'
|
5
|
+
not_on: 'inte i %{target}'
|
6
|
+
date:
|
7
|
+
formats:
|
8
|
+
default: '%-d %B %Y'
|
9
|
+
month_names:
|
10
|
+
-
|
11
|
+
- januari
|
12
|
+
- februari
|
13
|
+
- mars
|
14
|
+
- april
|
15
|
+
- maj
|
16
|
+
- juni
|
17
|
+
- juli
|
18
|
+
- augusti
|
19
|
+
- september
|
20
|
+
- oktober
|
21
|
+
- november
|
22
|
+
- december
|
23
|
+
day_names:
|
24
|
+
- söndag
|
25
|
+
- måndag
|
26
|
+
- tisdag
|
27
|
+
- onsdag
|
28
|
+
- torsdag
|
29
|
+
- fredag
|
30
|
+
- lördag
|
31
|
+
times:
|
32
|
+
other: '%{count} gånger'
|
33
|
+
one: '%{count} gång'
|
34
|
+
until: 'tills %{date}'
|
35
|
+
days_of_week: '%{segments} %{day}'
|
36
|
+
days_of_month:
|
37
|
+
other: '%{segments} dagen i månaden'
|
38
|
+
one: '%{segments} dagen i månaden'
|
39
|
+
days_of_year:
|
40
|
+
other: '%{segments} dagen på året'
|
41
|
+
one: '%{segments} dagen på året'
|
42
|
+
at_hours_of_the_day:
|
43
|
+
other: i %{segments} timme på dygnet
|
44
|
+
one: i %{segments} timme på dygnet
|
45
|
+
on_minutes_of_hour:
|
46
|
+
other: i %{segments} minuter av timmen
|
47
|
+
one: i %{segments} minuten av timmen
|
48
|
+
on_seconds_of_minute:
|
49
|
+
other: på %{segments} sekunden av minuten
|
50
|
+
one: på %{segments} sekunden av minuten
|
51
|
+
each_second:
|
52
|
+
one: Varje sekund
|
53
|
+
other: Varje %{count} sekund
|
54
|
+
each_minute:
|
55
|
+
one: Varje minut
|
56
|
+
other: Varje %{count} minut
|
57
|
+
each_hour:
|
58
|
+
one: Varje timme
|
59
|
+
other: Varje %{count} timme
|
60
|
+
each_day:
|
61
|
+
one: Varje dag
|
62
|
+
other: Varje %{count} dag
|
63
|
+
each_week:
|
64
|
+
one: Varje vecka
|
65
|
+
other: Varje %{count} vecka
|
66
|
+
each_month:
|
67
|
+
one: Varje månad
|
68
|
+
other: Varje %{count} månad
|
69
|
+
each_year:
|
70
|
+
one: Varje år
|
71
|
+
other: Varje %{count} år
|
72
|
+
'on': i %{sentence}
|
73
|
+
in: 'efter %{target}'
|
74
|
+
integer:
|
75
|
+
negative: '%{ordinal} från slutet'
|
76
|
+
literal_ordinals:
|
77
|
+
-1: sista
|
78
|
+
-2: nästsista
|
79
|
+
ordinal: '%{number}%{ordinal}'
|
80
|
+
ordinals:
|
81
|
+
default: ''
|
82
|
+
on_weekends: på helger
|
83
|
+
on_weekdays: på vardagar
|
84
|
+
days_on:
|
85
|
+
- söndagar
|
86
|
+
- måndagar
|
87
|
+
- tisdagar
|
88
|
+
- onsdagar
|
89
|
+
- torsdagar
|
90
|
+
- fredagar
|
91
|
+
- lördagar
|
92
|
+
on_days: på %{days}
|
93
|
+
array:
|
94
|
+
last_word_connector: ' och '
|
95
|
+
two_words_connector: ' och '
|
96
|
+
words_connector: ', '
|
97
|
+
string:
|
98
|
+
format:
|
99
|
+
day: '%{rest} %{current}'
|
100
|
+
day_of_week: '%{rest} %{current}'
|
101
|
+
day_of_month: '%{rest} %{current}'
|
102
|
+
day_of_year: '%{rest} %{current}'
|
103
|
+
hour_of_day: '%{rest} %{current}'
|
104
|
+
minute_of_hour: '%{rest} %{current}'
|
105
|
+
until: '%{rest} %{current}'
|
106
|
+
count: '%{rest} %{current}'
|
107
|
+
default: '%{rest} %{current}'
|
108
|
+
|
109
|
+
date:
|
110
|
+
abbr_day_names:
|
111
|
+
- Sön
|
112
|
+
- Mån
|
113
|
+
- Tis
|
114
|
+
- Ons
|
115
|
+
- Tor
|
116
|
+
- Fre
|
117
|
+
- Lör
|
118
|
+
abbr_month_names:
|
119
|
+
-
|
120
|
+
- Jan
|
121
|
+
- Feb
|
122
|
+
- Mar
|
123
|
+
- Apr
|
124
|
+
- Maj
|
125
|
+
- Jun
|
126
|
+
- Jul
|
127
|
+
- Aug
|
128
|
+
- Sep
|
129
|
+
- Okt
|
130
|
+
- Mov
|
131
|
+
- Dec
|
132
|
+
day_names:
|
133
|
+
- Söndag
|
134
|
+
- Måndag
|
135
|
+
- Tisdag
|
136
|
+
- Onsdag
|
137
|
+
- Torsdag
|
138
|
+
- Fredag
|
139
|
+
- Lördag
|
140
|
+
formats:
|
141
|
+
default: "%Y-%m-%d"
|
142
|
+
long: "%e %B %Y"
|
143
|
+
short: "%e %b"
|
144
|
+
month_names:
|
145
|
+
-
|
146
|
+
- Januari
|
147
|
+
- Februari
|
148
|
+
- Mars
|
149
|
+
- April
|
150
|
+
- Maj
|
151
|
+
- Juni
|
152
|
+
- Juli
|
153
|
+
- Augusti
|
154
|
+
- September
|
155
|
+
- Oktober
|
156
|
+
- November
|
157
|
+
- December
|
158
|
+
order:
|
159
|
+
- :day
|
160
|
+
- :month
|
161
|
+
- :year
|
162
|
+
|
163
|
+
time:
|
164
|
+
am: ''
|
165
|
+
formats:
|
166
|
+
default: "%a, %e %b %Y %H:%M:%S %z"
|
167
|
+
long: "%e %B %Y %H:%M"
|
168
|
+
short: "%e %b %H:%M"
|
169
|
+
pm: ''
|
data/lib/ice_cube.rb
CHANGED
@@ -43,6 +43,7 @@ module IceCube
|
|
43
43
|
|
44
44
|
autoload :Count, 'ice_cube/validations/count'
|
45
45
|
autoload :Until, 'ice_cube/validations/until'
|
46
|
+
autoload :OverrideDuration, 'ice_cube/validations/override_duration'
|
46
47
|
|
47
48
|
autoload :SecondlyInterval, 'ice_cube/validations/secondly_interval'
|
48
49
|
autoload :MinutelyInterval, 'ice_cube/validations/minutely_interval'
|
@@ -24,14 +24,18 @@ module IceCube
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.rule_from_ical(ical)
|
27
|
-
|
27
|
+
raise ArgumentError, 'empty ical rule' if ical.nil?
|
28
|
+
|
29
|
+
validations = {}
|
30
|
+
params = {validations: validations, interval: 1}
|
28
31
|
|
29
32
|
ical.split(';').each do |rule|
|
30
33
|
(name, value) = rule.split('=')
|
34
|
+
raise ArgumentError, "Invalid iCal rule component" if value.nil?
|
31
35
|
value.strip!
|
32
36
|
case name
|
33
37
|
when 'FREQ'
|
34
|
-
params[:
|
38
|
+
params[:rule_type] = "IceCube::#{value[0]}#{value.downcase[1..-1]}Rule"
|
35
39
|
when 'INTERVAL'
|
36
40
|
params[:interval] = value.to_i
|
37
41
|
when 'COUNT'
|
@@ -39,13 +43,13 @@ module IceCube
|
|
39
43
|
when 'UNTIL'
|
40
44
|
params[:until] = Time.parse(value).utc
|
41
45
|
when 'WKST'
|
42
|
-
params[:
|
46
|
+
params[:week_start] = TimeUtil.ical_day_to_symbol(value)
|
43
47
|
when 'BYSECOND'
|
44
|
-
|
48
|
+
validations[:second_of_minute] = value.split(',').map(&:to_i)
|
45
49
|
when 'BYMINUTE'
|
46
|
-
|
50
|
+
validations[:minute_of_hour] = value.split(',').map(&:to_i)
|
47
51
|
when 'BYHOUR'
|
48
|
-
|
52
|
+
validations[:hour_of_day] = value.split(',').map(&:to_i)
|
49
53
|
when 'BYDAY'
|
50
54
|
dows = {}
|
51
55
|
days = []
|
@@ -59,33 +63,21 @@ module IceCube
|
|
59
63
|
days.push TimeUtil.sym_to_wday(day) if dows[day].nil?
|
60
64
|
end
|
61
65
|
end
|
62
|
-
|
63
|
-
|
66
|
+
validations[:day_of_week] = dows unless dows.empty?
|
67
|
+
validations[:day] = days unless days.empty?
|
64
68
|
when 'BYMONTHDAY'
|
65
|
-
|
69
|
+
validations[:day_of_month] = value.split(',').map(&:to_i)
|
66
70
|
when 'BYMONTH'
|
67
|
-
|
71
|
+
validations[:month_of_year] = value.split(',').map(&:to_i)
|
68
72
|
when 'BYYEARDAY'
|
69
|
-
|
73
|
+
validations[:day_of_year] = value.split(',').map(&:to_i)
|
70
74
|
when 'BYSETPOS'
|
71
75
|
else
|
72
|
-
|
76
|
+
validations[name] = nil # invalid type
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
76
|
-
params
|
77
|
-
|
78
|
-
# WKST only valid for weekly rules
|
79
|
-
params.delete(:wkst) unless params[:freq] == 'weekly'
|
80
|
-
|
81
|
-
rule = Rule.send(*params.values_at(:freq, :interval, :wkst).compact)
|
82
|
-
rule.count(params[:count]) if params[:count]
|
83
|
-
rule.until(params[:until]) if params[:until]
|
84
|
-
params[:validations].each do |key, value|
|
85
|
-
value.is_a?(Array) ? rule.send(key, *value) : rule.send(key, value)
|
86
|
-
end
|
87
|
-
|
88
|
-
rule
|
80
|
+
Rule.from_hash(params)
|
89
81
|
end
|
90
82
|
end
|
91
83
|
end
|
data/lib/ice_cube/rule.rb
CHANGED
@@ -4,6 +4,11 @@ module IceCube
|
|
4
4
|
|
5
5
|
class Rule
|
6
6
|
|
7
|
+
INTERVAL_TYPES = [
|
8
|
+
:secondly, :minutely, :hourly,
|
9
|
+
:daily, :weekly, :monthly, :yearly
|
10
|
+
]
|
11
|
+
|
7
12
|
attr_reader :uses
|
8
13
|
|
9
14
|
# Is this a terminating schedule?
|
@@ -11,6 +16,11 @@ module IceCube
|
|
11
16
|
until_time || occurrence_count
|
12
17
|
end
|
13
18
|
|
19
|
+
# Does this rule override the schedule's duration?
|
20
|
+
def overrides_duration?
|
21
|
+
!duration.nil?
|
22
|
+
end
|
23
|
+
|
14
24
|
def ==(rule)
|
15
25
|
if rule.is_a? Rule
|
16
26
|
hash = to_hash
|
@@ -46,21 +56,6 @@ module IceCube
|
|
46
56
|
raise MethodNotImplemented, "Expected to be overridden by subclasses"
|
47
57
|
end
|
48
58
|
|
49
|
-
# Convert from a hash and create a rule
|
50
|
-
def self.from_hash(original_hash)
|
51
|
-
hash = IceCube::FlexibleHash.new original_hash
|
52
|
-
return nil unless match = hash[:rule_type].match(/\:\:(.+?)Rule/)
|
53
|
-
rule = IceCube::Rule.send(match[1].downcase.to_sym, hash[:interval] || 1)
|
54
|
-
rule.interval(hash[:interval] || 1, TimeUtil.wday_to_sym(hash[:week_start] || 0)) if match[1] == "Weekly"
|
55
|
-
rule.until(TimeUtil.deserialize_time(hash[:until])) if hash[:until]
|
56
|
-
rule.count(hash[:count]) if hash[:count]
|
57
|
-
hash[:validations] && hash[:validations].each do |key, value|
|
58
|
-
key = key.to_sym unless key.is_a?(Symbol)
|
59
|
-
value.is_a?(Array) ? rule.send(key, *value) : rule.send(key, value)
|
60
|
-
end
|
61
|
-
rule
|
62
|
-
end
|
63
|
-
|
64
59
|
# Reset the uses on the rule to 0
|
65
60
|
def reset
|
66
61
|
@uses = 0
|
@@ -78,6 +73,52 @@ module IceCube
|
|
78
73
|
!@count.nil?
|
79
74
|
end
|
80
75
|
|
76
|
+
class << self
|
77
|
+
|
78
|
+
# Convert from a hash and create a rule
|
79
|
+
def from_hash(original_hash)
|
80
|
+
hash = IceCube::FlexibleHash.new original_hash
|
81
|
+
|
82
|
+
unless hash[:rule_type] && match = hash[:rule_type].match(/\:\:(.+?)Rule/)
|
83
|
+
raise ArgumentError, 'Invalid rule type'
|
84
|
+
end
|
85
|
+
|
86
|
+
interval_type = match[1].downcase.to_sym
|
87
|
+
|
88
|
+
unless INTERVAL_TYPES.include?(interval_type)
|
89
|
+
raise ArgumentError, "Invalid rule frequency type: #{match[1]}"
|
90
|
+
end
|
91
|
+
|
92
|
+
rule = IceCube::Rule.send(interval_type, hash[:interval] || 1)
|
93
|
+
|
94
|
+
if match[1] == "Weekly"
|
95
|
+
rule.interval(hash[:interval] || 1, TimeUtil.wday_to_sym(hash[:week_start] || 0))
|
96
|
+
end
|
97
|
+
|
98
|
+
rule.until(TimeUtil.deserialize_time(hash[:until])) if hash[:until]
|
99
|
+
rule.count(hash[:count]) if hash[:count]
|
100
|
+
|
101
|
+
hash[:validations] && hash[:validations].each do |name, args|
|
102
|
+
apply_validation(rule, name, args)
|
103
|
+
end
|
104
|
+
|
105
|
+
rule
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def apply_validation(rule, name, args)
|
111
|
+
name = name.to_sym
|
112
|
+
|
113
|
+
unless ValidatedRule::VALIDATION_ORDER.include?(name)
|
114
|
+
raise ArgumentError, "Invalid rule validation type: #{name}"
|
115
|
+
end
|
116
|
+
|
117
|
+
args.is_a?(Array) ? rule.send(name, *args) : rule.send(name, args)
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
81
122
|
# Convenience methods for creating Rules
|
82
123
|
class << self
|
83
124
|
|
data/lib/ice_cube/schedule.rb
CHANGED
@@ -44,6 +44,16 @@ module IceCube
|
|
44
44
|
@end_time = start_time + seconds
|
45
45
|
end
|
46
46
|
|
47
|
+
# Return the maximum value between schedule's duration and
|
48
|
+
# the durations of all the recurrence and exception rules included
|
49
|
+
# in this schedule
|
50
|
+
def max_duration
|
51
|
+
all_durations = [duration]
|
52
|
+
all_durations += @all_recurrence_rules.map { |r| r.duration }.compact
|
53
|
+
all_durations += @all_exception_rules.map { |r| r.duration }.compact
|
54
|
+
all_durations.max
|
55
|
+
end
|
56
|
+
|
47
57
|
# Add a recurrence time to the schedule
|
48
58
|
def add_recurrence_time(time)
|
49
59
|
return nil if time.nil?
|
@@ -166,55 +176,55 @@ module IceCube
|
|
166
176
|
end
|
167
177
|
|
168
178
|
# The next n occurrences after now
|
169
|
-
def next_occurrences(num, from = nil,
|
179
|
+
def next_occurrences(num, from = nil, options = {})
|
170
180
|
from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time)
|
171
|
-
enumerate_occurrences(from + 1, nil,
|
181
|
+
enumerate_occurrences(from + 1, nil, options).take(num)
|
172
182
|
end
|
173
183
|
|
174
184
|
# The next occurrence after now (overridable)
|
175
|
-
def next_occurrence(from = nil,
|
185
|
+
def next_occurrence(from = nil, options = {})
|
176
186
|
from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time)
|
177
|
-
enumerate_occurrences(from + 1, nil,
|
187
|
+
enumerate_occurrences(from + 1, nil, options).next
|
178
188
|
rescue StopIteration
|
179
189
|
nil
|
180
190
|
end
|
181
191
|
|
182
192
|
# The previous occurrence from a given time
|
183
193
|
def previous_occurrence(from)
|
184
|
-
from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{
|
194
|
+
from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}"
|
185
195
|
return nil if from <= start_time
|
186
196
|
enumerate_occurrences(start_time, from - 1).to_a.last
|
187
197
|
end
|
188
198
|
|
189
199
|
# The previous n occurrences before a given time
|
190
200
|
def previous_occurrences(num, from)
|
191
|
-
from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{
|
201
|
+
from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}"
|
192
202
|
return [] if from <= start_time
|
193
203
|
a = enumerate_occurrences(start_time, from - 1).to_a
|
194
204
|
a.size > num ? a[-1*num,a.size] : a
|
195
205
|
end
|
196
206
|
|
197
207
|
# The remaining occurrences (same requirements as all_occurrences)
|
198
|
-
def remaining_occurrences(from = nil,
|
208
|
+
def remaining_occurrences(from = nil, options = {})
|
199
209
|
require_terminating_rules
|
200
210
|
from ||= TimeUtil.now(@start_time)
|
201
|
-
enumerate_occurrences(from, nil,
|
211
|
+
enumerate_occurrences(from, nil, options).to_a
|
202
212
|
end
|
203
213
|
|
204
214
|
# Returns an enumerator for all remaining occurrences
|
205
|
-
def remaining_occurrences_enumerator(from = nil,
|
215
|
+
def remaining_occurrences_enumerator(from = nil, options = {})
|
206
216
|
from ||= TimeUtil.now(@start_time)
|
207
|
-
enumerate_occurrences(from, nil,
|
217
|
+
enumerate_occurrences(from, nil, options)
|
208
218
|
end
|
209
219
|
|
210
220
|
# Occurrences between two times
|
211
|
-
def occurrences_between(begin_time, closing_time,
|
212
|
-
enumerate_occurrences(begin_time, closing_time,
|
221
|
+
def occurrences_between(begin_time, closing_time, options = {})
|
222
|
+
enumerate_occurrences(begin_time, closing_time, options).to_a
|
213
223
|
end
|
214
224
|
|
215
225
|
# Return a boolean indicating if an occurrence falls between two times
|
216
|
-
def occurs_between?(begin_time, closing_time,
|
217
|
-
enumerate_occurrences(begin_time, closing_time,
|
226
|
+
def occurs_between?(begin_time, closing_time, options = {})
|
227
|
+
enumerate_occurrences(begin_time, closing_time, options).next
|
218
228
|
true
|
219
229
|
rescue StopIteration
|
220
230
|
false
|
@@ -226,7 +236,7 @@ module IceCube
|
|
226
236
|
# occurrences at the end of the range since none of their duration
|
227
237
|
# intersects the range.
|
228
238
|
def occurring_between?(opening_time, closing_time)
|
229
|
-
occurs_between?(opening_time, closing_time, true)
|
239
|
+
occurs_between?(opening_time, closing_time, :spans => true)
|
230
240
|
end
|
231
241
|
|
232
242
|
# Return a boolean indicating if an occurrence falls on a certain date
|
@@ -240,9 +250,14 @@ module IceCube
|
|
240
250
|
# Determine if the schedule is occurring at a given time
|
241
251
|
def occurring_at?(time)
|
242
252
|
time = TimeUtil.match_zone(time, start_time) or raise ArgumentError, "Time required, got #{time.inspect}"
|
243
|
-
if
|
253
|
+
if max_duration > 0
|
244
254
|
return false if exception_time?(time)
|
245
|
-
|
255
|
+
begin
|
256
|
+
enumerate_occurrences(time, time, :spans => true).next
|
257
|
+
true
|
258
|
+
rescue StopIteration
|
259
|
+
false
|
260
|
+
end
|
246
261
|
else
|
247
262
|
occurs_at?(time)
|
248
263
|
end
|
@@ -405,15 +420,15 @@ module IceCube
|
|
405
420
|
# Find all of the occurrences for the schedule between opening_time
|
406
421
|
# and closing_time
|
407
422
|
# Iteration is unrolled in pairs to skip duplicate times in end of DST
|
408
|
-
def enumerate_occurrences(opening_time, closing_time = nil,
|
423
|
+
def enumerate_occurrences(opening_time, closing_time = nil, options = {}, &block)
|
409
424
|
opening_time = TimeUtil.match_zone(opening_time, start_time)
|
410
425
|
closing_time = TimeUtil.match_zone(closing_time, start_time)
|
411
426
|
opening_time += start_time.subsec - opening_time.subsec rescue 0
|
412
427
|
opening_time = start_time if opening_time < start_time
|
413
|
-
spans =
|
428
|
+
spans = options[:spans] == true && max_duration != 0
|
414
429
|
Enumerator.new do |yielder|
|
415
430
|
reset
|
416
|
-
t1 = full_required? ? start_time : realign((spans ?
|
431
|
+
t1 = full_required? ? start_time : realign(opening_time) - (spans ? max_duration : 0)
|
417
432
|
loop do
|
418
433
|
break unless (t0 = next_time(t1, closing_time))
|
419
434
|
break if closing_time && t0 > closing_time
|
@@ -437,17 +452,30 @@ module IceCube
|
|
437
452
|
# Get the next time after (or including) a specific time
|
438
453
|
def next_time(time, closing_time)
|
439
454
|
loop do
|
440
|
-
|
455
|
+
min_time_with_duration = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |min_time_with_duration, rule|
|
456
|
+
min_time = (min_time_with_duration && min_time_with_duration[0]) || nil
|
441
457
|
begin
|
442
458
|
new_time = rule.next_time(time, self, min_time || closing_time)
|
443
|
-
[
|
459
|
+
new_time_with_duration = [new_time, rule.duration]
|
460
|
+
|
461
|
+
if new_time.nil?
|
462
|
+
min_time_with_duration
|
463
|
+
elsif min_time.nil?
|
464
|
+
new_time_with_duration
|
465
|
+
elsif new_time < min_time
|
466
|
+
new_time_with_duration
|
467
|
+
else
|
468
|
+
min_time_with_duration
|
469
|
+
end
|
444
470
|
rescue StopIteration
|
445
|
-
min_time
|
471
|
+
(min_time && [min_time, rule.duration]) || nil
|
446
472
|
end
|
447
473
|
end
|
474
|
+
min_time = (min_time_with_duration && min_time_with_duration[0]) || nil
|
475
|
+
rule_duration = (min_time_with_duration && min_time_with_duration[1]) || nil
|
448
476
|
break nil unless min_time
|
449
477
|
next (time = min_time + 1) if exception_time?(min_time)
|
450
|
-
break Occurrence.new(min_time, min_time + duration)
|
478
|
+
break Occurrence.new(min_time, min_time + (rule_duration || duration))
|
451
479
|
end
|
452
480
|
end
|
453
481
|
|