parse-cron 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NDU3MTY0MGQ1YWE1YTlmNjVhODMzZDk2MjgxMzFiMDNhOGE2OWNmNA==
5
+ data.tar.gz: !binary |-
6
+ OGQ0ZmJlMTZlNTU0MDk1YmY4YjFhMzBhNWE4YTM2N2VjNDg2Yjc3MA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ Mzg4N2NiZTNhNWI2NDcwYTEwNTJkMGU5NDI3ZGRmMmVmOTkwY2E4ZGZmOGY5
10
+ MjQ0NDI2YTA5N2Y2YWUzNmRlZTNjOGM3NmUyMmIzY2YxOWRlZWJiMGIwYmQ1
11
+ YzE5YmIzMDc0NGM4ZTYzZWJiYWQ3MWM1NTA4NWIzN2U4MGQ3NDM=
12
+ data.tar.gz: !binary |-
13
+ ODRhNDM0ZTUyOTBlN2ZhNzkzNjc0NzdhYTA2NTMzY2ZjZTQ0MTVjZTE4ZDM4
14
+ YTBjNWQ2MzFkMmFmYjk0YjdmZjA3NzlmZWUxYzIyNGQyNWRhNDUyMDk4NGY4
15
+ NDQzNTMxMThlMDllYzgzODJjMmNkYTkxZDc1MTFiMDk3OTg0OTc=
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  .bundle
4
4
  Gemfile.lock
5
5
  pkg/*
6
+ .rvmrc
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.8.7"
4
+ - "1.9.3"
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "ZenTest", "4.6.0"
7
+ gem "rake"
data/License ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (C) 2013 Michael Siebert <siebertm85@googlemail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without restriction,
6
+ including without limitation the rights to use, copy, modify,
7
+ merge, publish, distribute, sublicense, and/or sell copies of
8
+ the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall
12
+ be included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ # parse-cron - parse crontab syntax & determine next scheduled run [![Build Status](https://travis-ci.org/siebertm/parse-cron.png)](https://travis-ci.org/siebertm/parse-cron)
2
+
3
+ The goal of this gem is to parse a crontab timing specification and determine when the
4
+ job should be run. It is not a scheduler, it does not run the jobs.
5
+
6
+ ## API example
7
+
8
+ ```
9
+ cron_parser = CronParser.new('30 * * * *')
10
+
11
+ # Comming times
12
+ next_comming_time = cron_parser.next(Time.now)
13
+
14
+ # Times that have been
15
+ most_resently_time = cron_parser.last(Time.now)
16
+ ```
17
+
@@ -1,4 +1,5 @@
1
1
  require 'set'
2
+ require 'date'
2
3
  #
3
4
  # Parses cron expressions and computes the next occurence of the "job"
4
5
  #
@@ -28,18 +29,18 @@ class CronParser
28
29
  end
29
30
 
30
31
  SYMBOLS = {
31
- "jan" => "0",
32
- "feb" => "1",
33
- "mar" => "2",
34
- "apr" => "3",
35
- "may" => "4",
36
- "jun" => "5",
37
- "jul" => "6",
38
- "aug" => "7",
39
- "sep" => "8",
40
- "oct" => "9",
41
- "nov" => "10",
42
- "dec" => "11",
32
+ "jan" => "1",
33
+ "feb" => "2",
34
+ "mar" => "3",
35
+ "apr" => "4",
36
+ "may" => "5",
37
+ "jun" => "6",
38
+ "jul" => "7",
39
+ "aug" => "8",
40
+ "sep" => "9",
41
+ "oct" => "10",
42
+ "nov" => "11",
43
+ "dec" => "12",
43
44
 
44
45
  "sun" => "0",
45
46
  "mon" => "1",
@@ -51,14 +52,34 @@ class CronParser
51
52
  }
52
53
 
53
54
  def initialize(source,time_source = Time)
54
- @source = source
55
+ @source = interpret_vixieisms(source)
55
56
  @time_source = time_source
57
+ validate_source
58
+ end
59
+
60
+ def interpret_vixieisms(spec)
61
+ case spec
62
+ when '@reboot'
63
+ raise ArgumentError, "Can't predict last/next run of @reboot"
64
+ when '@yearly', '@annually'
65
+ '0 0 1 1 *'
66
+ when '@monthly'
67
+ '0 0 1 * *'
68
+ when '@weekly'
69
+ '0 0 * * 0'
70
+ when '@daily', '@midnight'
71
+ '0 0 * * *'
72
+ when '@hourly'
73
+ '0 * * * *'
74
+ else
75
+ spec
76
+ end
56
77
  end
57
78
 
58
79
 
59
80
  # returns the next occurence after the given date
60
81
  def next(now = @time_source.now)
61
- t = InternalTime.new(now,@time_source)
82
+ t = InternalTime.new(now, @time_source)
62
83
 
63
84
  unless time_specs[:month][0].include?(t.month)
64
85
  nudge_month(t)
@@ -114,25 +135,25 @@ class CronParser
114
135
  else
115
136
  if SUBELEMENT_REGEX === subel
116
137
  if $5 # with range
117
- stepped_range($1.to_i..($3.to_i + 1), $5.to_i)
138
+ stepped_range($1.to_i..$3.to_i, $5.to_i)
118
139
  elsif $3 # range without step
119
- stepped_range($1.to_i..($3.to_i + 1), 1)
140
+ stepped_range($1.to_i..$3.to_i, 1)
120
141
  else # just a numeric
121
142
  [$1.to_i]
122
143
  end
123
144
  else
124
- raise "Bad Vixie-style specification #{subel}"
145
+ raise ArgumentError, "Bad Vixie-style specification #{subel}"
125
146
  end
126
147
  end
127
148
  end.flatten.sort
128
149
 
129
- [Set.new(values), values]
150
+ [Set.new(values), values, elem]
130
151
  end
131
152
 
132
153
 
133
154
  protected
134
155
 
135
- # returns a list of days which do both match time_spec[:dom] and time_spec[:dow]
156
+ # returns a list of days which do both match time_spec[:dom] or time_spec[:dow]
136
157
  def interpolate_weekdays(year, month)
137
158
  @_interpolate_weekdays_cache ||= {}
138
159
  @_interpolate_weekdays_cache["#{year}-#{month}"] ||= interpolate_weekdays_without_cache(year, month)
@@ -140,12 +161,21 @@ class CronParser
140
161
 
141
162
  def interpolate_weekdays_without_cache(year, month)
142
163
  t = Date.new(year, month, 1)
143
- valid_mday = time_specs[:dom][0]
144
- valid_wday = time_specs[:dow][0]
164
+ valid_mday, _, mday_field = time_specs[:dom]
165
+ valid_wday, _, wday_field = time_specs[:dow]
166
+
167
+ # Careful, if both DOW and DOM fields are non-wildcard,
168
+ # then we only need to match *one* for cron to run the job:
169
+ if not (mday_field == '*' and wday_field == '*')
170
+ valid_mday = [] if mday_field == '*'
171
+ valid_wday = [] if wday_field == '*'
172
+ end
173
+ # Careful: crontabs may use either 0 or 7 for Sunday:
174
+ valid_wday << 0 if valid_wday.include?(7)
145
175
 
146
176
  result = []
147
177
  while t.month == month
148
- result << t.mday if valid_mday.include?(t.mday) && valid_wday.include?(t.wday)
178
+ result << t.mday if valid_mday.include?(t.mday) || valid_wday.include?(t.wday)
149
179
  t = t.succ
150
180
  end
151
181
 
@@ -211,7 +241,7 @@ class CronParser
211
241
  end
212
242
 
213
243
  def substitute_parse_symbols(str)
214
- SYMBOLS.inject(str) do |s, (symbol, replacement)|
244
+ SYMBOLS.inject(str.downcase) do |s, (symbol, replacement)|
215
245
  s.gsub(symbol, replacement)
216
246
  end
217
247
  end
@@ -237,4 +267,14 @@ class CronParser
237
267
  allowed.sort.reverse.find { |val| val < current }
238
268
  end
239
269
  end
270
+
271
+ def validate_source
272
+ unless @source.respond_to?(:split)
273
+ raise ArgumentError, 'not a valid cronline'
274
+ end
275
+ source_length = @source.split(/\s+/).length
276
+ unless source_length >= 5 && source_length <= 6
277
+ raise ArgumentError, 'not a valid cronline'
278
+ end
279
+ end
240
280
  end
@@ -1,5 +1,5 @@
1
1
  module Parse
2
2
  module Cron
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
  end
@@ -1,7 +1,7 @@
1
1
  require "time"
2
2
  require "./spec/spec_helper"
3
3
  require "cron_parser"
4
- require "time"
4
+ require "date"
5
5
 
6
6
  def parse_date(str)
7
7
  dt = DateTime.strptime(str, "%Y-%m-%d %H:%M")
@@ -10,38 +10,73 @@ end
10
10
 
11
11
  describe "CronParser#parse_element" do
12
12
  [
13
- ["*", 0..60, (0..60).to_a],
14
- ["*/10", 0..60, [0, 10, 20, 30, 40, 50]],
15
- ["10", 0..60, [10]],
16
- ["10,30", 0..60, [10, 30]],
17
- ["10-15", 0..60, [10, 11, 12, 13, 14, 15]],
18
- ["10-40/10", 0..60, [10, 20, 30, 40]],
13
+ ["*", 0..59, (0..59).to_a],
14
+ ["*/10", 0..59, [0, 10, 20, 30, 40, 50]],
15
+ ["10", 0..59, [10]],
16
+ ["10,30", 0..59, [10, 30]],
17
+ ["10-15", 0..59, [10, 11, 12, 13, 14, 15]],
18
+ ["10-40/10", 0..59, [10, 20, 30, 40]],
19
19
  ].each do |element, range, expected|
