ice_cube_cron 0.0.2 → 0.0.3
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/.rdoc_options +25 -0
- data/.rubocop.yml +4 -0
- data/Gemfile +0 -8
- data/Gemfile.lock +1 -47
- data/README.md +6 -2
- data/lib/ice_cube_cron/base.rb +1 -1
- data/lib/ice_cube_cron/expression_parser.rb +102 -71
- data/lib/ice_cube_cron/extension.rb +22 -4
- data/lib/ice_cube_cron/parser_attribute.rb +28 -0
- data/lib/ice_cube_cron/rule_builder.rb +39 -19
- data/lib/ice_cube_cron/util.rb +4 -1
- data/lib/ice_cube_cron/version.rb +2 -2
- data/lib/ice_cube_cron.rb +6 -0
- data/lib/ice_cube_ext/validated_rule.rb +5 -0
- data/lib/ice_cube_ext/validations/year.rb +55 -0
- data/spec/lib/ice_cube_cron/base_spec.rb +63 -2
- data/spec/lib/ice_cube_cron/expression_parser_spec.rb +111 -58
- data/spec/lib/ice_cube_cron/rule_builder_spec.rb +5 -0
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 75073a57e6693975beb5f23a78daf4aa3e82fbf8
|
|
4
|
+
data.tar.gz: 8a6a29270f4b92bd20b4642307d3cf8e79d6c80b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06a51ee2d28f4725be2058c6009ea2eedddd8a35634690492e001132078aef5e404651530a2286f7a9c606b37e14c60169d7e3ffadcf15703f12867ca931c1cd
|
|
7
|
+
data.tar.gz: aa95de45173bfb490d5e7fb29058126af81a2b9a2d8f4af5fbee8381435310117b5d5b3ce0f5338f0d633aa1f0960fbbb864c455ba71850e0a74ed18c4c5df63
|
data/.rdoc_options
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
--- !ruby/object:RDoc::Options
|
|
2
|
+
encoding: UTF-8
|
|
3
|
+
static_path: []
|
|
4
|
+
rdoc_include:
|
|
5
|
+
- ./README.md
|
|
6
|
+
- "/Users/matthewnichols/Code/ice_cube_cron/."
|
|
7
|
+
charset: UTF-8
|
|
8
|
+
exclude:
|
|
9
|
+
- ./Gemfile*
|
|
10
|
+
- ./Guardfile
|
|
11
|
+
hyperlink_all: false
|
|
12
|
+
line_numbers: false
|
|
13
|
+
locale:
|
|
14
|
+
locale_dir: locale
|
|
15
|
+
locale_name:
|
|
16
|
+
main_page: README.md
|
|
17
|
+
markup: markdown
|
|
18
|
+
output_decoration: true
|
|
19
|
+
page_dir:
|
|
20
|
+
show_hash: false
|
|
21
|
+
tab_width: 8
|
|
22
|
+
template_stylesheets: []
|
|
23
|
+
title:
|
|
24
|
+
visibility: :protected
|
|
25
|
+
webcvs:
|
data/.rubocop.yml
CHANGED
|
@@ -8,6 +8,9 @@ Style/AccessModifierIndentation:
|
|
|
8
8
|
EnforcedStyle: outdent
|
|
9
9
|
|
|
10
10
|
Style/Documentation:
|
|
11
|
+
Enabled: true
|
|
12
|
+
|
|
13
|
+
Style/SignalException:
|
|
11
14
|
Enabled: false
|
|
12
15
|
|
|
13
16
|
Metrics/LineLength:
|
|
@@ -15,3 +18,4 @@ Metrics/LineLength:
|
|
|
15
18
|
|
|
16
19
|
Metrics/MethodLength:
|
|
17
20
|
Max: 15
|
|
21
|
+
|
data/Gemfile
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
|
-
# DEVUP--
|
|
5
|
-
gem 'guard-zeus', :group => :development
|
|
6
|
-
gem 'guard-rspec', :group => :development
|
|
7
|
-
gem 'guard-rubocop', :group => :development
|
|
8
|
-
gem 'rb-fsevent', :group => :development
|
|
9
|
-
gem 'terminal-notifier-guard', :group => :development
|
|
10
|
-
gem 'wirble', :group => :development
|
|
11
|
-
# --DEVUP
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
ice_cube_cron (0.0.
|
|
4
|
+
ice_cube_cron (0.0.2)
|
|
5
5
|
activesupport (>= 3.0.0)
|
|
6
6
|
ice_cube (= 0.13.0)
|
|
7
7
|
|
|
@@ -19,42 +19,11 @@ GEM
|
|
|
19
19
|
parser (~> 2.2)
|
|
20
20
|
coderay (1.1.0)
|
|
21
21
|
diff-lcs (1.2.5)
|
|
22
|
-
ffi (1.9.10)
|
|
23
|
-
formatador (0.2.5)
|
|
24
|
-
guard (2.13.0)
|
|
25
|
-
formatador (>= 0.2.4)
|
|
26
|
-
listen (>= 2.7, <= 4.0)
|
|
27
|
-
lumberjack (~> 1.0)
|
|
28
|
-
nenv (~> 0.1)
|
|
29
|
-
notiffany (~> 0.0)
|
|
30
|
-
pry (>= 0.9.12)
|
|
31
|
-
shellany (~> 0.0)
|
|
32
|
-
thor (>= 0.18.1)
|
|
33
|
-
guard-compat (1.2.1)
|
|
34
|
-
guard-rspec (4.6.4)
|
|
35
|
-
guard (~> 2.1)
|
|
36
|
-
guard-compat (~> 1.1)
|
|
37
|
-
rspec (>= 2.99.0, < 4.0)
|
|
38
|
-
guard-rubocop (1.2.0)
|
|
39
|
-
guard (~> 2.0)
|
|
40
|
-
rubocop (~> 0.20)
|
|
41
|
-
guard-zeus (2.0.1)
|
|
42
|
-
guard (~> 2.0)
|
|
43
|
-
guard-compat (~> 1.1)
|
|
44
|
-
zeus (~> 0)
|
|
45
22
|
i18n (0.7.0)
|
|
46
23
|
ice_cube (0.13.0)
|
|
47
24
|
json (1.8.3)
|
|
48
|
-
listen (3.0.3)
|
|
49
|
-
rb-fsevent (>= 0.9.3)
|
|
50
|
-
rb-inotify (>= 0.9)
|
|
51
|
-
lumberjack (1.0.9)
|
|
52
25
|
method_source (0.8.2)
|
|
53
26
|
minitest (5.8.1)
|
|
54
|
-
nenv (0.2.0)
|
|
55
|
-
notiffany (0.0.8)
|
|
56
|
-
nenv (~> 0.1)
|
|
57
|
-
shellany (~> 0.0)
|
|
58
27
|
parser (2.2.3.0)
|
|
59
28
|
ast (>= 1.1, < 3.0)
|
|
60
29
|
powerpack (0.1.1)
|
|
@@ -64,9 +33,6 @@ GEM
|
|
|
64
33
|
slop (~> 3.4)
|
|
65
34
|
rainbow (2.0.0)
|
|
66
35
|
rake (10.4.2)
|
|
67
|
-
rb-fsevent (0.9.6)
|
|
68
|
-
rb-inotify (0.9.5)
|
|
69
|
-
ffi (>= 0.5.0)
|
|
70
36
|
rspec (3.3.0)
|
|
71
37
|
rspec-core (~> 3.3.0)
|
|
72
38
|
rspec-expectations (~> 3.3.0)
|
|
@@ -87,32 +53,20 @@ GEM
|
|
|
87
53
|
rainbow (>= 1.99.1, < 3.0)
|
|
88
54
|
ruby-progressbar (~> 1.4)
|
|
89
55
|
ruby-progressbar (1.7.5)
|
|
90
|
-
shellany (0.0.1)
|
|
91
56
|
slop (3.6.0)
|
|
92
|
-
terminal-notifier-guard (1.6.4)
|
|
93
|
-
thor (0.19.1)
|
|
94
57
|
thread_safe (0.3.5)
|
|
95
58
|
tzinfo (1.2.2)
|
|
96
59
|
thread_safe (~> 0.1)
|
|
97
|
-
wirble (0.1.3)
|
|
98
|
-
zeus (0.15.4)
|
|
99
|
-
method_source (>= 0.6.7)
|
|
100
60
|
|
|
101
61
|
PLATFORMS
|
|
102
62
|
ruby
|
|
103
63
|
|
|
104
64
|
DEPENDENCIES
|
|
105
|
-
guard-rspec
|
|
106
|
-
guard-rubocop
|
|
107
|
-
guard-zeus
|
|
108
65
|
ice_cube_cron!
|
|
109
66
|
pry
|
|
110
67
|
rake
|
|
111
|
-
rb-fsevent
|
|
112
68
|
rspec
|
|
113
69
|
rubocop
|
|
114
|
-
terminal-notifier-guard
|
|
115
|
-
wirble
|
|
116
70
|
|
|
117
71
|
BUNDLED WITH
|
|
118
72
|
1.10.6
|
data/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/ice_cube_cron)
|
|
2
|
+
|
|
1
3
|
# ice_cube_cron
|
|
2
4
|
|
|
3
5
|
Adds new methods to ice_cube to create schedules using standard cron expressions.
|
|
4
6
|
|
|
5
7
|
## description
|
|
6
8
|
|
|
7
|
-
**ice_cube** is a sold library for projecting and querying recurrence rules. **Cron** is _the_ standard for expressing recurrence rules. This gem will allow you to generate ice_cube schedules using standard cron expressions [explained here](https://en.wikipedia.org/wiki/Cron). This includes range expressions, series expressions, "last" day of month, Nth weekday of month, etc.
|
|
9
|
+
**[ice_cube](https://github.com/seejohnrun/ice_cube)** is a sold library for projecting and querying recurrence rules. **[Cron](https://en.wikipedia.org/wiki/Cron)** is _the_ standard for expressing recurrence rules. This gem will allow you to generate ice_cube schedules using standard cron expressions [explained here](https://en.wikipedia.org/wiki/Cron). This includes range expressions, series expressions, "last" day of month, Nth weekday of month, etc.
|
|
8
10
|
|
|
9
11
|
PLEASE NOTE:
|
|
10
12
|
This gem is a work-in-progress. Many features have yet to be implemented.
|
|
@@ -19,7 +21,6 @@ or add to Gemfile
|
|
|
19
21
|
|
|
20
22
|
## example
|
|
21
23
|
|
|
22
|
-
Cron expression can be specified using a hash or a string in the format:
|
|
23
24
|
```
|
|
24
25
|
# * * * * * * command to execute
|
|
25
26
|
# │ │ │ │ │ │
|
|
@@ -31,9 +32,12 @@ Cron expression can be specified using a hash or a string in the format:
|
|
|
31
32
|
# │ └──────────────────── hour (0 - 23)
|
|
32
33
|
# └───────────────────────── min (0 - 59)
|
|
33
34
|
```
|
|
35
|
+
|
|
34
36
|
*[chart source](https://en.wikipedia.org/wiki/Cron)*
|
|
35
37
|
|
|
36
38
|
|
|
39
|
+
Cron expression can be specified using a hash or a string in the format:
|
|
40
|
+
|
|
37
41
|
```ruby
|
|
38
42
|
require 'ice_cube_cron'
|
|
39
43
|
|
data/lib/ice_cube_cron/base.rb
CHANGED
|
@@ -1,92 +1,106 @@
|
|
|
1
|
-
module IceCubeCron
|
|
1
|
+
module IceCubeCron # :nodoc:
|
|
2
|
+
##
|
|
3
|
+
# Parses the incoming expression and splits it into meaningful parts.
|
|
4
|
+
#
|
|
2
5
|
class ExpressionParser
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
include ::IceCubeCron::ParserAttribute
|
|
7
|
+
|
|
8
|
+
EXPRESSION_PART_DEFAULTS = {
|
|
9
|
+
:repeat_interval => 1,
|
|
10
|
+
:repeat_year => nil,
|
|
11
|
+
:repeat_month => nil,
|
|
12
|
+
:repeat_day => nil,
|
|
13
|
+
:repeat_weekday => nil,
|
|
14
|
+
:repeat_until => nil
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
EXPRESSION_PART_KEYS = [
|
|
18
|
+
:repeat_minute,
|
|
19
|
+
:repeat_hour,
|
|
20
|
+
:repeat_day,
|
|
21
|
+
:repeat_month,
|
|
22
|
+
:repeat_weekday,
|
|
23
|
+
:repeat_year
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Create a parsed expression
|
|
28
|
+
#
|
|
29
|
+
# Takes a hash of cron expression parts.
|
|
30
|
+
#
|
|
31
|
+
# ### Expression values:
|
|
32
|
+
# - interval
|
|
33
|
+
# - year
|
|
34
|
+
# - month
|
|
35
|
+
# - day
|
|
36
|
+
# - weekday
|
|
37
|
+
def initialize(*expression)
|
|
38
|
+
expression_parts = expression.last.is_a?(::Hash) ? expression.last : {}
|
|
39
|
+
|
|
40
|
+
expression_str = expression[0].is_a?(::String) ? expression[0] : nil
|
|
41
|
+
expression_parts.merge!(string_to_expression_parts(expression_str))
|
|
42
|
+
|
|
43
|
+
self.expression_hash = EXPRESSION_PART_DEFAULTS.dup
|
|
44
|
+
|
|
45
|
+
expression_parts.each do |name, val|
|
|
46
|
+
send("#{name}=", val)
|
|
20
47
|
end
|
|
21
48
|
end
|
|
22
49
|
|
|
23
|
-
|
|
24
|
-
|
|
50
|
+
parser_attribute_accessor :interval do |val|
|
|
51
|
+
ExpressionParser.sanitize_integer_param(val, 1)
|
|
25
52
|
end
|
|
26
53
|
|
|
27
|
-
|
|
28
|
-
|
|
54
|
+
parser_attribute_accessor :day do |val|
|
|
55
|
+
ExpressionParser.sanitize_day_param(val)
|
|
29
56
|
end
|
|
30
57
|
|
|
31
|
-
|
|
32
|
-
|
|
58
|
+
parser_attribute_accessor :month do |val|
|
|
59
|
+
ExpressionParser.sanitize_integer_array_param(val)
|
|
33
60
|
end
|
|
34
|
-
alias_method :repeat_interval, :interval
|
|
35
61
|
|
|
36
|
-
|
|
37
|
-
expression_hash[:repeat_interval] = sanitize_integer_param(val, 1)
|
|
38
|
-
end
|
|
39
|
-
alias_method :repeat_interval=, :interval=
|
|
62
|
+
parser_attribute_accessor :until
|
|
40
63
|
|
|
41
|
-
|
|
42
|
-
|
|
64
|
+
parser_attribute_accessor :year do |val|
|
|
65
|
+
ExpressionParser.sanitize_integer_array_param(val)
|
|
43
66
|
end
|
|
44
|
-
alias_method :repeat_day, :day
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
|
|
68
|
+
parser_attribute_accessor :weekday do |val|
|
|
69
|
+
ExpressionParser.sanitize_week_day_param(val)
|
|
48
70
|
end
|
|
49
|
-
alias_method :repeat_day=, :day=
|
|
50
71
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
72
|
+
##
|
|
73
|
+
# Split string expression into parts
|
|
74
|
+
#
|
|
75
|
+
def string_to_expression_parts(expression_str)
|
|
76
|
+
return {} if expression_str.nil?
|
|
55
77
|
|
|
56
|
-
|
|
57
|
-
expression_hash[:repeat_month] = sanitize_integer_array_param(val)
|
|
58
|
-
end
|
|
59
|
-
alias_method :repeat_month=, :month=
|
|
78
|
+
parts = expression_str.split(/ +/)
|
|
60
79
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def year=(val)
|
|
67
|
-
expression_hash[:repeat_year] = sanitize_integer_array_param(val)
|
|
68
|
-
end
|
|
69
|
-
alias_method :repeat_year=, :year=
|
|
80
|
+
expression_parts = ::Hash[EXPRESSION_PART_KEYS.zip(parts)]
|
|
81
|
+
expression_parts.select! do |_key, value|
|
|
82
|
+
next false if value.nil?
|
|
83
|
+
next false if value == '*'
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end
|
|
74
|
-
alias_method :repeat_weekday, :weekday
|
|
85
|
+
true
|
|
86
|
+
end
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
expression_hash[:repeat_weekday] = sanitize_week_day_param(val)
|
|
88
|
+
expression_parts
|
|
78
89
|
end
|
|
79
|
-
alias_method :repeat_weekday=, :weekday=
|
|
80
|
-
|
|
81
|
-
private
|
|
82
90
|
|
|
83
|
-
|
|
91
|
+
##
|
|
92
|
+
# Sanitize given value to an integer
|
|
93
|
+
#
|
|
94
|
+
def self.sanitize_integer_param(param, default = nil)
|
|
84
95
|
return default if param.blank?
|
|
85
96
|
|
|
86
97
|
param.to_i
|
|
87
98
|
end
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
##
|
|
101
|
+
# Sanitize given value to a valid day parameter
|
|
102
|
+
#
|
|
103
|
+
def self.sanitize_day_param(param)
|
|
90
104
|
return nil if param.blank?
|
|
91
105
|
return param if param.is_a?(::Array)
|
|
92
106
|
return [param] if param.is_a?(::Integer)
|
|
@@ -94,30 +108,47 @@ module IceCubeCron
|
|
|
94
108
|
param.to_s.split(',').map do |element|
|
|
95
109
|
next -1 if element == 'L'
|
|
96
110
|
|
|
97
|
-
element
|
|
98
|
-
end
|
|
111
|
+
ExpressionParser.sanitize_integer_array_param(element)
|
|
112
|
+
end.flatten.uniq
|
|
99
113
|
end
|
|
100
114
|
|
|
101
|
-
|
|
115
|
+
##
|
|
116
|
+
# Sanitize given value to a valid weekday parameter
|
|
117
|
+
#
|
|
118
|
+
def self.sanitize_week_day_param(param)
|
|
102
119
|
return nil if param.blank?
|
|
103
120
|
param.to_s.split(',').map do |element|
|
|
104
121
|
if element =~ /[0-9]+#[0-9]+/
|
|
105
122
|
parts = element.split('#')
|
|
106
|
-
{ sanitize_integer_param(parts[0]) => sanitize_integer_array_param(parts[1]) }
|
|
123
|
+
{ ExpressionParser.sanitize_integer_param(parts[0]) => ExpressionParser.sanitize_integer_array_param(parts[1]) }
|
|
107
124
|
elsif element =~ /[0-9]+L/
|
|
108
|
-
{ sanitize_integer_param(element) => [-1] }
|
|
125
|
+
{ ExpressionParser.sanitize_integer_param(element) => [-1] }
|
|
109
126
|
else
|
|
110
|
-
sanitize_integer_param(element)
|
|
127
|
+
ExpressionParser.sanitize_integer_param(element)
|
|
111
128
|
end
|
|
112
129
|
end
|
|
113
130
|
end
|
|
114
131
|
|
|
115
|
-
|
|
132
|
+
##
|
|
133
|
+
# Sanitize given value to an integer array
|
|
134
|
+
#
|
|
135
|
+
#--
|
|
136
|
+
# rubocop:disable Metrics/AbcSize
|
|
137
|
+
#++
|
|
138
|
+
def self.sanitize_integer_array_param(param)
|
|
116
139
|
return nil if param.blank?
|
|
117
140
|
return param if param.is_a?(::Array)
|
|
118
141
|
return [param] if param.is_a?(::Integer)
|
|
119
142
|
|
|
120
|
-
param.split(',').map
|
|
143
|
+
param.split(',').map do |element|
|
|
144
|
+
if element =~ /[0-9]+\-[0-9]+/
|
|
145
|
+
parts = element.split('-')
|
|
146
|
+
(parts[0].to_i..parts[1].to_i).to_a
|
|
147
|
+
else
|
|
148
|
+
element.to_i
|
|
149
|
+
end
|
|
150
|
+
end.flatten.uniq
|
|
121
151
|
end
|
|
152
|
+
# rubocop:enable Metrics/AbcSize
|
|
122
153
|
end
|
|
123
154
|
end
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
module IceCubeCron
|
|
1
|
+
module IceCubeCron # :nodoc:
|
|
2
|
+
##
|
|
3
|
+
# This adds the `.from_cron` extension to the `::IceCube::Schedule` class
|
|
4
|
+
#
|
|
2
5
|
module Extension
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
##
|
|
7
|
+
# Generates an ::IceCube::Schedule from a cron expression_parts
|
|
8
|
+
#
|
|
9
|
+
# :args: start_time, expression_parts
|
|
10
|
+
#
|
|
11
|
+
# ## Examples
|
|
12
|
+
#
|
|
13
|
+
# ```ruby
|
|
14
|
+
# schedule = ::IceCube::Schedule.from_cron(::Date.current, "* * * * 5")
|
|
15
|
+
#
|
|
16
|
+
# schedule = ::IceCube::Schedule.from_cron(::Date.new(2015, 1, 5), :repeat_day => 5)
|
|
17
|
+
#
|
|
18
|
+
# schedule.occurrences_between(::Date.new(2015, 3, 5), ::Date.new(2015, 6, 5))
|
|
19
|
+
# # => [2015-03-05 00:00:00 UTC, 2015-04-05 00:00:00 UTC, 2015-05-05 00:00:00 UTC, 2015-06-05 00:00:00 UTC]
|
|
20
|
+
#
|
|
21
|
+
def from_cron(start_time, *expression_parts)
|
|
22
|
+
expression = ::IceCubeCron::ExpressionParser.new(*expression_parts)
|
|
23
|
+
rule = ::IceCubeCron::RuleBuilder.new.build_rule(expression)
|
|
6
24
|
|
|
7
25
|
schedule = ::IceCube::Schedule.new(::IceCubeCron::Util.sanitize_date_param(start_time))
|
|
8
26
|
schedule.add_recurrence_rule(rule)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module IceCubeCron # :nodoc: all
|
|
2
|
+
module ParserAttribute # :nodoc:
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.extend(::IceCubeCron::ParserAttribute::ClassMethods)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
attr_accessor :expression_hash
|
|
8
|
+
|
|
9
|
+
module ClassMethods # :nodoc:
|
|
10
|
+
def parser_attribute_accessor(attr_name, &cleanser)
|
|
11
|
+
getter = "repeat_#{attr_name}".to_sym
|
|
12
|
+
setter = "repeat_#{attr_name}=".to_sym
|
|
13
|
+
|
|
14
|
+
define_method(getter) do
|
|
15
|
+
expression_hash[getter]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
define_method(setter) do |val|
|
|
19
|
+
val = cleanser.call(val) if cleanser
|
|
20
|
+
expression_hash[getter] = val
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alias_method attr_name, getter
|
|
24
|
+
alias_method "#{attr_name}=".to_sym, setter
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,34 +1,54 @@
|
|
|
1
|
-
module IceCubeCron
|
|
1
|
+
module IceCubeCron # :nodoc:
|
|
2
|
+
##
|
|
3
|
+
# Generates Rules based on parsed expression
|
|
4
|
+
#
|
|
2
5
|
class RuleBuilder
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
rule =
|
|
6
|
+
##
|
|
7
|
+
# Generates a rule based on a parsed expression
|
|
8
|
+
#
|
|
9
|
+
def build_rule(expression)
|
|
10
|
+
rule = build_root_recurrence_rule(expression)
|
|
11
|
+
rule = build_yearly_rules(rule, expression)
|
|
12
|
+
rule = build_weekday_rule(rule, expression)
|
|
13
|
+
rule = rule.day_of_month(*expression.day) unless expression.day.blank?
|
|
14
|
+
rule = rule.until(expression.until) unless expression.until.blank?
|
|
8
15
|
|
|
9
16
|
rule
|
|
10
17
|
end
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
19
|
+
# :nodoc:
|
|
20
|
+
def nth_day?(param)
|
|
21
|
+
return false if param.nil? || param.empty?
|
|
22
|
+
param[0].is_a?(::Hash)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
# :nodoc:
|
|
28
|
+
def build_weekday_rule(rule, expression)
|
|
29
|
+
return rule.day_of_week(*expression.weekday) if !expression.weekday.blank? && nth_day?(expression.weekday)
|
|
30
|
+
return rule.day(*expression.weekday) unless expression.weekday.blank?
|
|
15
31
|
|
|
16
32
|
rule
|
|
17
33
|
end
|
|
18
34
|
|
|
19
|
-
#
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return ::IceCube::Rule.weekly(params[:interval]) unless params[:weekday].blank?
|
|
35
|
+
# :nodoc:
|
|
36
|
+
def build_yearly_rules(rule, expression)
|
|
37
|
+
rule = rule.year(*expression.year) unless expression.year.blank?
|
|
38
|
+
rule = rule.month_of_year(*expression.month) unless expression.month.blank?
|
|
24
39
|
|
|
25
|
-
|
|
40
|
+
rule
|
|
26
41
|
end
|
|
27
|
-
# rubocop:enable Metrics/AbcSize
|
|
28
42
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
# rubocop:disable Metrics/AbcSize
|
|
44
|
+
def build_root_recurrence_rule(expression) # :nodoc:
|
|
45
|
+
return ::IceCube::Rule.yearly(expression.interval) unless expression.month.blank?
|
|
46
|
+
return ::IceCube::Rule.monthly(expression.interval) if !expression.weekday.blank? && nth_day?(expression.weekday)
|
|
47
|
+
return ::IceCube::Rule.monthly(expression.interval) unless expression.day.blank?
|
|
48
|
+
return ::IceCube::Rule.weekly(expression.interval) unless expression.weekday.blank?
|
|
49
|
+
|
|
50
|
+
::IceCube::Rule.monthly(expression.interval)
|
|
32
51
|
end
|
|
52
|
+
# rubocop:enable Metrics/AbcSize
|
|
33
53
|
end
|
|
34
54
|
end
|
data/lib/ice_cube_cron/util.rb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module IceCubeCron
|
|
2
|
-
VERSION = '0.0.
|
|
1
|
+
module IceCubeCron # :nodoc: all
|
|
2
|
+
VERSION = '0.0.3'
|
|
3
3
|
end
|
data/lib/ice_cube_cron.rb
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
require 'ice_cube'
|
|
2
2
|
|
|
3
|
+
# core extensions
|
|
3
4
|
require 'active_support/core_ext/date'
|
|
4
5
|
require 'active_support/core_ext/integer'
|
|
5
6
|
|
|
7
|
+
# ice_cube extentions
|
|
8
|
+
require 'ice_cube_ext/validations/year.rb'
|
|
9
|
+
require 'ice_cube_ext/validated_rule.rb'
|
|
10
|
+
|
|
6
11
|
require 'ice_cube_cron/version'
|
|
7
12
|
require 'ice_cube_cron/util'
|
|
8
13
|
require 'ice_cube_cron/rule_builder'
|
|
14
|
+
require 'ice_cube_cron/parser_attribute'
|
|
9
15
|
require 'ice_cube_cron/expression_parser'
|
|
10
16
|
require 'ice_cube_cron/extension'
|
|
11
17
|
require 'ice_cube_cron/base'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module IceCube
|
|
2
|
+
module Validations
|
|
3
|
+
##
|
|
4
|
+
# Allows addition of a year (non-standard cron) to the repeat rules.
|
|
5
|
+
#
|
|
6
|
+
module Year
|
|
7
|
+
##
|
|
8
|
+
# Call to filter occurrences to one or more years.
|
|
9
|
+
#
|
|
10
|
+
def year(*years)
|
|
11
|
+
years.flatten.each do |year|
|
|
12
|
+
unless year.is_a?(Fixnum)
|
|
13
|
+
raise ArgumentError, "expecting Fixnum value for year, got #{year.inspect}"
|
|
14
|
+
end
|
|
15
|
+
validations_for(:year) << Validation.new(year)
|
|
16
|
+
end
|
|
17
|
+
::IceCube::Validations::FixedValue::INTERVALS[:year] = 100
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Validation < Validations::FixedValue # :nodoc:
|
|
22
|
+
attr_reader :year
|
|
23
|
+
alias_method :value, :year
|
|
24
|
+
|
|
25
|
+
def initialize(year)
|
|
26
|
+
@year = year
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def type
|
|
30
|
+
:year
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def dst_adjust?
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def build_s(builder)
|
|
38
|
+
builder.piece(:year) << StringBuilder.nice_number(year)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def build_hash(builder)
|
|
42
|
+
builder.validations_array(:year) << year
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build_ical(builder)
|
|
46
|
+
builder['BYYEAR'] << year
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
StringBuilder.register_formatter(:year) do |entries|
|
|
50
|
+
"in #{StringBuilder.sentence(entries)} "
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -214,6 +214,67 @@ describe ::IceCubeCron do
|
|
|
214
214
|
expect(ice_cube_model.occurrences_between(::Date.new(2016, 2, 1), ::Date.new(2016, 4, 30))).to eq([::Date.new(2016, 2, 8), ::Date.new(2016, 3, 14), ::Date.new(2016, 4, 11)])
|
|
215
215
|
end
|
|
216
216
|
end
|
|
217
|
+
|
|
218
|
+
context 'every month until date' do
|
|
219
|
+
let(:schedule) do
|
|
220
|
+
::IceCube::Schedule.from_cron(
|
|
221
|
+
::Date.new(2015, 1, 1),
|
|
222
|
+
:repeat_day => '1',
|
|
223
|
+
:repeat_until => ::Date.new(2015, 3, 1)
|
|
224
|
+
)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'ends on specified end date' do
|
|
228
|
+
expect(schedule.occurrences_between(::Date.new(2015, 1, 1), ::Date.new(2015, 6, 30))).to eq([::Date.new(2015, 1, 1), ::Date.new(2015, 2, 1), ::Date.new(2015, 3, 1)])
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'year expression support (non-standard)' do
|
|
233
|
+
context 'in month of a year' do
|
|
234
|
+
let(:ice_cube_model) do
|
|
235
|
+
::IceCube::Schedule.from_cron(
|
|
236
|
+
::Date.new(2015, 1, 1),
|
|
237
|
+
:year => '2015',
|
|
238
|
+
:month => '6',
|
|
239
|
+
:day => '10'
|
|
240
|
+
)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it '#occurrences_between' do
|
|
244
|
+
expect(ice_cube_model.occurrences_between(::Date.new(2013, 1, 1), ::Date.new(2017, 12, 31))).to eq([::Date.new(2015, 6, 10)])
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
context 'in a month of multiple years' do
|
|
249
|
+
let(:ice_cube_model) do
|
|
250
|
+
::IceCube::Schedule.from_cron(
|
|
251
|
+
::Date.new(2015, 1, 1),
|
|
252
|
+
:year => '2015,2017',
|
|
253
|
+
:month => '6',
|
|
254
|
+
:day => '10'
|
|
255
|
+
)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it '#occurrences_between' do
|
|
259
|
+
expect(ice_cube_model.occurrences_between(::Date.new(2013, 1, 1), ::Date.new(2018, 12, 31))).to eq([::Date.new(2015, 6, 10), ::Date.new(2017, 6, 10)])
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
context 'multiple days in month of a year' do
|
|
264
|
+
let(:ice_cube_model) do
|
|
265
|
+
::IceCube::Schedule.from_cron(
|
|
266
|
+
::Date.new(2015, 1, 1),
|
|
267
|
+
:year => '2015',
|
|
268
|
+
:month => '6',
|
|
269
|
+
:day => '10,15'
|
|
270
|
+
)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it '#occurrences_between' do
|
|
274
|
+
expect(ice_cube_model.occurrences_between(::Date.new(2013, 1, 1), ::Date.new(2017, 12, 31))).to eq([::Date.new(2015, 6, 10), ::Date.new(2015, 6, 15)])
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
217
278
|
end
|
|
218
279
|
|
|
219
280
|
context 'input types' do
|
|
@@ -223,7 +284,7 @@ describe ::IceCubeCron do
|
|
|
223
284
|
:repeat_day => '1',
|
|
224
285
|
:repeat_interval => '2'
|
|
225
286
|
)
|
|
226
|
-
expect(ice_cube_model.occurrences_between(::
|
|
287
|
+
expect(ice_cube_model.occurrences_between(::Date.new(2015, 7, 1), ::Date.new(2015, 7, 31))).to eq([::Date.new(2015, 7, 1)])
|
|
227
288
|
end
|
|
228
289
|
|
|
229
290
|
it 'handles integer (epoch) as input' do
|
|
@@ -232,7 +293,7 @@ describe ::IceCubeCron do
|
|
|
232
293
|
:repeat_day => '1',
|
|
233
294
|
:repeat_interval => '2'
|
|
234
295
|
)
|
|
235
|
-
expect(ice_cube_model.occurrences_between(::
|
|
296
|
+
expect(ice_cube_model.occurrences_between(::Date.new(2015, 7, 1), ::Date.new(2015, 7, 31))).to eq([::Date.new(2015, 7, 1)])
|
|
236
297
|
end
|
|
237
298
|
end
|
|
238
299
|
end
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe ::IceCubeCron::ExpressionParser do
|
|
4
|
-
let(:
|
|
4
|
+
let(:expression) do
|
|
5
5
|
described_class.new(
|
|
6
|
+
nil,
|
|
6
7
|
:repeat_interval => 2,
|
|
7
8
|
:repeat_day => 3,
|
|
8
9
|
:repeat_month => 4,
|
|
@@ -11,144 +12,196 @@ describe ::IceCubeCron::ExpressionParser do
|
|
|
11
12
|
)
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
describe 'parses ::String expression' do
|
|
16
|
+
# rubocop:disable Style/SymbolProc
|
|
17
|
+
let(:expression_str) { |example| example.description }
|
|
18
|
+
# rubocop:enable Style/SymbolProc
|
|
19
|
+
let(:expression) { described_class.new(expression_str) }
|
|
20
|
+
|
|
21
|
+
it '* * 2 * *' do
|
|
22
|
+
expect(expression.expression_hash[:repeat_interval]).to eq(1)
|
|
23
|
+
expect(expression.expression_hash[:repeat_year]).to eq(nil)
|
|
24
|
+
expect(expression.expression_hash[:repeat_month]).to eq(nil)
|
|
25
|
+
expect(expression.expression_hash[:repeat_day]).to eq([2])
|
|
26
|
+
expect(expression.expression_hash[:repeat_weekday]).to eq(nil)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it '* * 1,15 * *' do
|
|
30
|
+
expect(expression.expression_hash[:repeat_interval]).to eq(1)
|
|
31
|
+
expect(expression.expression_hash[:repeat_year]).to eq(nil)
|
|
32
|
+
expect(expression.expression_hash[:repeat_month]).to eq(nil)
|
|
33
|
+
expect(expression.expression_hash[:repeat_day]).to eq([1, 15])
|
|
34
|
+
expect(expression.expression_hash[:repeat_weekday]).to eq(nil)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it '* * 1 6,12 *' do
|
|
38
|
+
expect(expression.expression_hash[:repeat_interval]).to eq(1)
|
|
39
|
+
expect(expression.expression_hash[:repeat_year]).to eq(nil)
|
|
40
|
+
expect(expression.expression_hash[:repeat_month]).to eq([6, 12])
|
|
41
|
+
expect(expression.expression_hash[:repeat_day]).to eq([1])
|
|
42
|
+
expect(expression.expression_hash[:repeat_weekday]).to eq(nil)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it '* * 1 6 * 2015' do
|
|
46
|
+
expect(expression.expression_hash[:repeat_interval]).to eq(1)
|
|
47
|
+
expect(expression.expression_hash[:repeat_year]).to eq([2015])
|
|
48
|
+
expect(expression.expression_hash[:repeat_month]).to eq([6])
|
|
49
|
+
expect(expression.expression_hash[:repeat_day]).to eq([1])
|
|
50
|
+
expect(expression.expression_hash[:repeat_weekday]).to eq(nil)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it '* * * 6 1L *' do
|
|
54
|
+
expect(expression.expression_hash[:repeat_interval]).to eq(1)
|
|
55
|
+
expect(expression.expression_hash[:repeat_year]).to eq(nil)
|
|
56
|
+
expect(expression.expression_hash[:repeat_month]).to eq([6])
|
|
57
|
+
expect(expression.expression_hash[:repeat_day]).to eq(nil)
|
|
58
|
+
expect(expression.expression_hash[:repeat_weekday]).to eq([1 => [-1]])
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
14
62
|
describe 'parses ::Hash expression' do
|
|
15
63
|
describe 'repeat_interval' do
|
|
16
64
|
it '[]' do
|
|
17
|
-
expect(
|
|
65
|
+
expect(expression.interval).to eq(2)
|
|
18
66
|
end
|
|
19
67
|
|
|
20
68
|
it '[]=' do
|
|
21
|
-
|
|
22
|
-
expect(
|
|
69
|
+
expression.interval = 13
|
|
70
|
+
expect(expression.interval).to eq(13)
|
|
23
71
|
end
|
|
24
72
|
|
|
25
73
|
it 'sanitizes' do
|
|
26
|
-
|
|
27
|
-
expect(
|
|
74
|
+
expression.interval = 2
|
|
75
|
+
expect(expression.interval).to eq(2)
|
|
28
76
|
|
|
29
|
-
|
|
30
|
-
expect(
|
|
77
|
+
expression.interval = nil
|
|
78
|
+
expect(expression.interval).to eq(1)
|
|
31
79
|
|
|
32
|
-
|
|
33
|
-
expect(
|
|
80
|
+
expression.interval = '3'
|
|
81
|
+
expect(expression.interval).to eq(3)
|
|
34
82
|
end
|
|
35
83
|
end
|
|
36
84
|
|
|
37
85
|
describe 'repeat_day' do
|
|
38
86
|
it '[]' do
|
|
39
|
-
expect(
|
|
87
|
+
expect(expression.day).to eq([3])
|
|
40
88
|
end
|
|
41
89
|
|
|
42
90
|
it '[]=' do
|
|
43
|
-
|
|
44
|
-
expect(
|
|
91
|
+
expression.day = 6
|
|
92
|
+
expect(expression.day).to eq([6])
|
|
45
93
|
end
|
|
46
94
|
|
|
47
95
|
it 'sanitizes' do
|
|
48
|
-
|
|
49
|
-
expect(
|
|
96
|
+
expression.day = 2
|
|
97
|
+
expect(expression.day).to eq([2])
|
|
50
98
|
|
|
51
|
-
|
|
52
|
-
expect(
|
|
99
|
+
expression.day = nil
|
|
100
|
+
expect(expression.day).to eq(nil)
|
|
53
101
|
|
|
54
|
-
|
|
55
|
-
expect(
|
|
102
|
+
expression.day = '3'
|
|
103
|
+
expect(expression.day).to eq([3])
|
|
56
104
|
end
|
|
57
105
|
|
|
58
106
|
it 'should accept single day expression' do
|
|
59
|
-
|
|
60
|
-
expect(
|
|
107
|
+
expression.day = '1'
|
|
108
|
+
expect(expression.day).to eq([1])
|
|
61
109
|
end
|
|
62
110
|
|
|
63
111
|
it 'should accept series expression' do
|
|
64
|
-
|
|
65
|
-
expect(
|
|
112
|
+
expression.day = '1,3'
|
|
113
|
+
expect(expression.day).to eq([1, 3])
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'should accept range expression' do
|
|
117
|
+
expression.day = '1-3'
|
|
118
|
+
expect(expression.day).to eq([1, 2, 3])
|
|
66
119
|
end
|
|
67
120
|
|
|
68
121
|
it 'should accept last day expression' do
|
|
69
|
-
|
|
70
|
-
expect(
|
|
122
|
+
expression.day = 'L'
|
|
123
|
+
expect(expression.day).to eq([-1])
|
|
71
124
|
end
|
|
72
125
|
end
|
|
73
126
|
|
|
74
127
|
describe 'repeat_month' do
|
|
75
128
|
it '[]' do
|
|
76
|
-
expect(
|
|
129
|
+
expect(expression.month).to eq([4])
|
|
77
130
|
end
|
|
78
131
|
|
|
79
132
|
it '[]=' do
|
|
80
|
-
|
|
81
|
-
expect(
|
|
133
|
+
expression.month = 11
|
|
134
|
+
expect(expression.month).to eq([11])
|
|
82
135
|
end
|
|
83
136
|
|
|
84
137
|
it 'sanitizes' do
|
|
85
|
-
|
|
86
|
-
expect(
|
|
138
|
+
expression.month = 2
|
|
139
|
+
expect(expression.month).to eq([2])
|
|
87
140
|
|
|
88
|
-
|
|
89
|
-
expect(
|
|
141
|
+
expression.month = nil
|
|
142
|
+
expect(expression.month).to eq(nil)
|
|
90
143
|
|
|
91
|
-
|
|
92
|
-
expect(
|
|
144
|
+
expression.month = '3'
|
|
145
|
+
expect(expression.month).to eq([3])
|
|
93
146
|
end
|
|
94
147
|
end
|
|
95
148
|
|
|
96
149
|
describe 'repeat_year' do
|
|
97
150
|
it '[]' do
|
|
98
|
-
expect(
|
|
151
|
+
expect(expression.year).to eq([1990])
|
|
99
152
|
end
|
|
100
153
|
|
|
101
154
|
it '[]=' do
|
|
102
|
-
|
|
103
|
-
expect(
|
|
155
|
+
expression.year = 1994
|
|
156
|
+
expect(expression.year).to eq([1994])
|
|
104
157
|
end
|
|
105
158
|
|
|
106
159
|
it 'sanitizes' do
|
|
107
|
-
|
|
108
|
-
expect(
|
|
160
|
+
expression.year = 1992
|
|
161
|
+
expect(expression.year).to eq([1992])
|
|
109
162
|
|
|
110
|
-
|
|
111
|
-
expect(
|
|
163
|
+
expression.year = nil
|
|
164
|
+
expect(expression.year).to eq(nil)
|
|
112
165
|
|
|
113
|
-
|
|
114
|
-
expect(
|
|
166
|
+
expression.year = '2001'
|
|
167
|
+
expect(expression.year).to eq([2001])
|
|
115
168
|
end
|
|
116
169
|
end
|
|
117
170
|
|
|
118
171
|
describe 'repeat_weekday' do
|
|
119
172
|
it '[]' do
|
|
120
|
-
expect(
|
|
173
|
+
expect(expression.weekday).to eq([0])
|
|
121
174
|
end
|
|
122
175
|
|
|
123
176
|
it '[]=' do
|
|
124
|
-
|
|
125
|
-
expect(
|
|
177
|
+
expression.weekday = 4
|
|
178
|
+
expect(expression.weekday).to eq([4])
|
|
126
179
|
end
|
|
127
180
|
|
|
128
181
|
it 'sanitizes' do
|
|
129
|
-
|
|
130
|
-
expect(
|
|
182
|
+
expression.weekday = 2
|
|
183
|
+
expect(expression.weekday).to eq([2])
|
|
131
184
|
|
|
132
|
-
|
|
133
|
-
expect(
|
|
185
|
+
expression.weekday = nil
|
|
186
|
+
expect(expression.weekday).to eq(nil)
|
|
134
187
|
|
|
135
|
-
|
|
136
|
-
expect(
|
|
188
|
+
expression.weekday = '3'
|
|
189
|
+
expect(expression.weekday).to eq([3])
|
|
137
190
|
end
|
|
138
191
|
|
|
139
192
|
it 'should accept non-nth weekday expression' do
|
|
140
|
-
|
|
141
|
-
expect(
|
|
193
|
+
expression.weekday = '1'
|
|
194
|
+
expect(expression.weekday).to eq([1])
|
|
142
195
|
end
|
|
143
196
|
|
|
144
197
|
it 'should accept nth weekday expression' do
|
|
145
|
-
|
|
146
|
-
expect(
|
|
198
|
+
expression.weekday = '1#3'
|
|
199
|
+
expect(expression.weekday).to eq([{ 1 => [3] }])
|
|
147
200
|
end
|
|
148
201
|
|
|
149
202
|
it 'should accept last weekday expression' do
|
|
150
|
-
|
|
151
|
-
expect(
|
|
203
|
+
expression.weekday = '1L'
|
|
204
|
+
expect(expression.weekday).to eq([{ 1 => [-1] }])
|
|
152
205
|
end
|
|
153
206
|
end
|
|
154
207
|
end
|
|
@@ -18,6 +18,11 @@ describe ::IceCubeCron::RuleBuilder do
|
|
|
18
18
|
expect(rule_builder.build_rule(expression)).to be_a(IceCube::WeeklyRule)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
it 'monthly (last week day of month)' do
|
|
22
|
+
expression.weekday = '2L'
|
|
23
|
+
expect(rule_builder.build_rule(expression)).to be_a(IceCube::MonthlyRule)
|
|
24
|
+
end
|
|
25
|
+
|
|
21
26
|
it 'yearly' do
|
|
22
27
|
expression.month = 2
|
|
23
28
|
expect(rule_builder.build_rule(expression)).to be_a(IceCube::YearlyRule)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ice_cube_cron
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Nichols
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-10-
|
|
11
|
+
date: 2015-10-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ice_cube
|
|
@@ -103,6 +103,7 @@ extensions: []
|
|
|
103
103
|
extra_rdoc_files: []
|
|
104
104
|
files:
|
|
105
105
|
- ".gitignore"
|
|
106
|
+
- ".rdoc_options"
|
|
106
107
|
- ".rspec"
|
|
107
108
|
- ".rubocop.yml"
|
|
108
109
|
- Gemfile
|
|
@@ -115,9 +116,12 @@ files:
|
|
|
115
116
|
- lib/ice_cube_cron/base.rb
|
|
116
117
|
- lib/ice_cube_cron/expression_parser.rb
|
|
117
118
|
- lib/ice_cube_cron/extension.rb
|
|
119
|
+
- lib/ice_cube_cron/parser_attribute.rb
|
|
118
120
|
- lib/ice_cube_cron/rule_builder.rb
|
|
119
121
|
- lib/ice_cube_cron/util.rb
|
|
120
122
|
- lib/ice_cube_cron/version.rb
|
|
123
|
+
- lib/ice_cube_ext/validated_rule.rb
|
|
124
|
+
- lib/ice_cube_ext/validations/year.rb
|
|
121
125
|
- spec/lib/ice_cube_cron/base_spec.rb
|
|
122
126
|
- spec/lib/ice_cube_cron/expression_parser_spec.rb
|
|
123
127
|
- spec/lib/ice_cube_cron/rule_builder_spec.rb
|