parse-cron 0.1.2 → 0.1.4

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.
@@ -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
-