ice_cube 0.15.0 → 0.16.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/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
|