ice_cube 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/ice_cube.rb +0 -11
- data/lib/ice_cube/builders/string_builder.rb +15 -23
- data/lib/ice_cube/deprecated.rb +26 -24
- data/lib/ice_cube/enumerator.rb +1 -3
- data/lib/ice_cube/hash_input.rb +71 -0
- data/lib/ice_cube/rule.rb +4 -6
- 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/yearly_rule.rb +1 -1
- data/lib/ice_cube/schedule.rb +4 -4
- data/lib/ice_cube/string_helpers.rb +10 -0
- data/lib/ice_cube/time_util.rb +14 -5
- data/lib/ice_cube/validations/count.rb +4 -6
- data/lib/ice_cube/validations/daily_interval.rb +13 -18
- data/lib/ice_cube/validations/day.rb +4 -4
- data/lib/ice_cube/validations/day_of_month.rb +8 -10
- data/lib/ice_cube/validations/day_of_week.rb +24 -26
- data/lib/ice_cube/validations/day_of_year.rb +11 -12
- data/lib/ice_cube/validations/hour_of_day.rb +9 -11
- data/lib/ice_cube/validations/hourly_interval.rb +18 -21
- data/lib/ice_cube/validations/lock.rb +35 -14
- data/lib/ice_cube/validations/minute_of_hour.rb +9 -11
- data/lib/ice_cube/validations/minutely_interval.rb +16 -19
- data/lib/ice_cube/validations/month_of_year.rb +4 -4
- data/lib/ice_cube/validations/monthly_interval.rb +15 -17
- data/lib/ice_cube/validations/schedule_lock.rb +12 -11
- data/lib/ice_cube/validations/second_of_minute.rb +5 -5
- data/lib/ice_cube/validations/secondly_interval.rb +13 -16
- data/lib/ice_cube/validations/until.rb +12 -12
- data/lib/ice_cube/validations/weekly_interval.rb +20 -23
- data/lib/ice_cube/validations/yearly_interval.rb +10 -11
- data/lib/ice_cube/version.rb +1 -1
- metadata +20 -33
@@ -10,8 +10,6 @@ module IceCube
|
|
10
10
|
self
|
11
11
|
end
|
12
12
|
|
13
|
-
# A validation for checking to make sure that a time
|
14
|
-
# is inside of a certain DailyInterval
|
15
13
|
class Validation
|
16
14
|
|
17
15
|
attr_reader :interval
|
@@ -20,6 +18,18 @@ module IceCube
|
|
20
18
|
@interval = interval
|
21
19
|
end
|
22
20
|
|
21
|
+
def type
|
22
|
+
:day
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate(step_time, schedule)
|
26
|
+
t0, t1 = schedule.start_time, step_time
|
27
|
+
days = Date.new(t1.year, t1.month, t1.day) -
|
28
|
+
Date.new(t0.year, t0.month, t0.day)
|
29
|
+
offset = (days % interval).nonzero?
|
30
|
+
interval - offset if offset
|
31
|
+
end
|
32
|
+
|
23
33
|
def build_s(builder)
|
24
34
|
builder.base = interval == 1 ? 'Daily' : "Every #{interval} days"
|
25
35
|
end
|
@@ -30,22 +40,7 @@ module IceCube
|
|
30
40
|
|
31
41
|
def build_ical(builder)
|
32
42
|
builder['FREQ'] << 'DAILY'
|
33
|
-
unless interval == 1
|
34
|
-
builder['INTERVAL'] << interval
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def type
|
39
|
-
:day
|
40
|
-
end
|
41
|
-
|
42
|
-
def validate(time, schedule)
|
43
|
-
time_date = Date.new(time.year, time.month, time.day)
|
44
|
-
start_date = Date.new(schedule.start_time.year, schedule.start_time.month, schedule.start_time.day)
|
45
|
-
days = time_date - start_date
|
46
|
-
unless days % interval === 0
|
47
|
-
interval - (days % interval)
|
48
|
-
end
|
43
|
+
builder['INTERVAL'] << interval unless interval == 1
|
49
44
|
end
|
50
45
|
|
51
46
|
end
|
@@ -27,6 +27,10 @@ module IceCube
|
|
27
27
|
@day = day
|
28
28
|
end
|
29
29
|
|
30
|
+
def type
|
31
|
+
:wday
|
32
|
+
end
|
33
|
+
|
30
34
|
def build_s(builder)
|
31
35
|
builder.piece(:day) << day
|
32
36
|
end
|
@@ -43,10 +47,6 @@ module IceCube
|
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
46
|
-
def type
|
47
|
-
:wday
|
48
|
-
end
|
49
|
-
|
50
50
|
StringBuilder.register_formatter(:day) do |validation_days|
|
51
51
|
# sort the days
|
52
52
|
validation_days.sort!
|
@@ -2,8 +2,6 @@ module IceCube
|
|
2
2
|
|
3
3
|
module Validations::DayOfMonth
|
4
4
|
|
5
|
-
include Validations::Lock
|
6
|
-
|
7
5
|
def day_of_month(*days)
|
8
6
|
days.flatten.each do |day|
|
9
7
|
unless day.is_a?(Fixnum)
|
@@ -19,12 +17,6 @@ module IceCube
|
|
19
17
|
|
20
18
|
include Validations::Lock
|
21
19
|
|
22
|
-
StringBuilder.register_formatter(:day_of_month) do |entries|
|
23
|
-
str = "on the #{StringBuilder.sentence(entries)} "
|
24
|
-
str << (entries.size == 1 ? 'day of the month' : 'days of the month')
|
25
|
-
str
|
26
|
-
end
|
27
|
-
|
28
20
|
attr_reader :day
|
29
21
|
alias :value :day
|
30
22
|
|
@@ -32,6 +24,10 @@ module IceCube
|
|
32
24
|
@day = day
|
33
25
|
end
|
34
26
|
|
27
|
+
def type
|
28
|
+
:day
|
29
|
+
end
|
30
|
+
|
35
31
|
def build_s(builder)
|
36
32
|
builder.piece(:day_of_month) << StringBuilder.nice_number(day)
|
37
33
|
end
|
@@ -44,8 +40,10 @@ module IceCube
|
|
44
40
|
builder['BYMONTHDAY'] << day
|
45
41
|
end
|
46
42
|
|
47
|
-
|
48
|
-
|
43
|
+
StringBuilder.register_formatter(:day_of_month) do |entries|
|
44
|
+
str = "on the #{StringBuilder.sentence(entries)} "
|
45
|
+
str << (entries.size == 1 ? 'day of the month' : 'days of the month')
|
46
|
+
str
|
49
47
|
end
|
50
48
|
|
51
49
|
end
|
@@ -17,23 +17,31 @@ module IceCube
|
|
17
17
|
|
18
18
|
attr_reader :day, :occ
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
def initialize(day, occ)
|
21
|
+
@day = day
|
22
|
+
@occ = occ
|
22
23
|
end
|
23
24
|
|
24
25
|
def type
|
25
26
|
:day
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
-
|
29
|
+
def validate(step_time, schedule)
|
30
|
+
wday = step_time.wday
|
31
|
+
offset = (day < wday) ? (7 - wday + day) : (day - wday)
|
32
|
+
wrapper = TimeUtil::TimeWrapper.new(step_time)
|
33
|
+
wrapper.add :day, offset
|
34
|
+
loop do
|
35
|
+
which_occ, num_occ = TimeUtil.which_occurrence_in_month(wrapper.to_time, day)
|
36
|
+
this_occ = (occ < 0) ? (num_occ + occ + 1) : (occ)
|
37
|
+
break offset if which_occ == this_occ
|
38
|
+
wrapper.add :day, 7
|
39
|
+
offset += 7
|
40
|
+
end
|
30
41
|
end
|
31
42
|
|
32
|
-
def
|
33
|
-
|
34
|
-
# Delete any with this day and no occ first
|
35
|
-
builder['BYDAY'].delete_if { |d| d == ical_day }
|
36
|
-
builder['BYDAY'] << "#{occ}#{ical_day}"
|
43
|
+
def build_s(builder)
|
44
|
+
builder.piece(:day_of_week) << "#{StringBuilder.nice_number(occ)} #{Date::DAYNAMES[day]}"
|
37
45
|
end
|
38
46
|
|
39
47
|
def build_hash(builder)
|
@@ -42,25 +50,15 @@ module IceCube
|
|
42
50
|
arr << occ
|
43
51
|
end
|
44
52
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
53
|
+
def build_ical(builder)
|
54
|
+
ical_day = IcalBuilder.fixnum_to_ical_day(day)
|
55
|
+
# Delete any with this day and no occ first
|
56
|
+
builder['BYDAY'].delete_if { |d| d == ical_day }
|
57
|
+
builder['BYDAY'] << "#{occ}#{ical_day}"
|
48
58
|
end
|
49
59
|
|
50
|
-
|
51
|
-
|
52
|
-
sum = day >= time.wday ? day - time.wday : 7 - time.wday + day
|
53
|
-
wrapper = TimeUtil::TimeWrapper.new(time)
|
54
|
-
wrapper.add :day, sum
|
55
|
-
# and then count the week until a viable occ
|
56
|
-
loop do
|
57
|
-
which_occ, num_occ = TimeUtil.which_occurrence_in_month(wrapper.to_time, day)
|
58
|
-
this_occ = occ < 0 ? num_occ + occ + 1 : occ
|
59
|
-
break if which_occ == this_occ
|
60
|
-
sum += 7
|
61
|
-
wrapper.add :day, 7 # one week
|
62
|
-
end
|
63
|
-
sum
|
60
|
+
StringBuilder.register_formatter(:day_of_week) do |segments|
|
61
|
+
'on the ' + segments.join(' and ')
|
64
62
|
end
|
65
63
|
|
66
64
|
end
|
@@ -17,12 +17,6 @@ module IceCube
|
|
17
17
|
|
18
18
|
attr_reader :day
|
19
19
|
|
20
|
-
StringBuilder.register_formatter(:day_of_year) do |entries|
|
21
|
-
str = "on the #{StringBuilder.sentence(entries)} "
|
22
|
-
str << (entries.size == 1 ? 'day of the year' : 'days of the year')
|
23
|
-
str
|
24
|
-
end
|
25
|
-
|
26
20
|
def initialize(day)
|
27
21
|
@day = day
|
28
22
|
end
|
@@ -31,6 +25,13 @@ module IceCube
|
|
31
25
|
:day
|
32
26
|
end
|
33
27
|
|
28
|
+
def validate(step_time, schedule)
|
29
|
+
days_in_year = TimeUtil.days_in_year(step_time)
|
30
|
+
yday = day < 0 ? day + days_in_year : day
|
31
|
+
offset = yday - step_time.yday
|
32
|
+
offset >= 0 ? offset : offset + days_in_year
|
33
|
+
end
|
34
|
+
|
34
35
|
def build_s(builder)
|
35
36
|
builder.piece(:day_of_year) << StringBuilder.nice_number(day)
|
36
37
|
end
|
@@ -43,12 +44,10 @@ module IceCube
|
|
43
44
|
builder['BYYEARDAY'] << day
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
diff = the_day - time.yday
|
51
|
-
diff >= 0 ? diff : diff + days_in_year
|
47
|
+
StringBuilder.register_formatter(:day_of_year) do |entries|
|
48
|
+
str = "on the #{StringBuilder.sentence(entries)} "
|
49
|
+
str << (entries.size == 1 ? 'day of the year' : 'days of the year')
|
50
|
+
str
|
52
51
|
end
|
53
52
|
|
54
53
|
end
|
@@ -2,8 +2,6 @@ module IceCube
|
|
2
2
|
|
3
3
|
module Validations::HourOfDay
|
4
4
|
|
5
|
-
include Validations::Lock
|
6
|
-
|
7
5
|
# Add hour of day validations
|
8
6
|
def hour_of_day(*hours)
|
9
7
|
hours.flatten.each do |hour|
|
@@ -20,11 +18,6 @@ module IceCube
|
|
20
18
|
|
21
19
|
include Validations::Lock
|
22
20
|
|
23
|
-
StringBuilder.register_formatter(:hour_of_day) do |segments|
|
24
|
-
str = "on the #{StringBuilder.sentence(segments)} "
|
25
|
-
str << (segments.size == 1 ? 'hour of the day' : 'hours of the day')
|
26
|
-
end
|
27
|
-
|
28
21
|
attr_reader :hour
|
29
22
|
alias :value :hour
|
30
23
|
|
@@ -32,14 +25,14 @@ module IceCube
|
|
32
25
|
@hour = hour
|
33
26
|
end
|
34
27
|
|
35
|
-
def build_s(builder)
|
36
|
-
builder.piece(:hour_of_day) << StringBuilder.nice_number(hour)
|
37
|
-
end
|
38
|
-
|
39
28
|
def type
|
40
29
|
:hour
|
41
30
|
end
|
42
31
|
|
32
|
+
def build_s(builder)
|
33
|
+
builder.piece(:hour_of_day) << StringBuilder.nice_number(hour)
|
34
|
+
end
|
35
|
+
|
43
36
|
def build_hash(builder)
|
44
37
|
builder.validations_array(:hour_of_day) << hour
|
45
38
|
end
|
@@ -48,6 +41,11 @@ module IceCube
|
|
48
41
|
builder['BYHOUR'] << hour
|
49
42
|
end
|
50
43
|
|
44
|
+
StringBuilder.register_formatter(:hour_of_day) do |segments|
|
45
|
+
str = "on the #{StringBuilder.sentence(segments)} "
|
46
|
+
str << (segments.size == 1 ? 'hour of the day' : 'hours of the day')
|
47
|
+
end
|
48
|
+
|
51
49
|
end
|
52
50
|
|
53
51
|
end
|
@@ -13,10 +13,27 @@ module IceCube
|
|
13
13
|
|
14
14
|
attr_reader :interval
|
15
15
|
|
16
|
+
def initialize(interval)
|
17
|
+
@interval = interval
|
18
|
+
end
|
19
|
+
|
16
20
|
def type
|
17
21
|
:hour
|
18
22
|
end
|
19
23
|
|
24
|
+
def dst_adjust?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate(step_time, schedule)
|
29
|
+
t0, t1 = schedule.start_time.to_i, step_time.to_i
|
30
|
+
sec = (t1 - t1 % ONE_HOUR) -
|
31
|
+
(t0 - t0 % ONE_HOUR)
|
32
|
+
hours = sec / ONE_HOUR
|
33
|
+
offset = (hours % interval).nonzero?
|
34
|
+
interval - offset if offset
|
35
|
+
end
|
36
|
+
|
20
37
|
def build_s(builder)
|
21
38
|
builder.base = interval == 1 ? 'Hourly' : "Every #{interval} hours"
|
22
39
|
end
|
@@ -27,27 +44,7 @@ module IceCube
|
|
27
44
|
|
28
45
|
def build_ical(builder)
|
29
46
|
builder['FREQ'] << 'HOURLY'
|
30
|
-
unless interval == 1
|
31
|
-
builder['INTERVAL'] << interval
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def initialize(interval)
|
36
|
-
@interval = interval
|
37
|
-
end
|
38
|
-
|
39
|
-
def dst_adjust?
|
40
|
-
false
|
41
|
-
end
|
42
|
-
|
43
|
-
def validate(time, schedule)
|
44
|
-
start_time = schedule.start_time
|
45
|
-
sec = (time.to_i - time.to_i % ONE_HOUR) -
|
46
|
-
(start_time.to_i - start_time.to_i % ONE_HOUR)
|
47
|
-
hours = sec / ONE_HOUR
|
48
|
-
unless hours % interval == 0
|
49
|
-
interval - (hours % interval)
|
50
|
-
end
|
47
|
+
builder['INTERVAL'] << interval unless interval == 1
|
51
48
|
end
|
52
49
|
|
53
50
|
end
|
@@ -1,34 +1,49 @@
|
|
1
1
|
module IceCube
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
|
3
|
+
# This validation mixin is used by the various "fixed-time" (e.g. day,
|
4
|
+
# day_of_month, hour_of_day) Validation and ScheduleLock::Validation modules.
|
5
|
+
# It is not a standalone rule validation like the others.
|
6
|
+
#
|
7
|
+
# Given the including Validation's defined +type+ field, it will lock
|
8
|
+
# to the specified +value+ or else the corresponding time unit from the
|
9
|
+
# schedule's start_time
|
10
|
+
#
|
6
11
|
module Validations::Lock
|
7
12
|
|
8
|
-
INTERVALS = {:min => 60, :sec => 60, :month => 12, :wday => 7}
|
13
|
+
INTERVALS = {:min => 60, :sec => 60, :hour => 24, :month => 12, :wday => 7}
|
9
14
|
|
10
15
|
def validate(time, schedule)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
case type
|
17
|
+
when :day then validate_day_lock(time, schedule)
|
18
|
+
when :hour then validate_hour_lock(time, schedule)
|
19
|
+
else validate_interval_lock(time, schedule)
|
20
|
+
end
|
15
21
|
end
|
16
22
|
|
17
23
|
private
|
18
24
|
|
25
|
+
# Validate if the current time unit matches the same unit from the schedule
|
26
|
+
# start time, returning the difference to the interval
|
27
|
+
#
|
28
|
+
def validate_interval_lock(time, schedule)
|
29
|
+
t0 = starting_unit(schedule.start_time)
|
30
|
+
t1 = time.send(type)
|
31
|
+
t0 >= t1 ? t0 - t1 : INTERVALS[type] - t1 + t0
|
32
|
+
end
|
33
|
+
|
19
34
|
# Lock the hour if explicitly set by hour_of_day, but allow for the nearest
|
20
35
|
# hour during DST start to keep the correct interval.
|
21
36
|
#
|
22
37
|
def validate_hour_lock(time, schedule)
|
23
|
-
|
24
|
-
|
25
|
-
if
|
26
|
-
|
38
|
+
h0 = starting_unit(schedule.start_time)
|
39
|
+
h1 = time.hour
|
40
|
+
if h0 >= h1
|
41
|
+
h0 - h1
|
27
42
|
else
|
28
43
|
if dst_offset = TimeUtil.dst_change(time)
|
29
|
-
|
44
|
+
h0 - h1 + dst_offset
|
30
45
|
else
|
31
|
-
24 -
|
46
|
+
24 - h1 + h0
|
32
47
|
end
|
33
48
|
end
|
34
49
|
end
|
@@ -69,6 +84,12 @@ module IceCube
|
|
69
84
|
sleeps >= 0 ? sleeps : until_next_month
|
70
85
|
end
|
71
86
|
|
87
|
+
def starting_unit(start_time)
|
88
|
+
start = value || start_time.send(type)
|
89
|
+
start += INTERVALS[type] while start < 0
|
90
|
+
start
|
91
|
+
end
|
92
|
+
|
72
93
|
end
|
73
94
|
|
74
95
|
end
|
@@ -2,8 +2,6 @@ module IceCube
|
|
2
2
|
|
3
3
|
module Validations::MinuteOfHour
|
4
4
|
|
5
|
-
include Validations::Lock
|
6
|
-
|
7
5
|
def minute_of_hour(*minutes)
|
8
6
|
minutes.flatten.each do |minute|
|
9
7
|
unless minute.is_a?(Fixnum)
|
@@ -19,11 +17,6 @@ module IceCube
|
|
19
17
|
|
20
18
|
include Validations::Lock
|
21
19
|
|
22
|
-
StringBuilder.register_formatter(:minute_of_hour) do |segments|
|
23
|
-
str = "on the #{StringBuilder.sentence(segments)} "
|
24
|
-
str << (segments.size == 1 ? 'minute of the hour' : 'minutes of the hour')
|
25
|
-
end
|
26
|
-
|
27
20
|
attr_reader :minute
|
28
21
|
alias :value :minute
|
29
22
|
|
@@ -31,14 +24,14 @@ module IceCube
|
|
31
24
|
@minute = minute
|
32
25
|
end
|
33
26
|
|
34
|
-
def build_s(builder)
|
35
|
-
builder.piece(:minute_of_hour) << StringBuilder.nice_number(minute)
|
36
|
-
end
|
37
|
-
|
38
27
|
def type
|
39
28
|
:min
|
40
29
|
end
|
41
30
|
|
31
|
+
def build_s(builder)
|
32
|
+
builder.piece(:minute_of_hour) << StringBuilder.nice_number(minute)
|
33
|
+
end
|
34
|
+
|
42
35
|
def build_hash(builder)
|
43
36
|
builder.validations_array(:minute_of_hour) << minute
|
44
37
|
end
|
@@ -47,6 +40,11 @@ module IceCube
|
|
47
40
|
builder['BYMINUTE'] << minute
|
48
41
|
end
|
49
42
|
|
43
|
+
StringBuilder.register_formatter(:minute_of_hour) do |segments|
|
44
|
+
str = "on the #{StringBuilder.sentence(segments)} "
|
45
|
+
str << (segments.size == 1 ? 'minute of the hour' : 'minutes of the hour')
|
46
|
+
end
|
47
|
+
|
50
48
|
end
|
51
49
|
|
52
50
|
end
|