when-cron 1.0.1 → 1.0.2
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/README.md +5 -2
- data/lib/when-cron/cron/cron.rb +19 -18
- data/lib/when-cron/cron/cron_part.rb +30 -1
- data/lib/when-cron/cron/validator.rb +112 -0
- data/spec/lib/when/cron/cron_part_spec.rb +15 -0
- data/spec/lib/when/cron/cron_spec.rb +26 -0
- data/spec/lib/when/cron/validator_spec.rb +108 -0
- data/spec/spec_helper.rb +0 -3
- data/when-cron.gemspec +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 420cf2151fc72d5f0b8826761b8b5f0a826539d0
|
4
|
+
data.tar.gz: 43452faf5af725c4c9b6e73a123beea17ac51285
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9b1fb00c0b8239626e911b6d438eb97573571825977f05d910a15d7b1ac0e56d6fe6f8baf77fc1ea2fab95af4a390c1a821893b4b47a254d08f68f4df8710e7
|
7
|
+
data.tar.gz: 8c230d9008b79afc09e9d1a48d36fc853a644a3b9bb031498ccd2f533fdbcfe744180b879027d8fddbb7bea132ca98bff082dbfb098b358341c9cf44c2c7b303
|
data/README.md
CHANGED
@@ -22,11 +22,14 @@ Compare to anything that has an interface like Ruby's Time class with ==.
|
|
22
22
|
|
23
23
|
```When::Cron.new('* * * * *') == Time.now # => true```
|
24
24
|
|
25
|
-
|
25
|
+
Numbers, *, and abbreviations (SUN, JAN, etc) are supported for values.
|
26
|
+
|
27
|
+
, - and / are supported as operators.
|
26
28
|
|
27
29
|
```When::Cron.valid?('a b c d e') # => false```
|
30
|
+
```When::Cron.valid('a b c d e') # => nil```
|
28
31
|
|
29
|
-
When::Cron will
|
32
|
+
When::Cron will only validate your string when specifically asked. This allows faster analysis of previously validated strings, but might lead to silent failures for invalid strings.
|
30
33
|
|
31
34
|
```When::Cron.new('100 * * * *') == Time.now # => false```
|
32
35
|
|
data/lib/when-cron/cron/cron.rb
CHANGED
@@ -1,35 +1,36 @@
|
|
1
1
|
module When
|
2
2
|
class Cron
|
3
3
|
def self.valid?(cron)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
true
|
4
|
+
Validator.valid?(cron)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.valid(cron)
|
8
|
+
new(cron) if valid?(cron)
|
10
9
|
end
|
11
10
|
|
12
11
|
def initialize(cron)
|
13
|
-
|
12
|
+
@cron = cron
|
14
13
|
end
|
15
14
|
|
16
15
|
def ==(time)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
@parsed ||= parse(@cron)
|
17
|
+
|
18
|
+
@minute == time.min &&
|
19
|
+
@hour == time.hour &&
|
20
|
+
@day == time.day &&
|
21
|
+
@month == time.month &&
|
22
|
+
@wday == time.wday
|
24
23
|
end
|
25
24
|
|
25
|
+
private
|
26
|
+
|
26
27
|
def parse(string)
|
27
28
|
strings = string.split(' ')
|
28
29
|
@minute = CronPart.new(strings[0])
|
29
|
-
@hour
|
30
|
-
@day
|
31
|
-
@month
|
32
|
-
@wday
|
30
|
+
@hour = CronPart.new(strings[1])
|
31
|
+
@day = CronPart.new(strings[2])
|
32
|
+
@month = CronPart.new(strings[3])
|
33
|
+
@wday = CronPart.new(strings[4])
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -2,11 +2,36 @@ module When
|
|
2
2
|
class CronPart
|
3
3
|
class InvalidString < StandardError; end
|
4
4
|
|
5
|
+
REMAP = {
|
6
|
+
'SUN' => '0',
|
7
|
+
'MON' => '1',
|
8
|
+
'TUE' => '2',
|
9
|
+
'WED' => '3',
|
10
|
+
'THU' => '4',
|
11
|
+
'FRI' => '5',
|
12
|
+
'SAT' => '6',
|
13
|
+
|
14
|
+
'JAN' => '1',
|
15
|
+
'FEB' => '2',
|
16
|
+
'MAR' => '3',
|
17
|
+
'APR' => '4',
|
18
|
+
'MAY' => '5',
|
19
|
+
'JUN' => '6',
|
20
|
+
'JUL' => '7',
|
21
|
+
'AUG' => '8',
|
22
|
+
'SEP' => '9',
|
23
|
+
'OCT' => '10',
|
24
|
+
'NOV' => '11',
|
25
|
+
'DEC' => '12',
|
26
|
+
}
|
27
|
+
|
5
28
|
def initialize(cron_part)
|
29
|
+
@cron_part = cron_part
|
6
30
|
@part = parse(cron_part)
|
7
31
|
end
|
8
32
|
|
9
33
|
def ==(int)
|
34
|
+
@part ||= parse(@cron_part)
|
10
35
|
@part == int
|
11
36
|
end
|
12
37
|
|
@@ -22,10 +47,14 @@ module When
|
|
22
47
|
elsif cron_part == '*'
|
23
48
|
Wildcard.new
|
24
49
|
else
|
25
|
-
|
50
|
+
to_int(cron_part)
|
26
51
|
end
|
27
52
|
end
|
28
53
|
|
54
|
+
def to_int(cron_part)
|
55
|
+
to_valid_int(REMAP[cron_part.upcase] || cron_part)
|
56
|
+
end
|
57
|
+
|
29
58
|
def to_valid_int(cron_part)
|
30
59
|
int = cron_part.to_i
|
31
60
|
if int.to_s == cron_part
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module When
|
2
|
+
class Cron
|
3
|
+
class Validator
|
4
|
+
MONTHS = {
|
5
|
+
'JAN' => '1',
|
6
|
+
'FEB' => '2',
|
7
|
+
'MAR' => '3',
|
8
|
+
'APR' => '4',
|
9
|
+
'MAY' => '5',
|
10
|
+
'JUN' => '6',
|
11
|
+
'JUL' => '7',
|
12
|
+
'AUG' => '8',
|
13
|
+
'SEP' => '9',
|
14
|
+
'OCT' => '10',
|
15
|
+
'NOV' => '11',
|
16
|
+
'DEC' => '12',
|
17
|
+
}
|
18
|
+
|
19
|
+
WDAYS = {
|
20
|
+
'SUN' => '0',
|
21
|
+
'MON' => '1',
|
22
|
+
'TUE' => '2',
|
23
|
+
'WED' => '3',
|
24
|
+
'THU' => '4',
|
25
|
+
'FRI' => '5',
|
26
|
+
'SAT' => '6',
|
27
|
+
}
|
28
|
+
|
29
|
+
NOT_BASIC_CHARS = /[^\d,\/\*\-]/
|
30
|
+
NOT_BASIC_OR_LETTERS = /[^\d,\/\*\-a-zA-Z]/
|
31
|
+
|
32
|
+
def self.valid?(cron)
|
33
|
+
v = new(cron)
|
34
|
+
v.correct_number_of_parts? &&
|
35
|
+
v.min_correct? &&
|
36
|
+
v.hour_correct? &&
|
37
|
+
v.day_correct? &&
|
38
|
+
v.month_correct? &&
|
39
|
+
v.wday_correct?
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :cron
|
43
|
+
|
44
|
+
def initialize(cron)
|
45
|
+
@cron = cron
|
46
|
+
end
|
47
|
+
|
48
|
+
def parts
|
49
|
+
@parts ||= cron.split(' ')
|
50
|
+
end
|
51
|
+
|
52
|
+
def min
|
53
|
+
parts[0]
|
54
|
+
end
|
55
|
+
|
56
|
+
def hour
|
57
|
+
parts[1]
|
58
|
+
end
|
59
|
+
|
60
|
+
def day
|
61
|
+
parts[2]
|
62
|
+
end
|
63
|
+
|
64
|
+
def month
|
65
|
+
parts[3]
|
66
|
+
end
|
67
|
+
|
68
|
+
def wday
|
69
|
+
parts[4]
|
70
|
+
end
|
71
|
+
|
72
|
+
def correct_number_of_parts?
|
73
|
+
cron.split(' ').count == 5
|
74
|
+
end
|
75
|
+
|
76
|
+
def min_correct?
|
77
|
+
correct_range?(min, 0..59) &&
|
78
|
+
!(min =~ NOT_BASIC_CHARS)
|
79
|
+
end
|
80
|
+
|
81
|
+
def hour_correct?
|
82
|
+
correct_range?(hour, 0..23) &&
|
83
|
+
!(hour =~ NOT_BASIC_CHARS)
|
84
|
+
end
|
85
|
+
|
86
|
+
def day_correct?
|
87
|
+
correct_range?(day, 1..31) &&
|
88
|
+
!(day =~ NOT_BASIC_CHARS)
|
89
|
+
end
|
90
|
+
|
91
|
+
def month_correct?
|
92
|
+
correct_range?(month, 1..12) &&
|
93
|
+
month.scan(/[a-zA-Z]+/).all? { |w| MONTHS[w.upcase] } &&
|
94
|
+
!(month =~ NOT_BASIC_OR_LETTERS)
|
95
|
+
end
|
96
|
+
|
97
|
+
def wday_correct?
|
98
|
+
correct_range?(wday, 0..6) &&
|
99
|
+
wday.scan(/[a-zA-Z]+/).all? { |w| WDAYS[w.upcase] } &&
|
100
|
+
!(wday =~ NOT_BASIC_OR_LETTERS)
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def correct_range?(part, range)
|
106
|
+
part.scan(/\d+/).all? do |digits|
|
107
|
+
range === digits.to_i
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -143,4 +143,19 @@ describe CronPart do
|
|
143
143
|
expect(cron_part == 8).to eq false
|
144
144
|
end
|
145
145
|
end
|
146
|
+
|
147
|
+
context 'abbreviations' do
|
148
|
+
CronPart::REMAP.each do |abbr, val|
|
149
|
+
cron_part = CronPart.new(abbr)
|
150
|
+
|
151
|
+
it "returns true for #{abbr} => #{val}" do
|
152
|
+
expect(cron_part == val.to_i).to eq true
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'returns false for #{abbr} => #{val} +/- 1' do
|
156
|
+
expect(cron_part == val.to_i + 1).to eq false
|
157
|
+
expect(cron_part == val.to_i - 1).to eq false
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
146
161
|
end
|
@@ -14,6 +14,20 @@ describe Cron do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
describe '.valid' do
|
18
|
+
context 'a valid cron string is given' do
|
19
|
+
it 'returns a new cron object' do
|
20
|
+
expect(Cron.valid('* * * * *')).to be_kind_of Cron
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'an invalid cron string is given' do
|
25
|
+
it 'returns nil' do
|
26
|
+
expect(Cron.valid('* * * * * *')).to be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
17
31
|
describe '#==' do
|
18
32
|
context 'simple cron' do
|
19
33
|
let(:cron) { Cron.new('30 12 15 6 6') }
|
@@ -36,5 +50,17 @@ describe Cron do
|
|
36
50
|
expect(cron == now - 3600).to eq false
|
37
51
|
end
|
38
52
|
end
|
53
|
+
|
54
|
+
context 'abbreviations' do
|
55
|
+
let(:cron) { Cron.new('* * * JUN SAT')}
|
56
|
+
|
57
|
+
it 'returns true for now' do
|
58
|
+
expect(cron == now).to eq true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns false for a day earlier' do
|
62
|
+
expect(cron == now - 3600 * 24).to eq false
|
63
|
+
end
|
64
|
+
end
|
39
65
|
end
|
40
66
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include When
|
3
|
+
|
4
|
+
describe Cron::Validator do
|
5
|
+
describe '.valid?' do
|
6
|
+
context 'number of parts' do
|
7
|
+
it 'returns true with 5 space separated parts' do
|
8
|
+
expect(Cron::Validator.valid?('* * * * *')).to be true
|
9
|
+
end
|
10
|
+
|
11
|
+
[ 1, 3, 6, 9 ].each do |i|
|
12
|
+
cron = (['*'] * i).join(' ')
|
13
|
+
it "returns false for '#{cron}'" do
|
14
|
+
expect(Cron::Validator.valid?(cron)).to be false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
context 'minutes' do
|
19
|
+
[ '0', '1', '59' ].each do |min|
|
20
|
+
it "returns true when minute is #{min}" do
|
21
|
+
expect(Cron::Validator.valid?("#{min} * * * *")).to be true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
[ '60', '134', '75' ].each do |min|
|
26
|
+
it "returns false when minute is #{min}" do
|
27
|
+
expect(Cron::Validator.valid?("#{min} * * * *")).to be false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'hours' do
|
33
|
+
[ '0', '5', '23' ].each do |hour|
|
34
|
+
it "returns true when hour is #{hour}" do
|
35
|
+
expect(Cron::Validator.valid?("* #{hour} * * *")).to be true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
[ '24', '50', '999' ].each do |hour|
|
40
|
+
it "returns false when hour is #{hour}" do
|
41
|
+
expect(Cron::Validator.valid?("* #{hour} * * *")).to be false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'days' do
|
47
|
+
[ '1', '5', '31' ].each do |day|
|
48
|
+
it "returns true when day is #{day}" do
|
49
|
+
expect(Cron::Validator.valid?("* * #{day} * *")).to be true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
[ '0', '32', '467' ].each do |day|
|
54
|
+
it "returns false when day is #{day}" do
|
55
|
+
expect(Cron::Validator.valid?("* * #{day} * *")).to be false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'months' do
|
61
|
+
[ '1', '5', '12', 'JAN', 'jan', 'AUG', 'DEC' ].each do |month|
|
62
|
+
it "returns true when month is #{month}" do
|
63
|
+
expect(Cron::Validator.valid?("* * * #{month} *")).to be true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
[ '0', '32', '467', 'MEY', 'JIN' ].each do |month|
|
68
|
+
it "returns false when month is #{month}" do
|
69
|
+
expect(Cron::Validator.valid?("* * * #{month} *")).to be false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'wdays' do
|
75
|
+
[ '0', '5', '6', 'Mon', 'TUE', 'thu', 'saT' ].each do |wday|
|
76
|
+
it "returns true when wday is #{wday}" do
|
77
|
+
expect(Cron::Validator.valid?("* * * * #{wday}")).to be true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
[ '7', '32', '467', 'MIN', 'TUW' ].each do |wday|
|
82
|
+
it "returns false when wday is #{wday}" do
|
83
|
+
expect(Cron::Validator.valid?("* * * * #{wday}")).to be false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'characters' do
|
89
|
+
[ '!', '&', '[', '\\' ].each do |char|
|
90
|
+
5.times do |i|
|
91
|
+
cron = [ '*', '*', '*', '*' ].insert(i, char).join(' ')
|
92
|
+
it "returns false for #{cron}" do
|
93
|
+
expect(Cron::Validator.valid?(cron)).to eq false
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
[ '-', '*', '/', ',' ].each do |char|
|
99
|
+
5.times do |i|
|
100
|
+
cron = [ '*', '*', '*', '*' ].insert(i, char).join(' ')
|
101
|
+
it "returns true for #{cron}" do
|
102
|
+
expect(Cron::Validator.valid?(cron)).to eq true
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/when-cron.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "when-cron"
|
7
|
-
spec.version = '1.0.
|
7
|
+
spec.version = '1.0.2'
|
8
8
|
spec.authors = ["TH"]
|
9
9
|
spec.email = ["tylerhartland7@gmail.com"]
|
10
10
|
spec.description = %q{A basic cron implementation.}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: when-cron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TH
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -102,12 +102,14 @@ files:
|
|
102
102
|
- lib/when-cron/cron/cron_interval.rb
|
103
103
|
- lib/when-cron/cron/cron_part.rb
|
104
104
|
- lib/when-cron/cron/cron_range.rb
|
105
|
+
- lib/when-cron/cron/validator.rb
|
105
106
|
- lib/when-cron/cron/wildcard.rb
|
106
107
|
- spec/lib/when/cron/cron_array_spec.rb
|
107
108
|
- spec/lib/when/cron/cron_interval_spec.rb
|
108
109
|
- spec/lib/when/cron/cron_part_spec.rb
|
109
110
|
- spec/lib/when/cron/cron_range_spec.rb
|
110
111
|
- spec/lib/when/cron/cron_spec.rb
|
112
|
+
- spec/lib/when/cron/validator_spec.rb
|
111
113
|
- spec/lib/when/cron/wildcard_spec.rb
|
112
114
|
- spec/lib/when_spec.rb
|
113
115
|
- spec/spec_helper.rb
|
@@ -142,7 +144,7 @@ test_files:
|
|
142
144
|
- spec/lib/when/cron/cron_part_spec.rb
|
143
145
|
- spec/lib/when/cron/cron_range_spec.rb
|
144
146
|
- spec/lib/when/cron/cron_spec.rb
|
147
|
+
- spec/lib/when/cron/validator_spec.rb
|
145
148
|
- spec/lib/when/cron/wildcard_spec.rb
|
146
149
|
- spec/lib/when_spec.rb
|
147
150
|
- spec/spec_helper.rb
|
148
|
-
has_rdoc:
|