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 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: