Skip to content

Commit db5c8b7

Browse files
committed
Support L in dom field
1 parent 268094a commit db5c8b7

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

lib/cron_parser.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,18 @@ def last(now = @time_source.now, num=1)
136136
end
137137

138138

139-
SUBELEMENT_REGEX = %r{^(\d+)(-(\d+)(/(\d+))?)?$}
140-
def parse_element(elem, allowed_range)
139+
SUBELEMENT_REGEX = %r{^(\d+|l)(-(\d+)(/(\d+))?)?$}
140+
def parse_element(elem, allowed_range, field_name = nil)
141141
values = elem.split(',').map do |subel|
142142
if subel =~ /^\*/
143143
step = subel.length > 1 ? subel[2..-1].to_i : 1
144144
stepped_range(allowed_range, step)
145145
else
146146
if SUBELEMENT_REGEX === subel
147+
if field_name != :dom && $1.include?('l')
148+
raise ArgumentError, "'L' specification is supported only for DOM field"
149+
end
150+
147151
if $5 # with range
148152
stepped_range($1.to_i..$3.to_i, $5.to_i)
149153
elsif $3 # range without step
@@ -191,6 +195,9 @@ def interpolate_weekdays_without_cache(year, month)
191195
# Careful: crontabs may use either 0 or 7 for Sunday:
192196
valid_wday << 0 if valid_wday.include?(7)
193197

198+
# L is converted to 0
199+
valid_mday << (t.next_month - 1).day if valid_mday.include?(0)
200+
194201
result = []
195202
while t.month == month
196203
result << t.mday if valid_mday.include?(t.mday) || valid_wday.include?(t.wday)
@@ -251,7 +258,7 @@ def time_specs
251258
{
252259
:minute => parse_element(tokens[0], 0..59), #minute
253260
:hour => parse_element(tokens[1], 0..23), #hour
254-
:dom => parse_element(tokens[2], 1..31), #DOM
261+
:dom => parse_element(tokens[2], 1..31, :dom), #DOM
255262
:month => parse_element(tokens[3], 1..12), #mon
256263
:dow => parse_element(tokens[4], 0..6) #DOW
257264
}

spec/cron_parser_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ def parse_date(str)
7777
["15-59/15 * * * *", "2014-02-01 15:45", "2014-02-01 16:15",4],
7878
["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 16:15",3],
7979
["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 16:15",2],
80+
["* * L 2 *", "2015-02-01 15:36", "2015-02-28 00:00",1],
81+
["* * L 2 *", "2016-02-01 15:36", "2016-02-29 00:00",1],
82+
["* * 15,L 2 *", "2015-02-01 15:36", "2015-02-15 00:00",1],
83+
["* * 15,L 2 *", "2015-02-16 15:36", "2015-02-28 00:00",1]
8084
].each do |line, now, expected_next,num|
8185
it "returns #{expected_next} for '#{line}' when now is #{now}" do
8286
parsed_now = parse_date(now)
@@ -156,6 +160,10 @@ def parse_date(str)
156160
["15-59/15 * * * *", "2014-02-01 15:36", "2014-02-01 15:30"],
157161
["15-59/15 * * * *", "2014-02-01 15:45", "2014-02-01 15:30"],
158162
["15-59/15 * * * *", "2014-02-01 15:46", "2014-02-01 15:45"],
163+
["* * L 2 *", "2014-02-01 15:36", "2013-02-28 23:59"],
164+
["* * L 2 *", "2017-02-01 15:36", "2016-02-29 23:59"],
165+
["* * 15,L 2 *", "2015-02-01 15:36", "2014-02-28 23:59"],
166+
["* * 15,L 2 *", "2015-02-16 15:36", "2015-02-15 23:59"]
159167
].each do |line, now, expected_next|
160168
it "should return #{expected_next} for '#{line}' when now is #{now}" do
161169
now = parse_date(now)
@@ -176,6 +184,19 @@ def parse_date(str)
176184
it 'should raise error when given an invalid cronline' do
177185
expect { CronParser.new('* * * *') }.to raise_error('not a valid cronline')
178186
end
187+
188+
it 'should not raise error when L is passed in DOM field' do
189+
expect { CronParser.new('* * L * *').next }.not_to raise_error
190+
end
191+
192+
(0..4).each do |n|
193+
next if n == 2
194+
it "should raise error when L is passed in #{n} field" do
195+
spec = Array.new(5) { '*' }
196+
spec[n] = 'L'
197+
expect { CronParser.new(spec.join(' ')).next }.to raise_error("'L' specification is supported only for DOM field")
198+
end
199+
end
179200
end
180201

181202
RSpec.describe "time source" do

0 commit comments

Comments
 (0)