20
20
  it "should return #{expected} for '#{element}' when range is #{range}" do
21
- parser = CronParser.new('')
22
- parser.parse_element(element, range) == expected
21
+ parser = CronParser.new('* * * * *')
22
+ parser.parse_element(element, range).first.to_a.sort.should == expected.sort
23
23
  end
24
24
  end
25
25
  end
26
26
 
27
27
  describe "CronParser#next" do
28
28
  [
29
- ["* * * * *", "2011-08-15 12:00", "2011-08-15 12:01"],
30
- ["* * * * *", "2011-08-15 02:25", "2011-08-15 02:26"],
31
- ["* * * * *", "2011-08-15 02:59", "2011-08-15 03:00"],
32
- ["*/15 * * * *", "2011-08-15 02:02", "2011-08-15 02:15"],
33
- ["*/15,25 * * * *", "2011-08-15 02:15", "2011-08-15 02:25"],
34
- ["30 3,6,9 * * *", "2011-08-15 02:15", "2011-08-15 03:30"],
35
- ["30 9 * * *", "2011-08-15 10:15", "2011-08-16 09:30"],
36
- ["30 9 * * *", "2011-08-31 10:15", "2011-09-01 09:30"],
37
- ["30 9 * * *", "2011-09-30 10:15", "2011-10-01 09:30"],
38
- ["0 9 * * *", "2011-12-31 10:15", "2012-01-01 09:00"],
39
- ["* * 12 * *", "2010-04-15 10:15", "2010-05-12 00:00"],
40
- ["* * * * 1,3", "2010-04-15 10:15", "2010-04-19 00:00"],
41
- ["0 0 1 1 *", "2010-04-15 10:15", "2011-01-01 00:00"],
42
- ["0 0 * * 1", "2011-08-01 00:00", "2011-08-08 00:00"],
43
- ["0 0 * * 1", "2011-07-25 00:00", "2011-08-01 00:00"],
44
- ["45 23 7 3 *", "2011-01-01 00:00", "2011-03-07 23:45"],
29
+ ["* * * * *", "2011-08-15 12:00", "2011-08-15 12:01"],
30
+ ["* * * * *", "2011-08-15 02:25", "2011-08-15 02:26"],
31
+ ["* * * * *", "2011-08-15 02:59", "2011-08-15 03:00"],
32
+ ["*/15 * * * *", "2011-08-15 02:02", "2011-08-15 02:15"],
33
+ ["*/15,25 * * * *", "2011-08-15 02:15", "2011-08-15 02:25"],
34
+ ["30 3,6,9 * * *", "2011-08-15 02:15", "2011-08-15 03:30"],
35
+ ["30 9 * * *", "2011-08-15 10:15", "2011-08-16 09:30"],
36
+ ["30 9 * * *", "2011-08-31 10:15", "2011-09-01 09:30"],
37
+ ["30 9 * * *", "2011-09-30 10:15", "2011-10-01 09:30"],
38
+ ["0 9 * * *", "2011-12-31 10:15", "2012-01-01 09:00"],
39
+ ["* * 12 * *", "2010-04-15 10:15", "2010-05-12 00:00"],
40
+ ["* * * * 1,3", "2010-04-15 10:15", "2010-04-19 00:00"],
41
+ ["* * * * MON,WED", "2010-04-15 10:15", "2010-04-19 00:00"],
42
+ ["0 0 1 1 *", "2010-04-15 10:15", "2011-01-01 00:00"],
43
+ ["0 0 * * 1", "2011-08-01 00:00", "2011-08-08 00:00"],
44
+ ["0 0 * * 1", "2011-07-25 00:00", "2011-08-01 00:00"],
45
+ ["45 23 7 3 *", "2011-01-01 00:00", "2011-03-07 23:45"],
46
+ ["0 0 1 jun *", "2013-05-14 11:20", "2013-06-01 00:00"],
47
+ ["0 0 1 may,jul *", "2013-05-14 15:00", "2013-07-01 00:00"],
48
+ ["0 0 1 MAY,JUL *", "2013-05-14 15:00", "2013-07-01 00:00"],
49
+ ["40 5 * * *", "2014-02-01 15:56", "2014-02-02 05:40"],
50
+ ["0 5 * * 1", "2014-02-01 15:56", "2014-02-03 05:00"],
51
+ ["10 8 15 * *", "2014-02-01 15:56", "2014-02-15 08:10"],
52
+ ["50 6 * * 1", "2014-02-01 15:56", "2014-02-03 06:50"],
53
+ ["1 2 * apr mOn", "2014-02-01 15:56", "2014-04-07 02:01"],
54
+ ["1 2 3 4 7", "2014-02-01 15:56", "2014-04-03 02:01"],
55
+ ["1 2 3 4 7", "2014-04-04 15:56", "2014-04-06 02:01"],
56
+ ["1-20/3 * * * *", "2014-02-01 15:56", "2014-02-01 16:01"],
57
+ ["1,2,3 * * * *", "2014-02-01 15:56", "2014-02-01 16:01"],
58
+ ["1-9,15-30 * * * *", "2014-02-01 15:56", "2014-02-01 16:01"],
59
+ ["1-9/3,15-30/4 * * * *", "2014-02-01 15:56", "2014-02-01 16:01"],
60
+ ["1 2 3 jan mon", "2014-02-01 15:56", "2015-01-03 02:01"],
61
+ ["1 2 3 4 mON", "2014-02-01 15:56", "2014-04-03 02:01"],
62
+ ["1 2 3 jan 5", "2014-02-01 15:56", "2015-01-02 02:01"],
63
+ ["@yearly", "2014-02-01 15:56", "2015-01-01 00:00"],
64
+ ["@annually", "2014-02-01 15:56", "2015-01-01 00:00"],
65
+ ["@monthly", "2014-02-01 15:56", "2014-03-01 00:00"],
66
+ ["@weekly", "2014-02-01 15:56", "2014-02-02 00:00"],
67
+ ["@daily", "2014-02-01 15:56", "2014-02-02 00:00"],
68
+ ["@midnight", "2014-02-01 15:56", "2014-02-02 00:00"],
69
+ ["@hourly", "2014-02-01 15:56", "2014-02-01 16:00"],
70
+ ["*/3 * * * *", "2014-02-01 15:56", "2014-02-01 15:57"],
71
+ ["0 5 * 2,3 *", "2014-02-01 15:56", "2014-02-02 05:00"],
72
+ ["15-59/15 * * * *", "2014-02-01 15:56", "2014-02-01 16:15"],
73
+ ["15-59/15 * * * *", "2014-02-01 15:00", "2014-02-01 15:15"],
74
+ ["15-59/15 * * * *", "2014-02-01 15:01", "2014-02-01 15:15"],
75
+ ["15-59/15 * * * *", "2014-02-01 15:16", "2014-02-01 15:30"],
76
+ ["15-59/15 * * * *", "2014-02-01 15:26", "2014-02-01 15:30"],
77
+ ["15-59/15 * * * *", "2014-02-01 15:36", "2014-02-01 15:45"],
78
+ ["15-59/15 * * * *", "2014-02-01 15:45", "2014-02-01 16:15"],
79
+ ["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 16:15"],
45
80
  ].each do |line, now, expected_next|
46
81
  it "should return #{expected_next} for '#{line}' when now is #{now}" do
47
82
  now = parse_date(now)
@@ -56,20 +91,55 @@ end
56
91
 
57
92
  describe "CronParser#last" do
58
93
  [
59
- ["* * * * *", "2011-08-15 12:00", "2011-08-15 11:59"],
60
- ["* * * * *", "2011-08-15 02:25", "2011-08-15 02:24"],
61
- ["* * * * *", "2011-08-15 03:00", "2011-08-15 02:59"],
62
- ["*/15 * * * *", "2011-08-15 02:02", "2011-08-15 02:00"],
63
- ["*/15,45 * * * *", "2011-08-15 02:55", "2011-08-15 02:45"],
64
- ["*/15,25 * * * *", "2011-08-15 02:35", "2011-08-15 02:30"],
65
- ["30 3,6,9 * * *", "2011-08-15 02:15", "2011-08-14 09:30"],
66
- ["30 9 * * *", "2011-08-15 10:15", "2011-08-15 09:30"],
67
- ["30 9 * * *", "2011-09-01 08:15", "2011-08-31 09:30"],
68
- ["30 9 * * *", "2011-10-01 08:15", "2011-09-30 09:30"],
69
- ["0 9 * * *", "2012-01-01 00:15", "2011-12-31 09:00"],
70
- ["* * 12 * *", "2010-04-15 10:15", "2010-04-12 23:59"],
71
- ["* * * * 1,3", "2010-04-15 10:15", "2010-04-14 23:59"],
72
- ["0 0 1 1 *", "2010-04-15 10:15", "2010-01-01 00:00"],
94
+ ["* * * * *", "2011-08-15 12:00", "2011-08-15 11:59"],
95
+ ["* * * * *", "2011-08-15 02:25", "2011-08-15 02:24"],
96
+ ["* * * * *", "2011-08-15 03:00", "2011-08-15 02:59"],
97
+ ["*/15 * * * *", "2011-08-15 02:02", "2011-08-15 02:00"],
98
+ ["*/15,45 * * * *", "2011-08-15 02:55", "2011-08-15 02:45"],
99
+ ["*/15,25 * * * *", "2011-08-15 02:35", "2011-08-15 02:30"],
100
+ ["30 3,6,9 * * *", "2011-08-15 02:15", "2011-08-14 09:30"],
101
+ ["30 9 * * *", "2011-08-15 10:15", "2011-08-15 09:30"],
102
+ ["30 9 * * *", "2011-09-01 08:15", "2011-08-31 09:30"],
103
+ ["30 9 * * *", "2011-10-01 08:15", "2011-09-30 09:30"],
104
+ ["0 9 * * *", "2012-01-01 00:15", "2011-12-31 09:00"],
105
+ ["* * 12 * *", "2010-04-15 10:15", "2010-04-12 23:59"],
106
+ ["* * * * 1,3", "2010-04-15 10:15", "2010-04-14 23:59"],
107
+ ["* * * * MON,WED", "2010-04-15 10:15", "2010-04-14 23:59"],
108
+ ["0 0 1 1 *", "2010-04-15 10:15", "2010-01-01 00:00"],
109
+ ["0 0 1 jun *", "2013-05-14 11:20", "2012-06-01 00:00"],
110
+ ["0 0 1 may,jul *", "2013-05-14 15:00", "2013-05-01 00:00"],
111
+ ["0 0 1 MAY,JUL *", "2013-05-14 15:00", "2013-05-01 00:00"],
112
+ ["40 5 * * *", "2014-02-01 15:56", "2014-02-01 05:40"],
113
+ ["0 5 * * 1", "2014-02-01 15:56", "2014-01-27 05:00"],
114
+ ["10 8 15 * *", "2014-02-01 15:56", "2014-01-15 08:10"],
115
+ ["50 6 * * 1", "2014-02-01 15:56", "2014-01-27 06:50"],
116
+ ["1 2 * apr mOn", "2014-02-01 15:56", "2013-04-29 02:01"],
117
+ ["1 2 3 4 7", "2014-02-01 15:56", "2013-04-28 02:01"],
118
+ ["1 2 3 4 7", "2014-04-04 15:56", "2014-04-03 02:01"],
119
+ ["1-20/3 * * * *", "2014-02-01 15:56", "2014-02-01 15:19"],
120
+ ["1,2,3 * * * *", "2014-02-01 15:56", "2014-02-01 15:03"],
121
+ ["1-9,15-30 * * * *", "2014-02-01 15:56", "2014-02-01 15:30"],
122
+ ["1-9/3,15-30/4 * * * *", "2014-02-01 15:56", "2014-02-01 15:27"],
123
+ ["1 2 3 jan mon", "2014-02-01 15:56", "2014-01-27 02:01"],
124
+ ["1 2 3 4 mON", "2014-02-01 15:56", "2013-04-29 02:01"],
125
+ ["1 2 3 jan 5", "2014-02-01 15:56", "2014-01-31 02:01"],
126
+ ["@yearly", "2014-02-01 15:56", "2014-01-01 00:00"],
127
+ ["@annually", "2014-02-01 15:56", "2014-01-01 00:00"],
128
+ ["@monthly", "2014-02-01 15:56", "2014-02-01 00:00"],
129
+ ["@weekly", "2014-02-01 15:56", "2014-01-26 00:00"],
130
+ ["@daily", "2014-02-01 15:56", "2014-02-01 00:00"],
131
+ ["@midnight", "2014-02-01 15:56", "2014-02-01 00:00"],
132
+ ["@hourly", "2014-02-01 15:56", "2014-02-01 15:00"],
133
+ ["*/3 * * * *", "2014-02-01 15:56", "2014-02-01 15:54"],
134
+ ["0 5 * 2,3 *", "2014-02-01 15:56", "2014-02-01 05:00"],
135
+ ["15-59/15 * * * *", "2014-02-01 15:56", "2014-02-01 15:45"],
136
+ ["15-59/15 * * * *", "2014-02-01 15:00", "2014-02-01 14:45"],
137
+ ["15-59/15 * * * *", "2014-02-01 15:01", "2014-02-01 14:45"],
138
+ ["15-59/15 * * * *", "2014-02-01 15:16", "2014-02-01 15:15"],
139
+ ["15-59/15 * * * *", "2014-02-01 15:26", "2014-02-01 15:15"],
140
+ ["15-59/15 * * * *", "2014-02-01 15:36", "2014-02-01 15:30"],
141
+ ["15-59/15 * * * *", "2014-02-01 15:45", "2014-02-01 15:30"],
142
+ ["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 15:45"],
73
143
  ].each do |line, now, expected_next|
74
144
  it "should return #{expected_next} for '#{line}' when now is #{now}" do
75
145
  now = parse_date(now)
@@ -82,6 +152,16 @@ describe "CronParser#last" do
82
152
  end
83
153
  end
84
154
 
155
+ describe "CronParser#new" do
156
+ it 'should not raise error when given a valid cronline' do
157
+ expect { CronParser.new('30 * * * *') }.not_to raise_error
158
+ end
159
+
160
+ it 'should raise error when given an invalid cronline' do
161
+ expect { CronParser.new('* * * *') }.to raise_error('not a valid cronline')
162
+ end
163
+ end
164
+
85
165
  describe "time source" do
86
166
  it "should use an alternate specified time source" do
87
167
  ExtendedTime = Class.new(Time)
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parse-cron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
5
- prerelease:
4
+ version: 0.1.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michael Siebert
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-07 00:00:00.000000000 Z
11
+ date: 2014-02-06 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rspec
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -36,8 +33,10 @@ extra_rdoc_files: []
36
33
  files:
37
34
  - .gitignore
38
35
  - .rspec
36
+ - .travis.yml
39
37
  - Gemfile
40
- - README
38
+ - License
39
+ - README.md
41
40
  - Rakefile
42
41
  - lib/cron_parser.rb
43
42
  - lib/parse-cron.rb
@@ -47,28 +46,25 @@ files:
47
46
  - spec/spec_helper.rb
48
47
  homepage: https://github.com/siebertm/parse-cron
49
48
  licenses: []
49
+ metadata: {}
50
50
  post_install_message:
51
51
  rdoc_options: []
52
52
  require_paths:
53
53
  - lib
54
54
  required_ruby_version: !ruby/object:Gem::Requirement
55
- none: false
56
55
  requirements:
57
56
  - - ! '>='
58
57
  - !ruby/object:Gem::Version
59
58
  version: '0'
60
59
  required_rubygems_version: !ruby/object:Gem::Requirement
61
- none: false
62
60
  requirements:
63
61
  - - ! '>='
64
62
  - !ruby/object:Gem::Version
65
63
  version: '0'
66
64
  requirements: []
67
65
  rubyforge_project: parse-cron
68
- rubygems_version: 1.8.23
66
+ rubygems_version: 2.1.11
69
67
  signing_key:
70
- specification_version: 3
68
+ specification_version: 4
71
69
  summary: Parses cron expressions and calculates the next occurence
72
- test_files:
73
- - spec/cron_parser_spec.rb
74
- - spec/spec_helper.rb
70
+ test_files: []
data/README DELETED
@@ -1,5 +0,0 @@
1
- # parse-cron - parse crontab syntax & determine next scheduled run
2
-
3
- The goal of this gem is to parse a crontab timing specification and determine when the
4
- job should be run. It is not a scheduler, it does not run the jobs.
5
-