ice_cube_chosko 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|