ice_cube 0.16.4 → 0.17.0
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/id.yml +134 -0
- data/lib/ice_cube/builders/hash_builder.rb +1 -5
- data/lib/ice_cube/builders/ical_builder.rb +13 -15
- data/lib/ice_cube/builders/string_builder.rb +10 -16
- data/lib/ice_cube/deprecated.rb +3 -4
- data/lib/ice_cube/errors/count_exceeded.rb +0 -2
- data/lib/ice_cube/errors/until_exceeded.rb +0 -2
- data/lib/ice_cube/flexible_hash.rb +3 -7
- data/lib/ice_cube/i18n.rb +11 -19
- data/lib/ice_cube/input_alignment.rb +9 -11
- data/lib/ice_cube/null_i18n.rb +6 -6
- data/lib/ice_cube/occurrence.rb +10 -11
- data/lib/ice_cube/parsers/hash_parser.rb +3 -6
- data/lib/ice_cube/parsers/ical_parser.rb +39 -38
- data/lib/ice_cube/parsers/yaml_parser.rb +2 -4
- data/lib/ice_cube/rule.rb +7 -18
- data/lib/ice_cube/rules/daily_rule.rb +0 -4
- data/lib/ice_cube/rules/hourly_rule.rb +0 -4
- data/lib/ice_cube/rules/minutely_rule.rb +0 -4
- data/lib/ice_cube/rules/monthly_rule.rb +0 -4
- data/lib/ice_cube/rules/secondly_rule.rb +0 -4
- data/lib/ice_cube/rules/weekly_rule.rb +1 -5
- data/lib/ice_cube/rules/yearly_rule.rb +0 -4
- data/lib/ice_cube/schedule.rb +32 -40
- data/lib/ice_cube/single_occurrence_rule.rb +1 -5
- data/lib/ice_cube/time_util.rb +49 -57
- data/lib/ice_cube/validated_rule.rb +4 -10
- data/lib/ice_cube/validations/count.rb +2 -8
- data/lib/ice_cube/validations/daily_interval.rb +5 -11
- data/lib/ice_cube/validations/day.rb +7 -13
- data/lib/ice_cube/validations/day_of_month.rb +4 -10
- data/lib/ice_cube/validations/day_of_week.rb +10 -13
- data/lib/ice_cube/validations/day_of_year.rb +6 -12
- data/lib/ice_cube/validations/fixed_value.rb +9 -15
- data/lib/ice_cube/validations/hour_of_day.rb +5 -11
- data/lib/ice_cube/validations/hourly_interval.rb +3 -9
- data/lib/ice_cube/validations/lock.rb +8 -14
- data/lib/ice_cube/validations/minute_of_hour.rb +4 -10
- data/lib/ice_cube/validations/minutely_interval.rb +4 -10
- data/lib/ice_cube/validations/month_of_year.rb +2 -8
- data/lib/ice_cube/validations/monthly_interval.rb +4 -10
- data/lib/ice_cube/validations/schedule_lock.rb +0 -6
- data/lib/ice_cube/validations/second_of_minute.rb +4 -10
- data/lib/ice_cube/validations/secondly_interval.rb +2 -8
- data/lib/ice_cube/validations/until.rb +2 -8
- data/lib/ice_cube/validations/weekly_interval.rb +5 -11
- data/lib/ice_cube/validations/yearly_interval.rb +3 -9
- data/lib/ice_cube/version.rb +1 -3
- data/lib/ice_cube.rb +51 -51
- metadata +23 -8
- data/spec/spec_helper.rb +0 -79
@@ -3,22 +3,22 @@ module IceCube
|
|
3
3
|
def self.schedule_from_ical(ical_string, options = {})
|
4
4
|
data = {}
|
5
5
|
ical_string.each_line do |line|
|
6
|
-
(property, value) = line.split(
|
7
|
-
(property, _tzid) = property.split(
|
6
|
+
(property, value) = line.split(":")
|
7
|
+
(property, _tzid) = property.split(";")
|
8
8
|
case property
|
9
|
-
when
|
9
|
+
when "DTSTART"
|
10
10
|
data[:start_time] = TimeUtil.deserialize_time(value)
|
11
|
-
when
|
11
|
+
when "DTEND"
|
12
12
|
data[:end_time] = TimeUtil.deserialize_time(value)
|
13
|
-
when
|
13
|
+
when "RDATE"
|
14
14
|
data[:rtimes] ||= []
|
15
|
-
data[:rtimes] += value.split(
|
16
|
-
when
|
15
|
+
data[:rtimes] += value.split(",").map { |v| TimeUtil.deserialize_time(v) }
|
16
|
+
when "EXDATE"
|
17
17
|
data[:extimes] ||= []
|
18
|
-
data[:extimes] += value.split(
|
19
|
-
when
|
18
|
+
data[:extimes] += value.split(",").map { |v| TimeUtil.deserialize_time(v) }
|
19
|
+
when "DURATION"
|
20
20
|
data[:duration] # FIXME
|
21
|
-
when
|
21
|
+
when "RRULE"
|
22
22
|
data[:rrules] ||= []
|
23
23
|
data[:rrules] += [rule_from_ical(value)]
|
24
24
|
end
|
@@ -27,54 +27,55 @@ module IceCube
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.rule_from_ical(ical)
|
30
|
-
raise ArgumentError,
|
30
|
+
raise ArgumentError, "empty ical rule" if ical.nil?
|
31
31
|
|
32
32
|
validations = {}
|
33
33
|
params = {validations: validations, interval: 1}
|
34
34
|
|
35
|
-
ical.split(
|
36
|
-
(name, value) = rule.split(
|
35
|
+
ical.split(";").each do |rule|
|
36
|
+
(name, value) = rule.split("=")
|
37
37
|
raise ArgumentError, "Invalid iCal rule component" if value.nil?
|
38
38
|
value.strip!
|
39
39
|
case name
|
40
|
-
when
|
41
|
-
params[:rule_type] = "IceCube::#{value[0]}#{value.downcase[1
|
42
|
-
when
|
40
|
+
when "FREQ"
|
41
|
+
params[:rule_type] = "IceCube::#{value[0]}#{value.downcase[1..]}Rule"
|
42
|
+
when "INTERVAL"
|
43
43
|
params[:interval] = value.to_i
|
44
|
-
when
|
44
|
+
when "COUNT"
|
45
45
|
params[:count] = value.to_i
|
46
|
-
when
|
46
|
+
when "UNTIL"
|
47
47
|
params[:until] = TimeUtil.deserialize_time(value).utc
|
48
|
-
when
|
48
|
+
when "WKST"
|
49
49
|
params[:week_start] = TimeUtil.ical_day_to_symbol(value)
|
50
|
-
when
|
51
|
-
validations[:second_of_minute] = value.split(
|
52
|
-
when
|
53
|
-
validations[:minute_of_hour] = value.split(
|
54
|
-
when
|
55
|
-
validations[:hour_of_day] = value.split(
|
56
|
-
when
|
50
|
+
when "BYSECOND"
|
51
|
+
validations[:second_of_minute] = value.split(",").map(&:to_i)
|
52
|
+
when "BYMINUTE"
|
53
|
+
validations[:minute_of_hour] = value.split(",").map(&:to_i)
|
54
|
+
when "BYHOUR"
|
55
|
+
validations[:hour_of_day] = value.split(",").map(&:to_i)
|
56
|
+
when "BYDAY"
|
57
57
|
dows = {}
|
58
58
|
days = []
|
59
|
-
value.split(
|
60
|
-
day = TimeUtil.ical_day_to_symbol(expr.strip[-2
|
61
|
-
if expr.strip.length > 2
|
59
|
+
value.split(",").each do |expr|
|
60
|
+
day = TimeUtil.ical_day_to_symbol(expr.strip[-2..])
|
61
|
+
if expr.strip.length > 2 # day with occurence
|
62
62
|
occ = expr[0..-3].to_i
|
63
63
|
dows[day].nil? ? dows[day] = [occ] : dows[day].push(occ)
|
64
64
|
days.delete(TimeUtil.sym_to_wday(day))
|
65
|
-
|
66
|
-
days.push TimeUtil.sym_to_wday(day)
|
65
|
+
elsif dows[day].nil?
|
66
|
+
days.push TimeUtil.sym_to_wday(day)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
validations[:day_of_week] = dows unless dows.empty?
|
70
70
|
validations[:day] = days unless days.empty?
|
71
|
-
when
|
72
|
-
validations[:day_of_month] = value.split(
|
73
|
-
when
|
74
|
-
validations[:month_of_year] = value.split(
|
75
|
-
when
|
76
|
-
validations[:day_of_year] = value.split(
|
77
|
-
when
|
71
|
+
when "BYMONTHDAY"
|
72
|
+
validations[:day_of_month] = value.split(",").map(&:to_i)
|
73
|
+
when "BYMONTH"
|
74
|
+
validations[:month_of_year] = value.split(",").map(&:to_i)
|
75
|
+
when "BYYEARDAY"
|
76
|
+
validations[:day_of_year] = value.split(",").map(&:to_i)
|
77
|
+
when "BYSETPOS"
|
78
|
+
# noop
|
78
79
|
else
|
79
80
|
validations[name] = nil # invalid type
|
80
81
|
end
|
@@ -1,19 +1,17 @@
|
|
1
|
-
require
|
1
|
+
require "yaml"
|
2
2
|
|
3
3
|
module IceCube
|
4
4
|
class YamlParser < HashParser
|
5
|
-
|
6
5
|
SERIALIZED_START = /start_(?:time|date): .+(?<tz>(?:-|\+)\d{2}:\d{2})$/
|
7
6
|
|
8
7
|
attr_reader :hash
|
9
8
|
|
10
9
|
def initialize(yaml)
|
11
|
-
@hash = YAML
|
10
|
+
@hash = YAML.safe_load(yaml, permitted_classes: [Date, Symbol, Time], aliases: true)
|
12
11
|
yaml.match SERIALIZED_START do |match|
|
13
12
|
start_time = hash[:start_time] || hash[:start_date]
|
14
13
|
TimeUtil.restore_deserialized_offset start_time, match[:tz]
|
15
14
|
end
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
17
|
end
|
data/lib/ice_cube/rule.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require
|
1
|
+
require "yaml"
|
2
2
|
|
3
3
|
module IceCube
|
4
|
-
|
5
4
|
class Rule
|
6
|
-
|
7
5
|
INTERVAL_TYPES = [
|
8
6
|
:secondly, :minutely, :hourly,
|
9
7
|
:daily, :weekly, :monthly, :yearly
|
@@ -39,12 +37,12 @@ module IceCube
|
|
39
37
|
|
40
38
|
# Yaml implementation
|
41
39
|
def to_yaml(*args)
|
42
|
-
YAML
|
40
|
+
YAML.dump(to_hash, *args)
|
43
41
|
end
|
44
42
|
|
45
43
|
# From yaml
|
46
44
|
def self.from_yaml(yaml)
|
47
|
-
from_hash YAML
|
45
|
+
from_hash YAML.safe_load(yaml, permitted_classes: [Date, Symbol, Time])
|
48
46
|
end
|
49
47
|
|
50
48
|
def to_hash
|
@@ -59,13 +57,12 @@ module IceCube
|
|
59
57
|
end
|
60
58
|
|
61
59
|
class << self
|
62
|
-
|
63
60
|
# Convert from a hash and create a rule
|
64
61
|
def from_hash(original_hash)
|
65
62
|
hash = IceCube::FlexibleHash.new original_hash
|
66
63
|
|
67
|
-
unless hash[:rule_type] && match = hash[:rule_type].match(
|
68
|
-
raise ArgumentError,
|
64
|
+
unless hash[:rule_type] && (match = hash[:rule_type].match(/::(.+?)Rule/))
|
65
|
+
raise ArgumentError, "Invalid rule type"
|
69
66
|
end
|
70
67
|
|
71
68
|
interval_type = match[1].downcase.to_sym
|
@@ -76,14 +73,11 @@ module IceCube
|
|
76
73
|
|
77
74
|
rule = IceCube::Rule.send(interval_type, hash[:interval] || 1)
|
78
75
|
|
79
|
-
|
80
|
-
rule.interval(hash[:interval] || 1, TimeUtil.wday_to_sym(hash[:week_start] || 0))
|
81
|
-
end
|
82
|
-
|
76
|
+
rule.interval(hash[:interval] || 1, TimeUtil.wday_to_sym(hash[:week_start] || 0)) if rule.is_a? WeeklyRule
|
83
77
|
rule.until(TimeUtil.deserialize_time(hash[:until])) if hash[:until]
|
84
78
|
rule.count(hash[:count]) if hash[:count]
|
85
79
|
|
86
|
-
hash[:validations]
|
80
|
+
hash[:validations]&.each do |name, args|
|
87
81
|
apply_validation(rule, name, args)
|
88
82
|
end
|
89
83
|
|
@@ -101,12 +95,10 @@ module IceCube
|
|
101
95
|
|
102
96
|
args.is_a?(Array) ? rule.send(name, *args) : rule.send(name, args)
|
103
97
|
end
|
104
|
-
|
105
98
|
end
|
106
99
|
|
107
100
|
# Convenience methods for creating Rules
|
108
101
|
class << self
|
109
|
-
|
110
102
|
# Secondly Rule
|
111
103
|
def secondly(interval = 1)
|
112
104
|
SecondlyRule.new(interval)
|
@@ -141,9 +133,6 @@ module IceCube
|
|
141
133
|
def yearly(interval = 1)
|
142
134
|
YearlyRule.new(interval)
|
143
135
|
end
|
144
|
-
|
145
136
|
end
|
146
|
-
|
147
137
|
end
|
148
|
-
|
149
138
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class DailyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -19,7 +17,5 @@ module IceCube
|
|
19
17
|
schedule_lock(:hour, :min, :sec)
|
20
18
|
reset
|
21
19
|
end
|
22
|
-
|
23
20
|
end
|
24
|
-
|
25
21
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class HourlyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -19,7 +17,5 @@ module IceCube
|
|
19
17
|
schedule_lock(:min, :sec)
|
20
18
|
reset
|
21
19
|
end
|
22
|
-
|
23
20
|
end
|
24
|
-
|
25
21
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class MinutelyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -19,7 +17,5 @@ module IceCube
|
|
19
17
|
schedule_lock(:sec)
|
20
18
|
reset
|
21
19
|
end
|
22
|
-
|
23
20
|
end
|
24
|
-
|
25
21
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class MonthlyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -19,7 +17,5 @@ module IceCube
|
|
19
17
|
schedule_lock(:day, :hour, :min, :sec)
|
20
18
|
reset
|
21
19
|
end
|
22
|
-
|
23
20
|
end
|
24
|
-
|
25
21
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class SecondlyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -18,7 +16,5 @@ module IceCube
|
|
18
16
|
interval(interval)
|
19
17
|
reset
|
20
18
|
end
|
21
|
-
|
22
19
|
end
|
23
|
-
|
24
20
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class WeeklyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -37,7 +35,7 @@ module IceCube
|
|
37
35
|
time = TimeUtil::TimeWrapper.new(start_time)
|
38
36
|
offset = wday_offset(step_time, start_time)
|
39
37
|
time.add(:day, offset)
|
40
|
-
super
|
38
|
+
super(step_time, time.to_time)
|
41
39
|
end
|
42
40
|
|
43
41
|
# Calculate how many days to the first wday validation in the correct
|
@@ -57,7 +55,5 @@ module IceCube
|
|
57
55
|
|
58
56
|
days + interval - step_wday + min_wday
|
59
57
|
end
|
60
|
-
|
61
58
|
end
|
62
|
-
|
63
59
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class YearlyRule < ValidatedRule
|
4
|
-
|
5
3
|
include Validations::HourOfDay
|
6
4
|
include Validations::MinuteOfHour
|
7
5
|
include Validations::SecondOfMinute
|
@@ -19,7 +17,5 @@ module IceCube
|
|
19
17
|
schedule_lock(:month, :day, :hour, :min, :sec)
|
20
18
|
reset
|
21
19
|
end
|
22
|
-
|
23
20
|
end
|
24
|
-
|
25
21
|
end
|
data/lib/ice_cube/schedule.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require
|
1
|
+
require "yaml"
|
2
2
|
|
3
3
|
module IceCube
|
4
|
-
|
5
4
|
class Schedule
|
6
|
-
|
7
5
|
extend Deprecated
|
8
6
|
|
9
7
|
# Get the start time
|
@@ -51,7 +49,7 @@ module IceCube
|
|
51
49
|
add_recurrence_rule rule
|
52
50
|
time
|
53
51
|
end
|
54
|
-
|
52
|
+
alias_method :rtime, :add_recurrence_time
|
55
53
|
deprecated_alias :rdate, :rtime
|
56
54
|
deprecated_alias :add_recurrence_date, :add_recurrence_time
|
57
55
|
|
@@ -62,7 +60,7 @@ module IceCube
|
|
62
60
|
add_exception_rule rule
|
63
61
|
time
|
64
62
|
end
|
65
|
-
|
63
|
+
alias_method :extime, :add_exception_time
|
66
64
|
deprecated_alias :exdate, :extime
|
67
65
|
deprecated_alias :add_exception_date, :add_exception_time
|
68
66
|
|
@@ -71,7 +69,7 @@ module IceCube
|
|
71
69
|
return if rule.nil?
|
72
70
|
@all_recurrence_rules << rule unless @all_recurrence_rules.include?(rule)
|
73
71
|
end
|
74
|
-
|
72
|
+
alias_method :rrule, :add_recurrence_rule
|
75
73
|
|
76
74
|
# Remove a recurrence rule
|
77
75
|
def remove_recurrence_rule(rule)
|
@@ -84,7 +82,7 @@ module IceCube
|
|
84
82
|
return if rule.nil?
|
85
83
|
@all_exception_rules << rule unless @all_exception_rules.include?(rule)
|
86
84
|
end
|
87
|
-
|
85
|
+
alias_method :exrule, :add_exception_rule
|
88
86
|
|
89
87
|
# Remove an exception rule
|
90
88
|
def remove_exception_rule(rule)
|
@@ -96,19 +94,19 @@ module IceCube
|
|
96
94
|
def recurrence_rules
|
97
95
|
@all_recurrence_rules.reject { |r| r.is_a?(SingleOccurrenceRule) }
|
98
96
|
end
|
99
|
-
|
97
|
+
alias_method :rrules, :recurrence_rules
|
100
98
|
|
101
99
|
# Get the exception rules
|
102
100
|
def exception_rules
|
103
101
|
@all_exception_rules.reject { |r| r.is_a?(SingleOccurrenceRule) }
|
104
102
|
end
|
105
|
-
|
103
|
+
alias_method :exrules, :exception_rules
|
106
104
|
|
107
105
|
# Get the recurrence times that are on the schedule
|
108
106
|
def recurrence_times
|
109
107
|
@all_recurrence_rules.select { |r| r.is_a?(SingleOccurrenceRule) }.map(&:time)
|
110
108
|
end
|
111
|
-
|
109
|
+
alias_method :rtimes, :recurrence_times
|
112
110
|
deprecated_alias :rdates, :rtimes
|
113
111
|
deprecated_alias :recurrence_dates, :recurrence_times
|
114
112
|
|
@@ -120,7 +118,7 @@ module IceCube
|
|
120
118
|
end
|
121
119
|
time if found
|
122
120
|
end
|
123
|
-
|
121
|
+
alias_method :remove_rtime, :remove_recurrence_time
|
124
122
|
deprecated_alias :remove_recurrence_date, :remove_recurrence_time
|
125
123
|
deprecated_alias :remove_rdate, :remove_rtime
|
126
124
|
|
@@ -128,7 +126,7 @@ module IceCube
|
|
128
126
|
def exception_times
|
129
127
|
@all_exception_rules.select { |r| r.is_a?(SingleOccurrenceRule) }.map(&:time)
|
130
128
|
end
|
131
|
-
|
129
|
+
alias_method :extimes, :exception_times
|
132
130
|
deprecated_alias :exdates, :extimes
|
133
131
|
deprecated_alias :exception_dates, :exception_times
|
134
132
|
|
@@ -140,7 +138,7 @@ module IceCube
|
|
140
138
|
end
|
141
139
|
time if found
|
142
140
|
end
|
143
|
-
|
141
|
+
alias_method :remove_extime, :remove_exception_time
|
144
142
|
deprecated_alias :remove_exception_date, :remove_exception_time
|
145
143
|
deprecated_alias :remove_exdate, :remove_extime
|
146
144
|
|
@@ -162,8 +160,8 @@ module IceCube
|
|
162
160
|
end
|
163
161
|
|
164
162
|
# Iterate forever
|
165
|
-
def each_occurrence(&
|
166
|
-
enumerate_occurrences(start_time, &
|
163
|
+
def each_occurrence(&)
|
164
|
+
enumerate_occurrences(start_time, &).to_a
|
167
165
|
self
|
168
166
|
end
|
169
167
|
|
@@ -193,7 +191,7 @@ module IceCube
|
|
193
191
|
from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}"
|
194
192
|
return [] if from <= start_time
|
195
193
|
a = enumerate_occurrences(start_time, from - 1).to_a
|
196
|
-
a.size > num ? a[-1*num,a.size] : a
|
194
|
+
(a.size > num) ? a[-1 * num, a.size] : a
|
197
195
|
end
|
198
196
|
|
199
197
|
# The remaining occurrences (same requirements as all_occurrences)
|
@@ -228,7 +226,7 @@ module IceCube
|
|
228
226
|
# occurrences at the end of the range since none of their duration
|
229
227
|
# intersects the range.
|
230
228
|
def occurring_between?(opening_time, closing_time)
|
231
|
-
occurs_between?(opening_time, closing_time, :
|
229
|
+
occurs_between?(opening_time, closing_time, spans: true)
|
232
230
|
end
|
233
231
|
|
234
232
|
# Return a boolean indicating if an occurrence falls on a certain date
|
@@ -306,7 +304,7 @@ module IceCube
|
|
306
304
|
def last(n = nil)
|
307
305
|
require_terminating_rules
|
308
306
|
occurrences = enumerate_occurrences(start_time).to_a
|
309
|
-
n.nil? ? occurrences.last : occurrences[-n
|
307
|
+
n.nil? ? occurrences.last : occurrences[-n..]
|
310
308
|
end
|
311
309
|
|
312
310
|
# String serialization
|
@@ -314,13 +312,13 @@ module IceCube
|
|
314
312
|
pieces = []
|
315
313
|
rd = recurrence_times_with_start_time - extimes
|
316
314
|
pieces.concat rd.sort.map { |t| IceCube::I18n.l(t, format: IceCube.to_s_time_format) }
|
317
|
-
pieces.concat rrules.map
|
318
|
-
pieces.concat exrules.map { |t| IceCube::I18n.t(
|
315
|
+
pieces.concat rrules.map { |t| t.to_s }
|
316
|
+
pieces.concat exrules.map { |t| IceCube::I18n.t("ice_cube.not", target: t.to_s) }
|
319
317
|
pieces.concat extimes.sort.map { |t|
|
320
318
|
target = IceCube::I18n.l(t, format: IceCube.to_s_time_format)
|
321
|
-
IceCube::I18n.t(
|
319
|
+
IceCube::I18n.t("ice_cube.not_on", target: target)
|
322
320
|
}
|
323
|
-
pieces.join(IceCube::I18n.t(
|
321
|
+
pieces.join(IceCube::I18n.t("ice_cube.pieces_connector"))
|
324
322
|
end
|
325
323
|
|
326
324
|
# Serialize this schedule to_ical
|
@@ -328,9 +326,9 @@ module IceCube
|
|
328
326
|
pieces = []
|
329
327
|
pieces << "DTSTART#{IcalBuilder.ical_format(start_time, force_utc)}"
|
330
328
|
pieces.concat recurrence_rules.map { |r| "RRULE:#{r.to_ical}" }
|
331
|
-
pieces.concat exception_rules.map
|
329
|
+
pieces.concat exception_rules.map { |r| "EXRULE:#{r.to_ical}" }
|
332
330
|
pieces.concat recurrence_times_without_start_time.map { |t| "RDATE#{IcalBuilder.ical_format(t, force_utc)}" }
|
333
|
-
pieces.concat exception_times.map
|
331
|
+
pieces.concat exception_times.map { |t| "EXDATE#{IcalBuilder.ical_format(t, force_utc)}" }
|
334
332
|
pieces << "DTEND#{IcalBuilder.ical_format(end_time, force_utc)}" if end_time
|
335
333
|
pieces.join("\n")
|
336
334
|
end
|
@@ -360,9 +358,7 @@ module IceCube
|
|
360
358
|
data[:start_date] = data[:start_time] if IceCube.compatibility <= 11
|
361
359
|
data[:end_time] = TimeUtil.serialize_time(end_time) if end_time
|
362
360
|
data[:rrules] = recurrence_rules.map(&:to_hash)
|
363
|
-
|
364
|
-
data[:exrules] = exception_rules.map(&:to_hash)
|
365
|
-
end
|
361
|
+
data[:exrules] = exception_rules.map(&:to_hash) if exception_rules.any?
|
366
362
|
data[:rtimes] = recurrence_times.map do |rt|
|
367
363
|
TimeUtil.serialize_time(rt)
|
368
364
|
end
|
@@ -396,9 +392,9 @@ module IceCube
|
|
396
392
|
end
|
397
393
|
|
398
394
|
def eql?(other)
|
399
|
-
|
395
|
+
hash == other.hash
|
400
396
|
end
|
401
|
-
|
397
|
+
alias_method :==, :eql?
|
402
398
|
|
403
399
|
def self.dump(schedule)
|
404
400
|
return schedule if schedule.nil? || schedule == ""
|
@@ -435,7 +431,7 @@ module IceCube
|
|
435
431
|
loop do
|
436
432
|
break unless (t0 = next_time(t1, closing_time))
|
437
433
|
break if closing_time && t0 > closing_time
|
438
|
-
if
|
434
|
+
if spans ? (t0.end_time > opening_time) : (t0 >= opening_time)
|
439
435
|
yielder << (block_given? ? yield(t0) : t0)
|
440
436
|
end
|
441
437
|
t1 = t0 + 1
|
@@ -447,12 +443,10 @@ module IceCube
|
|
447
443
|
def next_time(time, closing_time)
|
448
444
|
loop do
|
449
445
|
min_time = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |best_time, rule|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
best_time
|
455
|
-
end
|
446
|
+
new_time = rule.next_time(time, start_time, best_time || closing_time)
|
447
|
+
[best_time, new_time].compact.min
|
448
|
+
rescue StopIteration
|
449
|
+
best_time
|
456
450
|
end
|
457
451
|
break unless min_time
|
458
452
|
next (time = min_time + 1) if exception_time?(min_time)
|
@@ -464,7 +458,7 @@ module IceCube
|
|
464
458
|
# If we have rules with counts, we need to walk from the beginning of time
|
465
459
|
def full_required?
|
466
460
|
@all_recurrence_rules.any?(&:full_required?) ||
|
467
|
-
|
461
|
+
@all_exception_rules.any?(&:full_required?)
|
468
462
|
end
|
469
463
|
|
470
464
|
# Return a boolean indicating whether or not a specific time
|
@@ -477,7 +471,7 @@ module IceCube
|
|
477
471
|
|
478
472
|
def require_terminating_rules
|
479
473
|
return true if terminating?
|
480
|
-
method_name = caller
|
474
|
+
method_name = caller(1..1).first.split(" ").last
|
481
475
|
raise ArgumentError, "All recurrence rules must specify .until or .count to use #{method_name}"
|
482
476
|
end
|
483
477
|
|
@@ -504,7 +498,5 @@ module IceCube
|
|
504
498
|
@all_recurrence_rules
|
505
499
|
end
|
506
500
|
end
|
507
|
-
|
508
501
|
end
|
509
|
-
|
510
502
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module IceCube
|
2
|
-
|
3
2
|
class SingleOccurrenceRule < Rule
|
4
|
-
|
5
3
|
attr_reader :time
|
6
4
|
|
7
5
|
def initialize(time)
|
@@ -20,13 +18,11 @@ module IceCube
|
|
20
18
|
end
|
21
19
|
|
22
20
|
def to_hash
|
23
|
-
{
|
21
|
+
{time: time}
|
24
22
|
end
|
25
23
|
|
26
24
|
def full_required?
|
27
25
|
false
|
28
26
|
end
|
29
|
-
|
30
27
|
end
|
31
|
-
|
32
28
|
end
|