ice_cube 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ice_cube/deprecated.rb +4 -3
- data/lib/ice_cube/parsers/ical_parser.rb +1 -0
- data/lib/ice_cube/rule.rb +23 -9
- data/lib/ice_cube/rules/daily_rule.rb +1 -1
- data/lib/ice_cube/rules/hourly_rule.rb +1 -1
- data/lib/ice_cube/rules/minutely_rule.rb +1 -1
- data/lib/ice_cube/rules/monthly_rule.rb +1 -1
- data/lib/ice_cube/rules/secondly_rule.rb +1 -1
- data/lib/ice_cube/rules/weekly_rule.rb +27 -1
- data/lib/ice_cube/rules/yearly_rule.rb +1 -1
- data/lib/ice_cube/schedule.rb +7 -27
- data/lib/ice_cube/single_occurrence_rule.rb +1 -1
- data/lib/ice_cube/time_util.rb +3 -3
- data/lib/ice_cube/validated_rule.rb +16 -5
- data/lib/ice_cube/validations/count.rb +3 -3
- data/lib/ice_cube/validations/daily_interval.rb +2 -2
- data/lib/ice_cube/validations/day.rb +2 -2
- data/lib/ice_cube/validations/day_of_month.rb +2 -2
- data/lib/ice_cube/validations/day_of_week.rb +1 -1
- data/lib/ice_cube/validations/day_of_year.rb +4 -4
- data/lib/ice_cube/validations/fixed_value.rb +10 -10
- data/lib/ice_cube/validations/hour_of_day.rb +2 -2
- data/lib/ice_cube/validations/hourly_interval.rb +2 -2
- data/lib/ice_cube/validations/lock.rb +10 -10
- data/lib/ice_cube/validations/minute_of_hour.rb +2 -2
- data/lib/ice_cube/validations/minutely_interval.rb +2 -2
- data/lib/ice_cube/validations/month_of_year.rb +2 -2
- data/lib/ice_cube/validations/monthly_interval.rb +2 -2
- data/lib/ice_cube/validations/second_of_minute.rb +2 -2
- data/lib/ice_cube/validations/secondly_interval.rb +2 -2
- data/lib/ice_cube/validations/until.rb +2 -2
- data/lib/ice_cube/validations/weekly_interval.rb +3 -6
- data/lib/ice_cube/validations/yearly_interval.rb +2 -2
- data/lib/ice_cube/version.rb +1 -1
- data/spec/spec_helper.rb +15 -23
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01f55d89af28400fc30bdfe60ccacd66e42212b0
|
4
|
+
data.tar.gz: a7e85b8afe0d56f8b47c3e22139d080e035ee465
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a87067a8e0a099b1f9740bd4dab4ed408c72827c1498370b81ba3df3f6246fc7be12f8343f63832554dfa990f1754e5af365755831490d767df84b3462d49a41
|
7
|
+
data.tar.gz: d41ba1b2a5dc98db1522a38320452d9404a92510872a0473ba6dc9b440a5258352ea484ce28dc663908bf6bc19d747f4099035549865745377e4be9f035aed28
|
data/lib/ice_cube/deprecated.rb
CHANGED
@@ -7,7 +7,7 @@ module IceCube
|
|
7
7
|
def deprecated_alias(name, replacement)
|
8
8
|
# Create a wrapped version
|
9
9
|
define_method(name) do |*args, &block|
|
10
|
-
warn "IceCube: #{self.class}##{name} is deprecated
|
10
|
+
warn "IceCube: #{self.class}##{name} is deprecated (use #{replacement})", caller[0]
|
11
11
|
send replacement, *args, &block
|
12
12
|
end
|
13
13
|
end
|
@@ -21,14 +21,15 @@ module IceCube
|
|
21
21
|
alias_method old_name, name
|
22
22
|
# And replace it with a wrapped version
|
23
23
|
define_method(name) do |*args, &block|
|
24
|
-
warn "IceCube: #{self.class}##{name} is deprecated
|
24
|
+
warn "IceCube: #{self.class}##{name} is deprecated (use #{replacement})", caller[0]
|
25
25
|
send old_name, *args, &block
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.schedule_options(schedule, options)
|
30
30
|
if options[:start_date_override]
|
31
|
-
warn "IceCube: :start_date_override option is deprecated
|
31
|
+
warn "IceCube: :start_date_override option is deprecated " \
|
32
|
+
"(use a block: `{|s| s.start_time = override }`)", caller[0]
|
32
33
|
schedule.start_time = options[:start_date_override]
|
33
34
|
end
|
34
35
|
end
|
data/lib/ice_cube/rule.rb
CHANGED
@@ -11,6 +11,9 @@ module IceCube
|
|
11
11
|
|
12
12
|
attr_reader :uses
|
13
13
|
|
14
|
+
def reset
|
15
|
+
end
|
16
|
+
|
14
17
|
# Is this a terminating schedule?
|
15
18
|
def terminating?
|
16
19
|
until_time || occurrence_count
|
@@ -51,11 +54,6 @@ module IceCube
|
|
51
54
|
raise MethodNotImplemented, "Expected to be overridden by subclasses"
|
52
55
|
end
|
53
56
|
|
54
|
-
# Reset the uses on the rule to 0
|
55
|
-
def reset
|
56
|
-
@uses = 0
|
57
|
-
end
|
58
|
-
|
59
57
|
def next_time(time, schedule, closing_time)
|
60
58
|
end
|
61
59
|
|
@@ -73,18 +71,30 @@ module IceCube
|
|
73
71
|
# Convert from a hash and create a rule
|
74
72
|
def from_hash(original_hash)
|
75
73
|
hash = IceCube::FlexibleHash.new original_hash
|
76
|
-
|
74
|
+
|
75
|
+
unless hash[:rule_type] && match = hash[:rule_type].match(/\:\:(.+?)Rule/)
|
76
|
+
raise ArgumentError, 'Invalid rule type'
|
77
|
+
end
|
77
78
|
|
78
79
|
interval_type = match[1].downcase.to_sym
|
79
|
-
|
80
|
+
|
81
|
+
unless INTERVAL_TYPES.include?(interval_type)
|
82
|
+
raise ArgumentError, "Invalid rule frequency type: #{match[1]}"
|
83
|
+
end
|
80
84
|
|
81
85
|
rule = IceCube::Rule.send(interval_type, hash[:interval] || 1)
|
82
|
-
|
86
|
+
|
87
|
+
if match[1] == "Weekly"
|
88
|
+
rule.interval(hash[:interval] || 1, TimeUtil.wday_to_sym(hash[:week_start] || 0))
|
89
|
+
end
|
90
|
+
|
83
91
|
rule.until(TimeUtil.deserialize_time(hash[:until])) if hash[:until]
|
84
92
|
rule.count(hash[:count]) if hash[:count]
|
93
|
+
|
85
94
|
hash[:validations] && hash[:validations].each do |name, args|
|
86
95
|
apply_validation(rule, name, args)
|
87
96
|
end
|
97
|
+
|
88
98
|
rule
|
89
99
|
end
|
90
100
|
|
@@ -92,7 +102,11 @@ module IceCube
|
|
92
102
|
|
93
103
|
def apply_validation(rule, name, args)
|
94
104
|
name = name.to_sym
|
95
|
-
|
105
|
+
|
106
|
+
unless ValidatedRule::VALIDATION_ORDER.include?(name)
|
107
|
+
raise ArgumentError, "Invalid rule validation type: #{name}"
|
108
|
+
end
|
109
|
+
|
96
110
|
args.is_a?(Array) ? rule.send(name, *args) : rule.send(name, args)
|
97
111
|
end
|
98
112
|
|
@@ -4,13 +4,39 @@ module IceCube
|
|
4
4
|
|
5
5
|
include Validations::WeeklyInterval
|
6
6
|
|
7
|
+
attr_reader :week_start
|
8
|
+
|
7
9
|
def initialize(interval = 1, week_start = :sunday)
|
8
|
-
super
|
10
|
+
super(interval)
|
9
11
|
interval(interval, week_start)
|
10
12
|
schedule_lock(:wday, :hour, :min, :sec)
|
11
13
|
reset
|
12
14
|
end
|
13
15
|
|
16
|
+
# Calculate the effective start time for when the given start time is later
|
17
|
+
# in the week than one of the weekday validations, such that times could be
|
18
|
+
# missed by a 7-day jump using the weekly interval, or when selecting from a
|
19
|
+
# date that is misaligned from the schedule interval.
|
20
|
+
#
|
21
|
+
def realign(step_time, start_time)
|
22
|
+
time = TimeUtil::TimeWrapper.new(start_time)
|
23
|
+
offset = wday_offset(step_time, start_time)
|
24
|
+
time.add(:day, offset) if offset
|
25
|
+
time.to_time
|
26
|
+
end
|
27
|
+
|
28
|
+
def wday_offset(step_time, start_time)
|
29
|
+
wday_validations = other_interval_validations.select { |v| v.type == :wday }
|
30
|
+
return if wday_validations.none?
|
31
|
+
|
32
|
+
days = (step_time - start_time).to_i / ONE_DAY
|
33
|
+
interval = base_interval_validation.validate(step_time, start_time).to_i
|
34
|
+
min_wday = TimeUtil.normalize_wday(wday_validations.min_by(&:day).day, week_start)
|
35
|
+
step_wday = TimeUtil.normalize_wday(step_time.wday, week_start)
|
36
|
+
|
37
|
+
days + interval - step_wday + min_wday
|
38
|
+
end
|
39
|
+
|
14
40
|
end
|
15
41
|
|
16
42
|
end
|
data/lib/ice_cube/schedule.rb
CHANGED
@@ -46,7 +46,7 @@ module IceCube
|
|
46
46
|
|
47
47
|
# Add a recurrence time to the schedule
|
48
48
|
def add_recurrence_time(time)
|
49
|
-
return
|
49
|
+
return if time.nil?
|
50
50
|
rule = SingleOccurrenceRule.new(time)
|
51
51
|
add_recurrence_rule rule
|
52
52
|
time
|
@@ -57,7 +57,7 @@ module IceCube
|
|
57
57
|
|
58
58
|
# Add an exception time to the schedule
|
59
59
|
def add_exception_time(time)
|
60
|
-
return
|
60
|
+
return if time.nil?
|
61
61
|
rule = SingleOccurrenceRule.new(time)
|
62
62
|
add_exception_rule rule
|
63
63
|
time
|
@@ -68,6 +68,7 @@ module IceCube
|
|
68
68
|
|
69
69
|
# Add a recurrence rule to the schedule
|
70
70
|
def add_recurrence_rule(rule)
|
71
|
+
return if rule.nil?
|
71
72
|
@all_recurrence_rules << rule unless @all_recurrence_rules.include?(rule)
|
72
73
|
end
|
73
74
|
alias :rrule :add_recurrence_rule
|
@@ -80,6 +81,7 @@ module IceCube
|
|
80
81
|
|
81
82
|
# Add an exception rule to the schedule
|
82
83
|
def add_exception_rule(rule)
|
84
|
+
return if rule.nil?
|
83
85
|
@all_exception_rules << rule unless @all_exception_rules.include?(rule)
|
84
86
|
end
|
85
87
|
alias :exrule :add_exception_rule
|
@@ -413,7 +415,7 @@ module IceCube
|
|
413
415
|
spans = options[:spans] == true && duration != 0
|
414
416
|
Enumerator.new do |yielder|
|
415
417
|
reset
|
416
|
-
t1 = full_required? ? start_time :
|
418
|
+
t1 = full_required? ? start_time : opening_time - (spans ? duration : 0)
|
417
419
|
loop do
|
418
420
|
break unless (t0 = next_time(t1, closing_time))
|
419
421
|
break if closing_time && t0 > closing_time
|
@@ -439,7 +441,7 @@ module IceCube
|
|
439
441
|
loop do
|
440
442
|
min_time = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |min_time, rule|
|
441
443
|
begin
|
442
|
-
new_time = rule.next_time(time,
|
444
|
+
new_time = rule.next_time(time, start_time, min_time || closing_time)
|
443
445
|
[min_time, new_time].compact.min
|
444
446
|
rescue StopIteration
|
445
447
|
min_time
|
@@ -462,7 +464,7 @@ module IceCube
|
|
462
464
|
# is excluded from the schedule
|
463
465
|
def exception_time?(time)
|
464
466
|
@all_exception_rules.any? do |rule|
|
465
|
-
rule.on?(time,
|
467
|
+
rule.on?(time, start_time)
|
466
468
|
end
|
467
469
|
end
|
468
470
|
|
@@ -502,28 +504,6 @@ module IceCube
|
|
502
504
|
end
|
503
505
|
end
|
504
506
|
|
505
|
-
# If any rule has validations for values within the period, (overriding the
|
506
|
-
# interval from start time, e.g. `day[_of_week]`), and the opening time is
|
507
|
-
# offset from the interval multiplier such that it might miss the first
|
508
|
-
# correct occurrence (e.g. repeat is every N weeks, but selecting from end
|
509
|
-
# of week N-1, the first jump would go to end of week N and miss any
|
510
|
-
# earlier validations in the week). This realigns the opening time to
|
511
|
-
# the start of the interval's correct period (e.g. move to start of week N)
|
512
|
-
# TODO: check if this is needed for validations other than `:wday`
|
513
|
-
#
|
514
|
-
def realign(opening_time)
|
515
|
-
time = TimeUtil::TimeWrapper.new(opening_time)
|
516
|
-
recurrence_rules.each do |rule|
|
517
|
-
wday_validations = rule.other_interval_validations.select { |v| v.type == :wday } or next
|
518
|
-
interval = rule.base_interval_validation.validate(opening_time, self).to_i
|
519
|
-
offset = wday_validations
|
520
|
-
.map { |v| v.validate(opening_time, self).to_i }
|
521
|
-
.reduce(0) { |least, i| i > 0 && i <= interval && (i < least || least == 0) ? i : least }
|
522
|
-
time.add(rule.base_interval_type, 7 - time.to_time.wday) if offset > 0
|
523
|
-
end
|
524
|
-
time.to_time
|
525
|
-
end
|
526
|
-
|
527
507
|
end
|
528
508
|
|
529
509
|
end
|
data/lib/ice_cube/time_util.rb
CHANGED
@@ -135,7 +135,7 @@ module IceCube
|
|
135
135
|
def self.sym_to_month(sym)
|
136
136
|
MONTHS.fetch(sym) do |k|
|
137
137
|
MONTHS.values.detect { |i| i.to_s == k.to_s } or
|
138
|
-
raise ArgumentError, "Expecting
|
138
|
+
raise ArgumentError, "Expecting Integer or Symbol value for month. " \
|
139
139
|
"No such month: #{k.inspect}"
|
140
140
|
end
|
141
141
|
end
|
@@ -145,7 +145,7 @@ module IceCube
|
|
145
145
|
def self.sym_to_wday(sym)
|
146
146
|
DAYS.fetch(sym) do |k|
|
147
147
|
DAYS.values.detect { |i| i.to_s == k.to_s } or
|
148
|
-
raise ArgumentError, "Expecting
|
148
|
+
raise ArgumentError, "Expecting Integer or Symbol value for weekday. " \
|
149
149
|
"No such weekday: #{k.inspect}"
|
150
150
|
end
|
151
151
|
end
|
@@ -155,7 +155,7 @@ module IceCube
|
|
155
155
|
def self.wday_to_sym(wday)
|
156
156
|
return sym = wday if DAYS.keys.include? wday
|
157
157
|
DAYS.invert.fetch(wday) do |i|
|
158
|
-
raise ArgumentError, "Expecting
|
158
|
+
raise ArgumentError, "Expecting Integer value for weekday. " \
|
159
159
|
"No such wday number: #{i.inspect}"
|
160
160
|
end
|
161
161
|
end
|
@@ -32,10 +32,17 @@ module IceCube
|
|
32
32
|
|
33
33
|
attr_reader :validations
|
34
34
|
|
35
|
-
def initialize(interval = 1
|
35
|
+
def initialize(interval = 1)
|
36
36
|
@validations = Hash.new
|
37
37
|
end
|
38
38
|
|
39
|
+
# Reset the uses on the rule to 0
|
40
|
+
def reset
|
41
|
+
@time = nil
|
42
|
+
@start_time = nil
|
43
|
+
@uses = 0
|
44
|
+
end
|
45
|
+
|
39
46
|
def base_interval_validation
|
40
47
|
@validations[:interval].first
|
41
48
|
end
|
@@ -49,10 +56,10 @@ module IceCube
|
|
49
56
|
end
|
50
57
|
|
51
58
|
# Compute the next time after (or including) the specified time in respect
|
52
|
-
# to the given
|
53
|
-
def next_time(time,
|
59
|
+
# to the given start time
|
60
|
+
def next_time(time, start_time, closing_time)
|
54
61
|
@time = time
|
55
|
-
@
|
62
|
+
@start_time ||= realign(time, start_time)
|
56
63
|
|
57
64
|
return nil unless find_acceptable_time_before(closing_time)
|
58
65
|
|
@@ -60,6 +67,10 @@ module IceCube
|
|
60
67
|
@time
|
61
68
|
end
|
62
69
|
|
70
|
+
def realign(opening_time, start_time)
|
71
|
+
start_time
|
72
|
+
end
|
73
|
+
|
63
74
|
def skipped_for_dst
|
64
75
|
@uses -= 1 if @uses > 0
|
65
76
|
end
|
@@ -145,7 +156,7 @@ module IceCube
|
|
145
156
|
#
|
146
157
|
def validation_accepts_or_updates_time?(validations_for_type)
|
147
158
|
res = validations_for_type.each_with_object([]) do |validation, offsets|
|
148
|
-
r = validation.validate(@time, @
|
159
|
+
r = validation.validate(@time, @start_time)
|
149
160
|
return true if r.nil? || r == 0
|
150
161
|
offsets << r
|
151
162
|
end
|
@@ -8,8 +8,8 @@ module IceCube
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def count(max)
|
11
|
-
unless max.nil? || max.is_a?(
|
12
|
-
raise ArgumentError, "Expecting
|
11
|
+
unless max.nil? || max.is_a?(Integer)
|
12
|
+
raise ArgumentError, "Expecting Integer or nil value for count, got #{max.inspect}"
|
13
13
|
end
|
14
14
|
@count = max
|
15
15
|
replace_validations_for(:count, max && [Validation.new(max, self)])
|
@@ -33,7 +33,7 @@ module IceCube
|
|
33
33
|
false
|
34
34
|
end
|
35
35
|
|
36
|
-
def validate(time,
|
36
|
+
def validate(time, start_time)
|
37
37
|
raise CountExceeded if rule.uses && rule.uses >= count
|
38
38
|
end
|
39
39
|
|
@@ -26,8 +26,8 @@ module IceCube
|
|
26
26
|
true
|
27
27
|
end
|
28
28
|
|
29
|
-
def validate(step_time,
|
30
|
-
t0, t1 =
|
29
|
+
def validate(step_time, start_time)
|
30
|
+
t0, t1 = start_time, step_time
|
31
31
|
days = Date.new(t1.year, t1.month, t1.day) -
|
32
32
|
Date.new(t0.year, t0.month, t0.day)
|
33
33
|
offset = (days % interval).nonzero?
|
@@ -8,8 +8,8 @@ module IceCube
|
|
8
8
|
days = days.flatten
|
9
9
|
return self if days.empty?
|
10
10
|
days.flatten.each do |day|
|
11
|
-
unless day.is_a?(
|
12
|
-
raise ArgumentError, "expecting
|
11
|
+
unless day.is_a?(Integer) || day.is_a?(Symbol)
|
12
|
+
raise ArgumentError, "expecting Integer or Symbol value for day, got #{day.inspect}"
|
13
13
|
end
|
14
14
|
day = TimeUtil.sym_to_wday(day)
|
15
15
|
validations_for(:day) << Validation.new(day)
|
@@ -4,8 +4,8 @@ module IceCube
|
|
4
4
|
|
5
5
|
def day_of_month(*days)
|
6
6
|
days.flatten.each do |day|
|
7
|
-
unless day.is_a?(
|
8
|
-
raise ArgumentError, "expecting
|
7
|
+
unless day.is_a?(Integer)
|
8
|
+
raise ArgumentError, "expecting Integer value for day, got #{day.inspect}"
|
9
9
|
end
|
10
10
|
validations_for(:day_of_month) << Validation.new(day)
|
11
11
|
end
|
@@ -4,8 +4,8 @@ module IceCube
|
|
4
4
|
|
5
5
|
def day_of_year(*days)
|
6
6
|
days.flatten.each do |day|
|
7
|
-
unless day.is_a?(
|
8
|
-
raise ArgumentError, "expecting
|
7
|
+
unless day.is_a?(Integer)
|
8
|
+
raise ArgumentError, "expecting Integer value for day, got #{day.inspect}"
|
9
9
|
end
|
10
10
|
validations_for(:day_of_year) << Validation.new(day)
|
11
11
|
end
|
@@ -29,9 +29,9 @@ module IceCube
|
|
29
29
|
true
|
30
30
|
end
|
31
31
|
|
32
|
-
def validate(step_time,
|
32
|
+
def validate(step_time, start_time)
|
33
33
|
days_in_year = TimeUtil.days_in_year(step_time)
|
34
|
-
yday = day < 0 ? day + days_in_year : day
|
34
|
+
yday = day < 0 ? day + days_in_year + 1 : day
|
35
35
|
offset = yday - step_time.yday
|
36
36
|
offset >= 0 ? offset : offset + days_in_year
|
37
37
|
end
|
@@ -12,11 +12,11 @@ module IceCube
|
|
12
12
|
|
13
13
|
INTERVALS = {:min => 60, :sec => 60, :hour => 24, :month => 12, :wday => 7}
|
14
14
|
|
15
|
-
def validate(time,
|
15
|
+
def validate(time, start_time)
|
16
16
|
case type
|
17
|
-
when :day then validate_day_lock(time,
|
18
|
-
when :hour then validate_hour_lock(time,
|
19
|
-
else validate_interval_lock(time,
|
17
|
+
when :day then validate_day_lock(time, start_time)
|
18
|
+
when :hour then validate_hour_lock(time, start_time)
|
19
|
+
else validate_interval_lock(time, start_time)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
# Validate if the current time unit matches the same unit from the schedule
|
26
26
|
# start time, returning the difference to the interval
|
27
27
|
#
|
28
|
-
def validate_interval_lock(time,
|
29
|
-
t0 = starting_unit(
|
28
|
+
def validate_interval_lock(time, start_time)
|
29
|
+
t0 = starting_unit(start_time)
|
30
30
|
t1 = time.send(type)
|
31
31
|
t0 >= t1 ? t0 - t1 : INTERVALS[type] - t1 + t0
|
32
32
|
end
|
@@ -34,8 +34,8 @@ module IceCube
|
|
34
34
|
# Lock the hour if explicitly set by hour_of_day, but allow for the nearest
|
35
35
|
# hour during DST start to keep the correct interval.
|
36
36
|
#
|
37
|
-
def validate_hour_lock(time,
|
38
|
-
h0 = starting_unit(
|
37
|
+
def validate_hour_lock(time, start_time)
|
38
|
+
h0 = starting_unit(start_time)
|
39
39
|
h1 = time.hour
|
40
40
|
if h0 >= h1
|
41
41
|
h0 - h1
|
@@ -57,7 +57,7 @@ module IceCube
|
|
57
57
|
# Positive day values are taken literally so months with fewer days will
|
58
58
|
# be skipped.
|
59
59
|
#
|
60
|
-
def validate_day_lock(time,
|
60
|
+
def validate_day_lock(time, start_time)
|
61
61
|
days_in_month = TimeUtil.days_in_month(time)
|
62
62
|
date = Date.new(time.year, time.month, time.day)
|
63
63
|
|
@@ -68,7 +68,7 @@ module IceCube
|
|
68
68
|
start = value
|
69
69
|
month_overflow = 0
|
70
70
|
else
|
71
|
-
start = TimeUtil.day_of_month(
|
71
|
+
start = TimeUtil.day_of_month(start_time.day, date)
|
72
72
|
month_overflow = 0
|
73
73
|
end
|
74
74
|
|
@@ -5,8 +5,8 @@ module IceCube
|
|
5
5
|
# Add hour of day validations
|
6
6
|
def hour_of_day(*hours)
|
7
7
|
hours.flatten.each do |hour|
|
8
|
-
unless hour.is_a?(
|
9
|
-
raise ArgumentError, "expecting
|
8
|
+
unless hour.is_a?(Integer)
|
9
|
+
raise ArgumentError, "expecting Integer value for hour, got #{hour.inspect}"
|
10
10
|
end
|
11
11
|
validations_for(:hour_of_day) << Validation.new(hour)
|
12
12
|
end
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
false
|
26
26
|
end
|
27
27
|
|
28
|
-
def validate(step_time,
|
29
|
-
t0, t1 =
|
28
|
+
def validate(step_time, start_time)
|
29
|
+
t0, t1 = start_time.to_i, step_time.to_i
|
30
30
|
sec = (t1 - t1 % ONE_HOUR) -
|
31
31
|
(t0 - t0 % ONE_HOUR)
|
32
32
|
hours = sec / ONE_HOUR
|
@@ -12,11 +12,11 @@ module IceCube
|
|
12
12
|
|
13
13
|
INTERVALS = {:min => 60, :sec => 60, :hour => 24, :month => 12, :wday => 7}
|
14
14
|
|
15
|
-
def validate(time,
|
15
|
+
def validate(time, start_time)
|
16
16
|
case type
|
17
|
-
when :day then validate_day_lock(time,
|
18
|
-
when :hour then validate_hour_lock(time,
|
19
|
-
else validate_interval_lock(time,
|
17
|
+
when :day then validate_day_lock(time, start_time)
|
18
|
+
when :hour then validate_hour_lock(time, start_time)
|
19
|
+
else validate_interval_lock(time, start_time)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
# Validate if the current time unit matches the same unit from the schedule
|
26
26
|
# start time, returning the difference to the interval
|
27
27
|
#
|
28
|
-
def validate_interval_lock(time,
|
29
|
-
t0 = starting_unit(
|
28
|
+
def validate_interval_lock(time, start_time)
|
29
|
+
t0 = starting_unit(start_time)
|
30
30
|
t1 = time.send(type)
|
31
31
|
t0 >= t1 ? t0 - t1 : INTERVALS[type] - t1 + t0
|
32
32
|
end
|
@@ -34,8 +34,8 @@ module IceCube
|
|
34
34
|
# Lock the hour if explicitly set by hour_of_day, but allow for the nearest
|
35
35
|
# hour during DST start to keep the correct interval.
|
36
36
|
#
|
37
|
-
def validate_hour_lock(time,
|
38
|
-
h0 = starting_unit(
|
37
|
+
def validate_hour_lock(time, start_time)
|
38
|
+
h0 = starting_unit(start_time)
|
39
39
|
h1 = time.hour
|
40
40
|
if h0 >= h1
|
41
41
|
h0 - h1
|
@@ -57,7 +57,7 @@ module IceCube
|
|
57
57
|
# Positive day values are taken literally so months with fewer days will
|
58
58
|
# be skipped.
|
59
59
|
#
|
60
|
-
def validate_day_lock(time,
|
60
|
+
def validate_day_lock(time, start_time)
|
61
61
|
days_in_month = TimeUtil.days_in_month(time)
|
62
62
|
date = Date.new(time.year, time.month, time.day)
|
63
63
|
|
@@ -68,7 +68,7 @@ module IceCube
|
|
68
68
|
start = value
|
69
69
|
month_overflow = 0
|
70
70
|
else
|
71
|
-
start = TimeUtil.day_of_month(
|
71
|
+
start = TimeUtil.day_of_month(start_time.day, date)
|
72
72
|
month_overflow = 0
|
73
73
|
end
|
74
74
|
|
@@ -4,8 +4,8 @@ module IceCube
|
|
4
4
|
|
5
5
|
def minute_of_hour(*minutes)
|
6
6
|
minutes.flatten.each do |minute|
|
7
|
-
unless minute.is_a?(
|
8
|
-
raise ArgumentError, "expecting
|
7
|
+
unless minute.is_a?(Integer)
|
8
|
+
raise ArgumentError, "expecting Integer value for minute, got #{minute.inspect}"
|
9
9
|
end
|
10
10
|
validations_for(:minute_of_hour) << Validation.new(minute)
|
11
11
|
end
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
false
|
26
26
|
end
|
27
27
|
|
28
|
-
def validate(step_time,
|
29
|
-
t0, t1 =
|
28
|
+
def validate(step_time, start_time)
|
29
|
+
t0, t1 = start_time.to_i, step_time.to_i
|
30
30
|
sec = (t1 - t1 % ONE_MINUTE) -
|
31
31
|
(t0 - t0 % ONE_MINUTE)
|
32
32
|
minutes = sec / ONE_MINUTE
|
@@ -4,8 +4,8 @@ module IceCube
|
|
4
4
|
|
5
5
|
def month_of_year(*months)
|
6
6
|
months.flatten.each do |month|
|
7
|
-
unless month.is_a?(
|
8
|
-
raise ArgumentError, "expecting
|
7
|
+
unless month.is_a?(Integer) || month.is_a?(Symbol)
|
8
|
+
raise ArgumentError, "expecting Integer or Symbol value for month, got #{month.inspect}"
|
9
9
|
end
|
10
10
|
month = TimeUtil.sym_to_month(month)
|
11
11
|
validations_for(:month_of_year) << Validation.new(month)
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
true
|
26
26
|
end
|
27
27
|
|
28
|
-
def validate(step_time,
|
29
|
-
t0, t1 =
|
28
|
+
def validate(step_time, start_time)
|
29
|
+
t0, t1 = start_time, step_time
|
30
30
|
months = (t1.month - t0.month) +
|
31
31
|
(t1.year - t0.year) * 12
|
32
32
|
offset = (months % interval).nonzero?
|
@@ -4,8 +4,8 @@ module IceCube
|
|
4
4
|
|
5
5
|
def second_of_minute(*seconds)
|
6
6
|
seconds.flatten.each do |second|
|
7
|
-
unless second.is_a?(
|
8
|
-
raise ArgumentError, "Expecting
|
7
|
+
unless second.is_a?(Integer)
|
8
|
+
raise ArgumentError, "Expecting Integer value for second, got #{second.inspect}"
|
9
9
|
end
|
10
10
|
validations_for(:second_of_minute) << Validation.new(second)
|
11
11
|
end
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
false
|
26
26
|
end
|
27
27
|
|
28
|
-
def validate(step_time,
|
29
|
-
seconds = step_time.to_i -
|
28
|
+
def validate(step_time, start_time)
|
29
|
+
seconds = step_time.to_i - start_time.to_i
|
30
30
|
offset = (seconds % interval).nonzero?
|
31
31
|
interval - offset if offset
|
32
32
|
end
|
@@ -32,8 +32,8 @@ module IceCube
|
|
32
32
|
false
|
33
33
|
end
|
34
34
|
|
35
|
-
def validate(step_time,
|
36
|
-
end_time = TimeUtil.ensure_time(time,
|
35
|
+
def validate(step_time, start_time)
|
36
|
+
end_time = TimeUtil.ensure_time(time, start_time, true)
|
37
37
|
raise UntilExceeded if step_time > end_time
|
38
38
|
end
|
39
39
|
|
@@ -12,10 +12,6 @@ module IceCube
|
|
12
12
|
self
|
13
13
|
end
|
14
14
|
|
15
|
-
def week_start
|
16
|
-
@week_start
|
17
|
-
end
|
18
|
-
|
19
15
|
class Validation
|
20
16
|
|
21
17
|
attr_reader :interval, :week_start
|
@@ -33,8 +29,9 @@ module IceCube
|
|
33
29
|
true
|
34
30
|
end
|
35
31
|
|
36
|
-
def validate(step_time,
|
37
|
-
|
32
|
+
def validate(step_time, start_time)
|
33
|
+
return if step_time < start_time
|
34
|
+
t0, t1 = start_time, step_time
|
38
35
|
d0 = Date.new(t0.year, t0.month, t0.day)
|
39
36
|
d1 = Date.new(t1.year, t1.month, t1.day)
|
40
37
|
days = (d1 - TimeUtil.normalize_wday(d1.wday, week_start)) -
|
@@ -25,8 +25,8 @@ module IceCube
|
|
25
25
|
true
|
26
26
|
end
|
27
27
|
|
28
|
-
def validate(step_time,
|
29
|
-
years = step_time.year -
|
28
|
+
def validate(step_time, start_time)
|
29
|
+
years = step_time.year - start_time.year
|
30
30
|
offset = (years % interval).nonzero?
|
31
31
|
interval - offset if offset
|
32
32
|
end
|
data/lib/ice_cube/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require 'ice_cube'
|
3
|
+
|
1
4
|
begin
|
2
5
|
require 'simplecov'
|
3
6
|
SimpleCov.start
|
@@ -5,8 +8,6 @@ rescue LoadError
|
|
5
8
|
# okay
|
6
9
|
end
|
7
10
|
|
8
|
-
require File.dirname(__FILE__) + '/../lib/ice_cube'
|
9
|
-
|
10
11
|
IceCube.compatibility = 12
|
11
12
|
|
12
13
|
DAY = Time.utc(2010, 3, 1)
|
@@ -19,46 +20,37 @@ WORLD_TIME_ZONES = [
|
|
19
20
|
]
|
20
21
|
|
21
22
|
RSpec.configure do |config|
|
23
|
+
# Enable flags like --only-failures and --next-failure
|
24
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
25
|
+
|
26
|
+
config.expect_with :rspec do |c|
|
27
|
+
c.syntax = :expect
|
28
|
+
end
|
29
|
+
|
22
30
|
Dir[File.dirname(__FILE__) + '/support/**/*'].each { |f| require f }
|
23
31
|
|
24
32
|
config.include WarningHelpers
|
25
33
|
|
26
|
-
config.
|
27
|
-
example.
|
28
|
-
|
29
|
-
|
30
|
-
config.around :each, :if_active_support_time => false do |example|
|
31
|
-
unless defined? ActiveSupport
|
32
|
-
stubbed_active_support = ::ActiveSupport = Module.new
|
33
|
-
example.run
|
34
|
-
Object.send :remove_const, :ActiveSupport
|
34
|
+
config.before :each do |example|
|
35
|
+
if example.metadata[:requires_active_support]
|
36
|
+
raise 'ActiveSupport required but not present' unless defined?(ActiveSupport)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
40
|
config.around :each do |example|
|
39
41
|
if zone = example.metadata[:system_time_zone]
|
40
|
-
|
42
|
+
orig_zone = ENV['TZ']
|
41
43
|
ENV['TZ'] = zone
|
42
44
|
example.run
|
43
|
-
ENV['TZ'] =
|
45
|
+
ENV['TZ'] = orig_zone
|
44
46
|
else
|
45
47
|
example.run
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
config.before :each do
|
50
|
-
if time_args = @example.metadata[:system_time]
|
51
|
-
case time_args
|
52
|
-
when Array then Time.stub!(:now).and_return Time.local(*time_args)
|
53
|
-
when Time then Time.stub!(:now).and_return time_args
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
51
|
config.around :each, expect_warnings: true do |example|
|
59
52
|
capture_warnings do
|
60
53
|
example.run
|
61
54
|
end
|
62
55
|
end
|
63
|
-
|
64
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ice_cube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Crepezzi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '3'
|
41
41
|
description: ice_cube is a recurring date library for Ruby. It allows for quick,
|
42
42
|
programatic expansion of recurring date rules.
|
43
43
|
email: john@crepezzi.com
|