ice_cube 0.6.14 → 0.7.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.
- data/lib/ice_cube.rb +63 -37
- data/lib/ice_cube/builders/hash_builder.rb +27 -0
- data/lib/ice_cube/builders/ical_builder.rb +59 -0
- data/lib/ice_cube/builders/string_builder.rb +74 -0
- data/lib/ice_cube/errors/count_exceeded.rb +7 -0
- data/lib/ice_cube/errors/until_exceeded.rb +7 -0
- data/lib/ice_cube/rule.rb +85 -147
- data/lib/ice_cube/rules/daily_rule.rb +5 -27
- data/lib/ice_cube/rules/hourly_rule.rb +6 -26
- data/lib/ice_cube/rules/minutely_rule.rb +5 -25
- data/lib/ice_cube/rules/monthly_rule.rb +6 -30
- data/lib/ice_cube/rules/secondly_rule.rb +5 -26
- data/lib/ice_cube/rules/weekly_rule.rb +5 -36
- data/lib/ice_cube/rules/yearly_rule.rb +8 -34
- data/lib/ice_cube/schedule.rb +257 -229
- data/lib/ice_cube/single_occurrence_rule.rb +28 -0
- data/lib/ice_cube/time_util.rb +202 -76
- data/lib/ice_cube/validated_rule.rb +107 -0
- data/lib/ice_cube/validations/count.rb +56 -0
- data/lib/ice_cube/validations/daily_interval.rb +51 -0
- data/lib/ice_cube/validations/day.rb +45 -31
- data/lib/ice_cube/validations/day_of_month.rb +44 -44
- data/lib/ice_cube/validations/day_of_week.rb +60 -47
- data/lib/ice_cube/validations/day_of_year.rb +48 -44
- data/lib/ice_cube/validations/hour_of_day.rb +42 -30
- data/lib/ice_cube/validations/hourly_interval.rb +50 -0
- data/lib/ice_cube/validations/lock.rb +47 -0
- data/lib/ice_cube/validations/minute_of_hour.rb +42 -31
- data/lib/ice_cube/validations/minutely_interval.rb +50 -0
- data/lib/ice_cube/validations/month_of_year.rb +39 -30
- data/lib/ice_cube/validations/monthly_interval.rb +47 -0
- data/lib/ice_cube/validations/schedule_lock.rb +41 -0
- data/lib/ice_cube/validations/second_of_minute.rb +39 -30
- data/lib/ice_cube/validations/secondly_interval.rb +50 -0
- data/lib/ice_cube/validations/until.rb +49 -0
- data/lib/ice_cube/validations/weekly_interval.rb +50 -0
- data/lib/ice_cube/validations/yearly_interval.rb +45 -0
- data/lib/ice_cube/version.rb +2 -2
- data/spec/spec_helper.rb +13 -0
- metadata +50 -9
- data/lib/ice_cube/rule_occurrence.rb +0 -94
- data/lib/ice_cube/validation.rb +0 -44
- data/lib/ice_cube/validation_types.rb +0 -137
data/lib/ice_cube.rb
CHANGED
@@ -1,48 +1,74 @@
|
|
1
|
-
require 'yaml.rb'
|
2
|
-
require 'set.rb'
|
3
1
|
require 'date'
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
require '
|
8
|
-
|
9
|
-
require '
|
10
|
-
|
11
|
-
require 'ice_cube/rule_occurrence'
|
3
|
+
# Use psych if we can
|
4
|
+
begin
|
5
|
+
require 'psych'
|
6
|
+
rescue LoadError
|
7
|
+
require 'yaml'
|
8
|
+
end
|
12
9
|
|
13
10
|
module IceCube
|
14
|
-
|
11
|
+
|
12
|
+
autoload :VERSION, 'ice_cube/version'
|
13
|
+
|
14
|
+
autoload :TimeUtil, 'ice_cube/time_util'
|
15
|
+
|
16
|
+
autoload :Rule, 'ice_cube/rule'
|
17
|
+
autoload :Schedule, 'ice_cube/schedule'
|
18
|
+
|
19
|
+
autoload :IcalBuilder, 'ice_cube/builders/ical_builder'
|
20
|
+
autoload :HashBuilder, 'ice_cube/builders/hash_builder'
|
21
|
+
autoload :StringBuilder, 'ice_cube/builders/string_builder'
|
22
|
+
|
23
|
+
autoload :CountExceeded, 'ice_cube/errors/count_exceeded'
|
24
|
+
autoload :UntilExceeded, 'ice_cube/errors/until_exceeded'
|
25
|
+
|
26
|
+
autoload :ValidatedRule, 'ice_cube/validated_rule'
|
27
|
+
autoload :SingleOccurrenceRule, 'ice_cube/single_occurrence_rule'
|
28
|
+
|
29
|
+
autoload :SecondlyRule, 'ice_cube/rules/secondly_rule'
|
30
|
+
autoload :MinutelyRule, 'ice_cube/rules/minutely_rule'
|
31
|
+
autoload :HourlyRule, 'ice_cube/rules/hourly_rule'
|
15
32
|
autoload :DailyRule, 'ice_cube/rules/daily_rule'
|
16
33
|
autoload :WeeklyRule, 'ice_cube/rules/weekly_rule'
|
17
34
|
autoload :MonthlyRule, 'ice_cube/rules/monthly_rule'
|
18
35
|
autoload :YearlyRule, 'ice_cube/rules/yearly_rule'
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
36
|
+
|
37
|
+
module Validations
|
38
|
+
|
39
|
+
autoload :Lock, 'ice_cube/validations/lock'
|
40
|
+
autoload :ScheduleLock, 'ice_cube/validations/schedule_lock'
|
41
|
+
|
42
|
+
autoload :Count, 'ice_cube/validations/count'
|
43
|
+
autoload :Until, 'ice_cube/validations/until'
|
44
|
+
|
45
|
+
autoload :SecondlyInterval, 'ice_cube/validations/secondly_interval'
|
46
|
+
autoload :MinutelyInterval, 'ice_cube/validations/minutely_interval'
|
47
|
+
autoload :DailyInterval, 'ice_cube/validations/daily_interval'
|
48
|
+
autoload :WeeklyInterval, 'ice_cube/validations/weekly_interval'
|
49
|
+
autoload :MonthlyInterval, 'ice_cube/validations/monthly_interval'
|
50
|
+
autoload :YearlyInterval, 'ice_cube/validations/yearly_interval'
|
51
|
+
autoload :HourlyInterval, 'ice_cube/validations/hourly_interval'
|
52
|
+
|
53
|
+
autoload :HourOfDay, 'ice_cube/validations/hour_of_day'
|
54
|
+
autoload :MonthOfYear, 'ice_cube/validations/month_of_year'
|
55
|
+
autoload :MinuteOfHour, 'ice_cube/validations/minute_of_hour'
|
56
|
+
autoload :SecondOfMinute, 'ice_cube/validations/second_of_minute'
|
57
|
+
autoload :DayOfMonth, 'ice_cube/validations/day_of_month'
|
58
|
+
autoload :DayOfWeek, 'ice_cube/validations/day_of_week'
|
59
|
+
autoload :Day, 'ice_cube/validations/day'
|
60
|
+
autoload :DayOfYear, 'ice_cube/validations/day_of_year'
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# Define some useful constants
|
65
|
+
ONE_SECOND = 1
|
66
|
+
ONE_MINUTE = ONE_SECOND * 60
|
67
|
+
ONE_HOUR = ONE_MINUTE * 60
|
68
|
+
ONE_DAY = ONE_HOUR * 24
|
69
|
+
ONE_WEEK = ONE_DAY * 7
|
23
70
|
|
24
|
-
|
25
|
-
|
26
|
-
autoload :DayOfWeekValidation, 'ice_cube/validations/day_of_week'
|
27
|
-
autoload :DayOfYearValidation, 'ice_cube/validations/day_of_year'
|
28
|
-
autoload :HourOfDayValidation, 'ice_cube/validations/hour_of_day'
|
29
|
-
autoload :MinuteOfHourValidation, 'ice_cube/validations/minute_of_hour'
|
30
|
-
autoload :MonthOfYearValidation, 'ice_cube/validations/month_of_year'
|
31
|
-
autoload :SecondOfMinuteValidation, 'ice_cube/validations/second_of_minute'
|
32
|
-
|
33
|
-
# if you're reading this code, you've just been iced
|
34
|
-
# http://brosicingbros.com/
|
35
|
-
|
36
|
-
IceCube::ONE_DAY = 24 * 60 * 60
|
37
|
-
IceCube::ONE_HOUR = 60 * 60
|
38
|
-
IceCube::ONE_MINUTE = 60
|
39
|
-
IceCube::ONE_SECOND = 1
|
40
|
-
|
41
|
-
ICAL_DAYS = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']
|
42
|
-
DAYS = { :sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3, :thursday => 4, :friday => 5, :saturday => 6 }
|
43
|
-
MONTHS = { :january => 1, :february => 2, :march => 3, :april => 4, :may => 5, :june => 6, :july => 7, :august => 8,
|
44
|
-
:september => 9, :october => 10, :november => 11, :december => 12 }
|
45
|
-
|
46
|
-
include TimeUtil
|
71
|
+
# Formatting
|
72
|
+
TO_S_TIME_FORMAT = '%B %e, %Y'
|
47
73
|
|
48
74
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module IceCube
|
2
|
+
|
3
|
+
class HashBuilder
|
4
|
+
|
5
|
+
def initialize(rule = nil)
|
6
|
+
@hash = { :validations => {}, :rule_type => rule.class.name }
|
7
|
+
end
|
8
|
+
|
9
|
+
def validations
|
10
|
+
@hash[:validations]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
@hash[key] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def validations_array(type)
|
18
|
+
validations[type] ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_hash
|
22
|
+
@hash
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module IceCube
|
2
|
+
|
3
|
+
class IcalBuilder
|
4
|
+
|
5
|
+
ICAL_DAYS = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@hash = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.fixnum_to_ical_day(num)
|
12
|
+
ICAL_DAYS[num]
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
@hash[key] ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
# Build for a single rule entry
|
20
|
+
def to_s
|
21
|
+
arr = []
|
22
|
+
if freq = @hash.delete('FREQ')
|
23
|
+
arr << "FREQ=#{freq.join(',')}"
|
24
|
+
end
|
25
|
+
arr.concat(@hash.map do |key, value|
|
26
|
+
if value.is_a?(Array)
|
27
|
+
"#{key}=#{value.join(',')}"
|
28
|
+
end
|
29
|
+
end.compact)
|
30
|
+
arr.join(';')
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.ical_utc_format(time)
|
34
|
+
time = time.dup.utc
|
35
|
+
"#{time.strftime('%Y%m%dT%H%M%SZ')}" # utc time
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.ical_format(time, force_utc)
|
39
|
+
time = time.dup.utc if force_utc
|
40
|
+
if time.utc?
|
41
|
+
":#{time.strftime('%Y%m%dT%H%M%SZ')}" # utc time
|
42
|
+
else
|
43
|
+
";TZID=#{time.strftime('%Z:%Y%m%dT%H%M%S')}" # local time specified
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.ical_duration(duration)
|
48
|
+
hours = duration / 3600; duration %= 3600
|
49
|
+
minutes = duration / 60; duration %= 60
|
50
|
+
repr = ''
|
51
|
+
repr << "#{hours}H" if hours > 0
|
52
|
+
repr << "#{minutes}M" if minutes > 0
|
53
|
+
repr << "#{duration}S" if duration > 0
|
54
|
+
"PT#{repr}"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module IceCube
|
2
|
+
|
3
|
+
class StringBuilder
|
4
|
+
|
5
|
+
attr_writer :base
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@types = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def piece(type, prefix = nil, suffix = nil)
|
12
|
+
@types[type] ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
str = @base || ''
|
17
|
+
res = @types.map do |type, segments|
|
18
|
+
if f = self.class.formatter(type)
|
19
|
+
str << ' ' + f.call(segments)
|
20
|
+
else
|
21
|
+
next if segments.empty?
|
22
|
+
str << ' ' + self.class.sentence(segments)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
str
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
|
30
|
+
def formatter(type)
|
31
|
+
@formatters[type]
|
32
|
+
end
|
33
|
+
|
34
|
+
def register_formatter(type, &formatter)
|
35
|
+
@formatters ||= {}
|
36
|
+
@formatters[type] = formatter
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
|
43
|
+
NUMBER_SUFFIX = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th']
|
44
|
+
SPECIAL_SUFFIX = { 11 => 'th', 12 => 'th', 13 => 'th', 14 => 'th' }
|
45
|
+
|
46
|
+
# influenced by ActiveSupport's to_sentence
|
47
|
+
def sentence(array)
|
48
|
+
case array.length
|
49
|
+
when 0 ; ''
|
50
|
+
when 1 ; array[0].to_s
|
51
|
+
when 2 ; "#{array[0]} and #{array[1]}"
|
52
|
+
else ; "#{array[0...-1].join(', ')}, and #{array[-1]}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def nice_number(number)
|
57
|
+
if number == -1
|
58
|
+
'last'
|
59
|
+
elsif number < -1
|
60
|
+
suffix = SPECIAL_SUFFIX.include?(number) ?
|
61
|
+
SPECIAL_SUFFIX[number] : NUMBER_SUFFIX[number.abs % 10]
|
62
|
+
number.abs.to_s << suffix << ' to last'
|
63
|
+
else
|
64
|
+
suffix = SPECIAL_SUFFIX.include?(number) ?
|
65
|
+
SPECIAL_SUFFIX[number] : NUMBER_SUFFIX[number.abs % 10]
|
66
|
+
number.to_s << suffix
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
data/lib/ice_cube/rule.rb
CHANGED
@@ -1,171 +1,109 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
module IceCube
|
2
|
-
|
4
|
+
|
3
5
|
class Rule
|
4
|
-
|
5
|
-
attr_reader :occurrence_count, :until_date
|
6
|
-
attr_reader :interval
|
7
|
-
attr_reader :validations
|
8
|
-
|
9
|
-
include ValidationTypes
|
10
|
-
include Comparable
|
11
6
|
|
12
|
-
|
13
|
-
def <=>(other)
|
14
|
-
to_hash <=> other.to_hash
|
15
|
-
end
|
7
|
+
attr_reader :uses
|
16
8
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
hash[:interval] = @interval
|
21
|
-
hash[:until] = @until_date ? TimeUtil.serialize_time(@until_date) : @until_date
|
22
|
-
hash[:count] = @occurrence_count
|
23
|
-
hash[:validations] = @validations
|
24
|
-
hash
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.from_hash(hash)
|
28
|
-
rule = hash[:rule_type].split('::').inject(Object) { |namespace, const_name| namespace.const_get(const_name) }.new(hash[:interval])
|
29
|
-
rule.count(hash[:count]) if hash[:count]
|
30
|
-
rule.until(hash[:until]) if hash[:until]
|
31
|
-
hash[:validations].each do |validation, data|
|
32
|
-
data.is_a?(Array) ? rule.send(validation, *data) : rule.send(validation, data)
|
33
|
-
end
|
34
|
-
rule
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_yaml(options = {})
|
38
|
-
to_hash.to_yaml(options)
|
9
|
+
# Is this a terminating schedule?
|
10
|
+
def terminating?
|
11
|
+
until_time || occurrence_count
|
39
12
|
end
|
40
13
|
|
41
|
-
def
|
42
|
-
|
14
|
+
def ==(rule)
|
15
|
+
hash = to_hash
|
16
|
+
hash && hash == rule.to_hash
|
43
17
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
18
|
+
|
19
|
+
def hash
|
20
|
+
h = to_hash
|
21
|
+
h.nil? ? super : h.hash
|
48
22
|
end
|
49
23
|
|
50
|
-
#
|
51
|
-
def
|
52
|
-
|
24
|
+
# Expected to be overridden by subclasses
|
25
|
+
def to_ical
|
26
|
+
nil
|
53
27
|
end
|
54
28
|
|
55
|
-
#
|
56
|
-
def
|
57
|
-
|
29
|
+
# Yaml implementation
|
30
|
+
def to_yaml(*args)
|
31
|
+
defined?(Psych) ? Psych::dump(to_hash) : YAML::dump(to_hash, *args)
|
58
32
|
end
|
59
33
|
|
60
|
-
#
|
61
|
-
def self.
|
62
|
-
|
34
|
+
# From yaml
|
35
|
+
def self.from_yaml(yaml)
|
36
|
+
from_hash defined?(Psych) ? Psych::load(yaml) : YAML::load(yaml)
|
63
37
|
end
|
64
|
-
|
65
|
-
#
|
66
|
-
def
|
67
|
-
|
38
|
+
|
39
|
+
# Expected to be overridden by subclasses
|
40
|
+
def to_hash
|
41
|
+
nil
|
68
42
|
end
|
69
|
-
|
70
|
-
#
|
71
|
-
def self.
|
72
|
-
|
43
|
+
|
44
|
+
# Convert from a hash and create a rule
|
45
|
+
def self.from_hash(hash)
|
46
|
+
return nil unless match = hash[:rule_type].match(/\:\:(.+?)Rule/)
|
47
|
+
rule = IceCube::Rule.send(match[1].downcase.to_sym, hash[:interval] || 1)
|
48
|
+
rule.until(TimeUtil.deserialize_time(hash[:until])) if hash[:until]
|
49
|
+
rule.count(hash[:count]) if hash[:count]
|
50
|
+
hash[:validations] && hash[:validations].each do |key, value|
|
51
|
+
key = key.to_sym unless key.is_a?(Symbol)
|
52
|
+
value.is_a?(Array) ? rule.send(key, *value) : rule.send(key, value)
|
53
|
+
end
|
54
|
+
rule
|
73
55
|
end
|
74
|
-
|
75
|
-
#
|
76
|
-
def
|
77
|
-
|
56
|
+
|
57
|
+
# Reset the uses on the rule to 0
|
58
|
+
def reset
|
59
|
+
@uses = 0
|
78
60
|
end
|
79
|
-
|
80
|
-
|
81
|
-
def until(until_date)
|
82
|
-
raise ArgumentError.new('Cannot specify until and count on the same rule') if @count #as per rfc
|
83
|
-
@until_date = until_date
|
84
|
-
self
|
61
|
+
|
62
|
+
def next_time(time, schedule, closing_time)
|
85
63
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
raise ArgumentError.new('Argument must be a positive integer') unless Integer(count) && count >= 0
|
90
|
-
@occurrence_count = count
|
91
|
-
self
|
64
|
+
|
65
|
+
def on?(time, schedule)
|
66
|
+
next_time(time, schedule, time) == time
|
92
67
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
68
|
+
|
69
|
+
# Convenience methods for creating Rules
|
70
|
+
class << self
|
71
|
+
|
72
|
+
# Secondly Rule
|
73
|
+
def secondly(interval = 1)
|
74
|
+
SecondlyRule.new(interval)
|
98
75
|
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
# by constantly moving the farthest back value forward
|
104
|
-
def next_suggestion(date)
|
105
|
-
# get the next date recommendation set
|
106
|
-
suggestions = {};
|
107
|
-
@validation_types.each { |k, validation| suggestions[k] = validation.send(:closest, date) }
|
108
|
-
compact_suggestions = suggestions.values.compact
|
109
|
-
# find the next date to go to
|
110
|
-
if compact_suggestions.empty?
|
111
|
-
attempt_count = 0
|
112
|
-
loop do
|
113
|
-
# keep going through rule suggestions
|
114
|
-
next_date = self.default_jump(date, attempt_count += 1)
|
115
|
-
return next_date if !next_date.nil? && validate_single_date(next_date)
|
116
|
-
end
|
117
|
-
else
|
118
|
-
loop do
|
119
|
-
compact_suggestions = suggestions.values.compact
|
120
|
-
min_suggestion = compact_suggestions.min
|
121
|
-
# validate all against the minimum
|
122
|
-
return min_suggestion if validate_single_date(min_suggestion)
|
123
|
-
# move anything that is the minimum to its next closest
|
124
|
-
@validation_types.each do |k, validation|
|
125
|
-
suggestions[k] = validation.send(:closest, min_suggestion) if min_suggestion == suggestions[k]
|
126
|
-
end
|
127
|
-
end
|
76
|
+
|
77
|
+
# Minutely Rule
|
78
|
+
def minutely(interval = 1)
|
79
|
+
MinutelyRule.new(interval)
|
128
80
|
end
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
representation << ';' << v.send(:to_ical)
|
156
|
-
end
|
157
|
-
representation << ";COUNT=#{@occurrence_count}" if @occurrence_count
|
158
|
-
representation << ";UNTIL=#{TimeUtil.ical_utc_format(@until_date)}" if @until_date
|
159
|
-
representation
|
160
|
-
end
|
161
|
-
|
162
|
-
# Set the interval for the rule. Depending on the type of rule,
|
163
|
-
# interval means every (n) weeks, months, etc. starting on the start_date's
|
164
|
-
def initialize(interval = 1)
|
165
|
-
throw ArgumentError.new('Interval must be > 0') unless interval > 0
|
166
|
-
@validations = {}
|
167
|
-
@validation_types = {}
|
168
|
-
@interval = interval
|
81
|
+
|
82
|
+
# Hourly Rule
|
83
|
+
def hourly(interval = 1)
|
84
|
+
HourlyRule.new(interval)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Daily Rule
|
88
|
+
def daily(interval = 1)
|
89
|
+
DailyRule.new(interval)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Weekly Rule
|
93
|
+
def weekly(interval = 1)
|
94
|
+
WeeklyRule.new(interval)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Monthly Rule
|
98
|
+
def monthly(interval = 1)
|
99
|
+
MonthlyRule.new(interval)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Yearly Rule
|
103
|
+
def yearly(interval = 1)
|
104
|
+
YearlyRule.new(interval)
|
105
|
+
end
|
106
|
+
|
169
107
|
end
|
170
108
|
|
171
109
|
end
|