ice_cube 0.16.0 → 0.16.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/config/locales/de.yml +1 -1
- data/config/locales/en.yml +7 -46
- data/config/locales/es.yml +47 -83
- data/config/locales/fr.yml +2 -2
- data/config/locales/it.yml +179 -0
- data/config/locales/ja.yml +52 -29
- data/config/locales/nl.yml +133 -0
- data/config/locales/pt-BR.yml +178 -0
- data/config/locales/sv.yml +1 -1
- data/lib/ice_cube/i18n.rb +11 -12
- data/lib/ice_cube/input_alignment.rb +89 -0
- data/lib/ice_cube/null_i18n.rb +12 -6
- data/lib/ice_cube/occurrence.rb +25 -23
- data/lib/ice_cube/parsers/ical_parser.rb +8 -5
- data/lib/ice_cube/rule.rb +5 -13
- data/lib/ice_cube/rules/daily_rule.rb +9 -0
- data/lib/ice_cube/rules/hourly_rule.rb +9 -0
- data/lib/ice_cube/rules/minutely_rule.rb +9 -0
- data/lib/ice_cube/rules/monthly_rule.rb +9 -0
- data/lib/ice_cube/rules/secondly_rule.rb +9 -0
- data/lib/ice_cube/rules/weekly_rule.rb +30 -9
- data/lib/ice_cube/rules/yearly_rule.rb +9 -0
- data/lib/ice_cube/schedule.rb +30 -29
- data/lib/ice_cube/single_occurrence_rule.rb +4 -0
- data/lib/ice_cube/time_util.rb +65 -46
- data/lib/ice_cube/validated_rule.rb +18 -24
- data/lib/ice_cube/validations/count.rb +1 -2
- data/lib/ice_cube/validations/daily_interval.rb +5 -1
- data/lib/ice_cube/validations/day.rb +6 -2
- data/lib/ice_cube/validations/day_of_month.rb +5 -0
- data/lib/ice_cube/validations/day_of_week.rb +1 -1
- data/lib/ice_cube/validations/hour_of_day.rb +23 -0
- data/lib/ice_cube/validations/hourly_interval.rb +2 -0
- data/lib/ice_cube/validations/minute_of_hour.rb +16 -0
- data/lib/ice_cube/validations/minutely_interval.rb +2 -0
- data/lib/ice_cube/validations/month_of_year.rb +6 -1
- data/lib/ice_cube/validations/monthly_interval.rb +4 -1
- data/lib/ice_cube/validations/schedule_lock.rb +4 -0
- data/lib/ice_cube/validations/second_of_minute.rb +19 -3
- data/lib/ice_cube/validations/secondly_interval.rb +2 -0
- data/lib/ice_cube/validations/until.rb +1 -2
- data/lib/ice_cube/validations/weekly_interval.rb +0 -2
- data/lib/ice_cube/version.rb +1 -1
- data/lib/ice_cube.rb +1 -3
- data/spec/spec_helper.rb +32 -9
- metadata +10 -7
@@ -0,0 +1,178 @@
|
|
1
|
+
pt-BR:
|
2
|
+
ice_cube:
|
3
|
+
pieces_connector: ' / '
|
4
|
+
not: 'exceto %{target}'
|
5
|
+
not_on: 'exceto o dia %{target}'
|
6
|
+
date:
|
7
|
+
formats:
|
8
|
+
default: '%-d %B %Y'
|
9
|
+
month_names:
|
10
|
+
-
|
11
|
+
- Janeiro
|
12
|
+
- Fevereiro
|
13
|
+
- Março
|
14
|
+
- Abril
|
15
|
+
- Maio
|
16
|
+
- Junho
|
17
|
+
- Julho
|
18
|
+
- Agosto
|
19
|
+
- Setembro
|
20
|
+
- Outubro
|
21
|
+
- Novembro
|
22
|
+
- Dezembro
|
23
|
+
day_names:
|
24
|
+
- Domingo
|
25
|
+
- Segunda
|
26
|
+
- Terça
|
27
|
+
- Quarta
|
28
|
+
- Quinta
|
29
|
+
- Sexta
|
30
|
+
- Sábado
|
31
|
+
times:
|
32
|
+
other: '%{count} vezes'
|
33
|
+
one: '%{count} vez'
|
34
|
+
until: 'até %{date}'
|
35
|
+
days_of_week: '%{segments} %{day}'
|
36
|
+
days_of_month:
|
37
|
+
other: '%{segments} dias do mês'
|
38
|
+
one: '%{segments} dia'
|
39
|
+
days_of_year:
|
40
|
+
other: '%{segments} dias do ano'
|
41
|
+
one: '%{segments} dia'
|
42
|
+
at_hours_of_the_day:
|
43
|
+
other: às %{segments} horas
|
44
|
+
one: à %{segments} hora
|
45
|
+
on_minutes_of_hour:
|
46
|
+
other: aos %{segments} minutos
|
47
|
+
one: ao %{segments} minuto
|
48
|
+
at_seconds_of_minute:
|
49
|
+
other: aos %{segments} segundos
|
50
|
+
one: ao %{segments} segundo
|
51
|
+
on_seconds_of_minute:
|
52
|
+
other: aos %{segments} segundos
|
53
|
+
one: ao %{segments} segundo
|
54
|
+
each_second:
|
55
|
+
one: A cada segundo
|
56
|
+
other: A cada %{count} segundos
|
57
|
+
each_minute:
|
58
|
+
one: A cada minuto
|
59
|
+
other: A cada %{count} minutos
|
60
|
+
each_hour:
|
61
|
+
one: A cada hora
|
62
|
+
other: A cada %{count} horas
|
63
|
+
each_day:
|
64
|
+
one: Diariamente
|
65
|
+
other: A cada %{count} dias
|
66
|
+
each_week:
|
67
|
+
one: Semanalmente
|
68
|
+
other: A cada %{count} semanas
|
69
|
+
each_month:
|
70
|
+
one: Mensalmente
|
71
|
+
other: A cada %{count} meses
|
72
|
+
each_year:
|
73
|
+
one: Anualmente
|
74
|
+
other: A cada %{count} anos
|
75
|
+
'on': no %{sentence}
|
76
|
+
in: 'em %{target}'
|
77
|
+
integer:
|
78
|
+
negative: '%{ordinal} depois que acabar'
|
79
|
+
literal_ordinals:
|
80
|
+
-1: último
|
81
|
+
-2: penúltimo
|
82
|
+
ordinal: '%{number}%{ordinal}'
|
83
|
+
ordinals:
|
84
|
+
default: º
|
85
|
+
1: º
|
86
|
+
2: º
|
87
|
+
3: º
|
88
|
+
11: º
|
89
|
+
12: º
|
90
|
+
13: º
|
91
|
+
on_weekends: nos finais de semana
|
92
|
+
on_weekdays: nos dias úteis
|
93
|
+
days_on:
|
94
|
+
- Domingos
|
95
|
+
- Segundas-feiras
|
96
|
+
- Terças-feiras
|
97
|
+
- Quartas-feiras
|
98
|
+
- Quintas-feiras
|
99
|
+
- Sextas-feiras
|
100
|
+
- Sábados
|
101
|
+
on_days: no dia %{days}
|
102
|
+
array:
|
103
|
+
last_word_connector: ' e '
|
104
|
+
two_words_connector: ' e '
|
105
|
+
words_connector: ', '
|
106
|
+
string:
|
107
|
+
format:
|
108
|
+
day: '%{rest} %{current}'
|
109
|
+
day_of_week: '%{rest} %{current}'
|
110
|
+
day_of_month: '%{rest} %{current}'
|
111
|
+
day_of_year: '%{rest} %{current}'
|
112
|
+
hour_of_day: '%{rest} %{current}'
|
113
|
+
minute_of_hour: '%{rest} %{current}'
|
114
|
+
until: '%{rest} %{current}'
|
115
|
+
count: '%{rest} %{current}'
|
116
|
+
default: '%{rest} %{current}'
|
117
|
+
|
118
|
+
date:
|
119
|
+
abbr_day_names:
|
120
|
+
- Dom
|
121
|
+
- Seg
|
122
|
+
- Ter
|
123
|
+
- Qua
|
124
|
+
- Qui
|
125
|
+
- Sex
|
126
|
+
- Sáb
|
127
|
+
abbr_month_names:
|
128
|
+
-
|
129
|
+
- Jan
|
130
|
+
- Fev
|
131
|
+
- Mar
|
132
|
+
- Abr
|
133
|
+
- Mai
|
134
|
+
- Jun
|
135
|
+
- Jul
|
136
|
+
- Ago
|
137
|
+
- Set
|
138
|
+
- Out
|
139
|
+
- Nov
|
140
|
+
- Dez
|
141
|
+
day_names:
|
142
|
+
- Domingo
|
143
|
+
- Segunda-feira
|
144
|
+
- Terça-feira
|
145
|
+
- Quarta-feira
|
146
|
+
- Quinta-feira
|
147
|
+
- Sexta-feira
|
148
|
+
- Sábado
|
149
|
+
formats:
|
150
|
+
default: "%d/%m/%Y"
|
151
|
+
long: "%d de %B de %Y"
|
152
|
+
short: "%d de %B"
|
153
|
+
month_names:
|
154
|
+
-
|
155
|
+
- Janeiro
|
156
|
+
- Fevereiro
|
157
|
+
- Março
|
158
|
+
- Abril
|
159
|
+
- Maio
|
160
|
+
- Junho
|
161
|
+
- Julho
|
162
|
+
- Agosto
|
163
|
+
- Setembro
|
164
|
+
- Outubro
|
165
|
+
- Novembro
|
166
|
+
- Dezembro
|
167
|
+
order:
|
168
|
+
- :day
|
169
|
+
- :month
|
170
|
+
- :year
|
171
|
+
|
172
|
+
time:
|
173
|
+
am: ''
|
174
|
+
formats:
|
175
|
+
default: "%a, %d de %B de %Y, %H:%M:%S %z"
|
176
|
+
long: "%d de %B de %Y, %H:%M"
|
177
|
+
short: "%d de %B, %H:%M"
|
178
|
+
pm: ''
|
data/config/locales/sv.yml
CHANGED
data/lib/ice_cube/i18n.rb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
|
+
require 'ice_cube/null_i18n'
|
2
|
+
|
1
3
|
module IceCube
|
2
4
|
module I18n
|
3
|
-
def self.t(*args)
|
4
|
-
backend.t(*args)
|
5
|
-
end
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
LOCALES_PATH = File.expand_path(File.join('..', '..', '..', 'config', 'locales'), __FILE__)
|
7
|
+
|
8
|
+
class << self
|
9
|
+
delegate :t, :l, to: :backend
|
9
10
|
end
|
10
11
|
|
11
12
|
def self.backend
|
12
|
-
@backend
|
13
|
+
@backend ||= detect_backend!
|
13
14
|
end
|
14
15
|
|
15
16
|
def self.detect_backend!
|
16
|
-
|
17
|
-
::I18n
|
18
|
-
|
19
|
-
|
20
|
-
require 'ice_cube/null_i18n'
|
21
|
-
@backend = NullI18n
|
17
|
+
::I18n.load_path += Dir[File.join(LOCALES_PATH, '*.yml')]
|
18
|
+
::I18n
|
19
|
+
rescue NameError
|
20
|
+
NullI18n
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module IceCube
|
2
|
+
class InputAlignment
|
3
|
+
|
4
|
+
def initialize(rule, value, rule_part)
|
5
|
+
@rule = rule
|
6
|
+
@value = value
|
7
|
+
@rule_part = rule_part
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :rule, :value, :rule_part
|
11
|
+
|
12
|
+
def verify(freq, options={}, &block)
|
13
|
+
@rule.validations[:interval] or return
|
14
|
+
|
15
|
+
case @rule
|
16
|
+
when DailyRule
|
17
|
+
verify_wday_alignment(freq, &block)
|
18
|
+
when MonthlyRule
|
19
|
+
verify_month_alignment(freq, &block)
|
20
|
+
else
|
21
|
+
verify_freq_alignment(freq, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def interval_validation
|
28
|
+
@interval_validation ||= @rule.validations[:interval].first
|
29
|
+
end
|
30
|
+
|
31
|
+
def interval_value
|
32
|
+
@interval_value ||= (rule_part == :interval) ? value : interval_validation.interval
|
33
|
+
end
|
34
|
+
|
35
|
+
def fixed_validations
|
36
|
+
@fixed_validations ||= @rule.validations.values.flatten.select { |v|
|
37
|
+
interval_type = (v.type == :wday ? :day : v.type)
|
38
|
+
v.class < Validations::FixedValue &&
|
39
|
+
interval_type == rule.base_interval_validation.type
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def verify_freq_alignment(freq)
|
44
|
+
interval_validation.type == freq or return
|
45
|
+
(last_validation = fixed_validations.min_by(&:value)) or return
|
46
|
+
|
47
|
+
alignment = (value - last_validation.value) % interval_validation.interval
|
48
|
+
return if alignment.zero?
|
49
|
+
|
50
|
+
validation_values = fixed_validations.map(&:value).join(', ')
|
51
|
+
if rule_part == :interval
|
52
|
+
message = "interval(#{value}) " \
|
53
|
+
"must be a multiple of " \
|
54
|
+
"intervals in #{last_validation.key}(#{validation_values})"
|
55
|
+
else
|
56
|
+
message = "intervals in #{last_validation.key}(#{validation_values}, #{value}) " \
|
57
|
+
"must be multiples of " \
|
58
|
+
"interval(#{interval_validation.interval})"
|
59
|
+
end
|
60
|
+
|
61
|
+
yield ArgumentError.new(message)
|
62
|
+
end
|
63
|
+
|
64
|
+
def verify_month_alignment(_freq)
|
65
|
+
return if interval_value == 1 || (interval_value % 12).zero?
|
66
|
+
return if fixed_validations.empty?
|
67
|
+
|
68
|
+
message = "month_of_year can only be used with interval(1) or multiples of interval(12)"
|
69
|
+
|
70
|
+
yield ArgumentError.new(message)
|
71
|
+
end
|
72
|
+
|
73
|
+
def verify_wday_alignment(freq)
|
74
|
+
return if interval_value == 1
|
75
|
+
|
76
|
+
if freq == :wday
|
77
|
+
return if (interval_value % 7).zero?
|
78
|
+
return if Array(@rule.validations[:day]).empty?
|
79
|
+
message = "day can only be used with multiples of interval(7)"
|
80
|
+
else
|
81
|
+
(fixed_validation = fixed_validations.first) or return
|
82
|
+
message = "#{fixed_validation.key} can only be used with interval(1)"
|
83
|
+
end
|
84
|
+
|
85
|
+
yield ArgumentError.new(message)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
data/lib/ice_cube/null_i18n.rb
CHANGED
@@ -7,13 +7,19 @@ module IceCube
|
|
7
7
|
|
8
8
|
base = base[options[:count] == 1 ? "one" : "other"] if options[:count]
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
case base
|
11
|
+
when Hash
|
12
|
+
base.each_with_object({}) do |(k, v), hash|
|
13
|
+
hash[k.is_a?(String) ? k.to_sym : k] = v
|
13
14
|
end
|
15
|
+
when Array
|
16
|
+
base.each_with_index.each_with_object({}) do |(v, k), hash|
|
17
|
+
hash[k] = v
|
18
|
+
end
|
19
|
+
else
|
20
|
+
return base unless base.include?('%{')
|
21
|
+
base % options
|
14
22
|
end
|
15
|
-
|
16
|
-
options.reduce(base) { |result, (find, replace)| result.gsub("%{#{find}}", "#{replace}") }
|
17
23
|
end
|
18
24
|
|
19
25
|
def self.l(date_or_time, options = {})
|
@@ -22,7 +28,7 @@ module IceCube
|
|
22
28
|
end
|
23
29
|
|
24
30
|
def self.config
|
25
|
-
@config ||= YAML.
|
31
|
+
@config ||= YAML.load_file(File.join(IceCube::I18n::LOCALES_PATH, 'en.yml'))['en']
|
26
32
|
end
|
27
33
|
end
|
28
34
|
end
|
data/lib/ice_cube/occurrence.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'forwardable'
|
2
1
|
require 'delegate'
|
3
2
|
|
4
3
|
module IceCube
|
@@ -20,18 +19,16 @@ module IceCube
|
|
20
19
|
# Time.now - Occurrence.new(start_time) # => 3600
|
21
20
|
#
|
22
21
|
class Occurrence < SimpleDelegator
|
22
|
+
include Comparable
|
23
23
|
|
24
24
|
# Report class name as 'Time' to thwart type checking.
|
25
25
|
def self.name
|
26
26
|
'Time'
|
27
27
|
end
|
28
28
|
|
29
|
-
# Optimize for common methods to avoid method_missing
|
30
|
-
extend Forwardable
|
31
|
-
def_delegators :start_time, :to_i, :<=>, :==
|
32
|
-
def_delegators :to_range, :cover?, :include?, :each, :first, :last
|
33
|
-
|
34
29
|
attr_reader :start_time, :end_time
|
30
|
+
alias first start_time
|
31
|
+
alias last end_time
|
35
32
|
|
36
33
|
def initialize(start_time, end_time=nil)
|
37
34
|
@start_time = start_time
|
@@ -39,29 +36,34 @@ module IceCube
|
|
39
36
|
__setobj__ @start_time
|
40
37
|
end
|
41
38
|
|
39
|
+
def to_i
|
40
|
+
@start_time.to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
def <=>(other)
|
44
|
+
@start_time <=> other
|
45
|
+
end
|
46
|
+
|
42
47
|
def is_a?(klass)
|
43
48
|
klass == ::Time || super
|
44
49
|
end
|
45
50
|
alias_method :kind_of?, :is_a?
|
46
51
|
|
47
|
-
def intersects?
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
else
|
62
|
-
cover? other
|
63
|
-
end
|
52
|
+
def intersects?(other)
|
53
|
+
return cover?(other) unless other.is_a?(Occurrence) || other.is_a?(Range)
|
54
|
+
|
55
|
+
this_start = first + 1
|
56
|
+
this_end = last # exclude end boundary
|
57
|
+
other_start = other.first + 1
|
58
|
+
other_end = other.last + 1
|
59
|
+
|
60
|
+
!(this_end < other_start || this_start > other_end)
|
61
|
+
end
|
62
|
+
|
63
|
+
def cover?(other)
|
64
|
+
to_range.cover?(other)
|
64
65
|
end
|
66
|
+
alias_method :include?, :cover?
|
65
67
|
|
66
68
|
def comparable_time
|
67
69
|
start_time
|
@@ -4,15 +4,18 @@ module IceCube
|
|
4
4
|
data = {}
|
5
5
|
ical_string.each_line do |line|
|
6
6
|
(property, value) = line.split(':')
|
7
|
-
(property,
|
7
|
+
(property, _tzid) = property.split(';')
|
8
8
|
case property
|
9
9
|
when 'DTSTART'
|
10
|
-
data[:start_time] =
|
10
|
+
data[:start_time] = TimeUtil.deserialize_time(value)
|
11
11
|
when 'DTEND'
|
12
|
-
data[:end_time] =
|
12
|
+
data[:end_time] = TimeUtil.deserialize_time(value)
|
13
|
+
when 'RDATE'
|
14
|
+
data[:rtimes] ||= []
|
15
|
+
data[:rtimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
|
13
16
|
when 'EXDATE'
|
14
17
|
data[:extimes] ||= []
|
15
|
-
data[:extimes] += value.split(',').map{|v|
|
18
|
+
data[:extimes] += value.split(',').map { |v| TimeUtil.deserialize_time(v) }
|
16
19
|
when 'DURATION'
|
17
20
|
data[:duration] # FIXME
|
18
21
|
when 'RRULE'
|
@@ -41,7 +44,7 @@ module IceCube
|
|
41
44
|
when 'COUNT'
|
42
45
|
params[:count] = value.to_i
|
43
46
|
when 'UNTIL'
|
44
|
-
params[:until] =
|
47
|
+
params[:until] = TimeUtil.deserialize_time(value).utc
|
45
48
|
when 'WKST'
|
46
49
|
params[:week_start] = TimeUtil.ical_day_to_symbol(value)
|
47
50
|
when 'BYSECOND'
|
data/lib/ice_cube/rule.rb
CHANGED
@@ -19,20 +19,17 @@ module IceCube
|
|
19
19
|
until_time || occurrence_count
|
20
20
|
end
|
21
21
|
|
22
|
-
def ==(
|
23
|
-
|
24
|
-
|
25
|
-
hash && hash == rule.to_hash
|
26
|
-
end
|
22
|
+
def ==(other)
|
23
|
+
return false unless other.is_a? Rule
|
24
|
+
hash == other.hash
|
27
25
|
end
|
28
26
|
|
29
27
|
def hash
|
30
|
-
|
31
|
-
h.nil? ? super : h.hash
|
28
|
+
to_hash.hash
|
32
29
|
end
|
33
30
|
|
34
31
|
def to_ical
|
35
|
-
raise MethodNotImplemented, "Expected to be
|
32
|
+
raise MethodNotImplemented, "Expected to be overridden by subclasses"
|
36
33
|
end
|
37
34
|
|
38
35
|
# Convert from ical string and create a rule
|
@@ -61,11 +58,6 @@ module IceCube
|
|
61
58
|
next_time(time, schedule, time).to_i == time.to_i
|
62
59
|
end
|
63
60
|
|
64
|
-
# Whether this rule requires a full run
|
65
|
-
def full_required?
|
66
|
-
!@count.nil?
|
67
|
-
end
|
68
|
-
|
69
61
|
class << self
|
70
62
|
|
71
63
|
# Convert from a hash and create a rule
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class DailyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
include Validations::DayOfMonth
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
# include Validations::DayOfYear # n/a
|
13
|
+
|
5
14
|
include Validations::DailyInterval
|
6
15
|
|
7
16
|
def initialize(interval = 1)
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class HourlyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
include Validations::DayOfMonth
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
include Validations::DayOfYear
|
13
|
+
|
5
14
|
include Validations::HourlyInterval
|
6
15
|
|
7
16
|
def initialize(interval = 1)
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class MinutelyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
include Validations::DayOfMonth
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
include Validations::DayOfYear
|
13
|
+
|
5
14
|
include Validations::MinutelyInterval
|
6
15
|
|
7
16
|
def initialize(interval = 1)
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class MonthlyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
include Validations::DayOfMonth
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
# include Validations::DayOfYear # n/a
|
13
|
+
|
5
14
|
include Validations::MonthlyInterval
|
6
15
|
|
7
16
|
def initialize(interval = 1)
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class SecondlyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
include Validations::DayOfMonth
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
include Validations::DayOfYear
|
13
|
+
|
5
14
|
include Validations::SecondlyInterval
|
6
15
|
|
7
16
|
def initialize(interval = 1)
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class WeeklyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
# include Validations::DayOfMonth # n/a
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
# include Validations::DayOfYear # n/a
|
13
|
+
|
5
14
|
include Validations::WeeklyInterval
|
6
15
|
|
7
16
|
attr_reader :week_start
|
@@ -13,25 +22,37 @@ module IceCube
|
|
13
22
|
reset
|
14
23
|
end
|
15
24
|
|
16
|
-
#
|
17
|
-
# in the week than
|
18
|
-
#
|
19
|
-
#
|
25
|
+
# Move the effective start time to correct for when the schedule has
|
26
|
+
# validations earlier in the week than the selected start time, e.g.
|
27
|
+
#
|
28
|
+
# Schedule.new(wednesday).weekly(2).day(:monday)
|
29
|
+
#
|
30
|
+
# The effective start time gets realigned to the second next Monday, jumping
|
31
|
+
# over the gap week for the interval (2). Without realignment, the correct
|
32
|
+
# Monday occurrence would be missed when the schedule performs a 7-day jump
|
33
|
+
# into the next interval week, arriving on the Wednesday. This corrects any
|
34
|
+
# selections from dates that are misaligned to the schedule interval.
|
20
35
|
#
|
21
36
|
def realign(step_time, start_time)
|
22
37
|
time = TimeUtil::TimeWrapper.new(start_time)
|
23
38
|
offset = wday_offset(step_time, start_time)
|
24
|
-
time.add(:day, offset)
|
25
|
-
time.to_time
|
39
|
+
time.add(:day, offset)
|
40
|
+
super step_time, time.to_time
|
26
41
|
end
|
27
42
|
|
43
|
+
# Calculate how many days to the first wday validation in the correct
|
44
|
+
# interval week. This may move backwards within the week if starting in an
|
45
|
+
# interval week with earlier validations.
|
46
|
+
#
|
28
47
|
def wday_offset(step_time, start_time)
|
48
|
+
return 0 if step_time == start_time
|
49
|
+
|
29
50
|
wday_validations = other_interval_validations.select { |v| v.type == :wday }
|
30
|
-
return if wday_validations.none?
|
51
|
+
return 0 if wday_validations.none?
|
31
52
|
|
32
|
-
days =
|
53
|
+
days = step_time.to_date - start_time.to_date
|
33
54
|
interval = base_interval_validation.validate(step_time, start_time).to_i
|
34
|
-
min_wday = TimeUtil.normalize_wday(
|
55
|
+
min_wday = wday_validations.map { |v| TimeUtil.normalize_wday(v.day, week_start) }.min
|
35
56
|
step_wday = TimeUtil.normalize_wday(step_time.wday, week_start)
|
36
57
|
|
37
58
|
days + interval - step_wday + min_wday
|
@@ -2,6 +2,15 @@ module IceCube
|
|
2
2
|
|
3
3
|
class YearlyRule < ValidatedRule
|
4
4
|
|
5
|
+
include Validations::HourOfDay
|
6
|
+
include Validations::MinuteOfHour
|
7
|
+
include Validations::SecondOfMinute
|
8
|
+
include Validations::DayOfMonth
|
9
|
+
include Validations::DayOfWeek
|
10
|
+
include Validations::Day
|
11
|
+
include Validations::MonthOfYear
|
12
|
+
include Validations::DayOfYear
|
13
|
+
|
5
14
|
include Validations::YearlyInterval
|
6
15
|
|
7
16
|
def initialize(interval = 1)
|