when-cron 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7be791179d6810b1a235984131c4c440b13c945f
4
- data.tar.gz: 56b1bf74f137172458f068778a8ec123fa43f38a
3
+ metadata.gz: 420cf2151fc72d5f0b8826761b8b5f0a826539d0
4
+ data.tar.gz: 43452faf5af725c4c9b6e73a123beea17ac51285
5
5
  SHA512:
6
- metadata.gz: c2cf26e262f12206f73ed74be0c4c8cf5a0179ea74f28a82b116c19e5cdb95983b2735396aab3cc5dd989719ea6eef69794be9e28d393f6908cbb733a9121c3e
7
- data.tar.gz: 616f6a08f514dfd476880bce095335bcc4362ae6edfc82c6cf33aaa1b76c23a0a685f71709cbb15fcae15e3ba2c6fc1a80f0cca72ac239315062e1f15cb7abcf
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
- Only numbers or * are supported for values, only - , / are supported as operators.
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 allow nonsensical values (exa. 100 in the minute spot), but because the minute will never match, == will always return false.
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
 
@@ -1,35 +1,36 @@
1
1
  module When
2
2
  class Cron
3
3
  def self.valid?(cron)
4
- begin
5
- new(cron)
6
- rescue When::CronPart::InvalidString
7
- return false
8
- end
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
- parse(cron)
12
+ @cron = cron
14
13
  end
15
14
 
16
15
  def ==(time)
17
- matches = []
18
- matches << (@minute == time.min)
19
- matches << (@hour == time.hour)
20
- matches << (@day == time.day)
21
- matches << (@month == time.month)
22
- matches << (@wday == time.wday)
23
- matches.all?
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 = CronPart.new(strings[1])
30
- @day = CronPart.new(strings[2])
31
- @month = CronPart.new(strings[3])
32
- @wday = CronPart.new(strings[4])
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
- to_valid_int(cron_part)
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
@@ -1,8 +1,5 @@
1
1
  require 'when-cron'
2
2
 
3
3
  RSpec.configure do |config|
4
- config.run_all_when_everything_filtered = true
5
- config.filter_run :focus
6
-
7
4
  config.order = 'random'
8
5
  end
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.1'
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.1
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-03-24 00:00:00.000000000 Z
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: