rufus-scheduler 2.0.17 → 2.0.18

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,13 @@
2
2
  = rufus-scheduler CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-scheduler - 2.0.18 released 2012/03/06
6
+
7
+ - support for "L" in cron lines (Thanks Andrew Davey)
8
+ - support for negative time strings (Thanks Danny "northox" Fullerton)
9
+ - reject invalid weekdays (Thanks pazustep)
10
+
11
+
5
12
  == rufus-scheduler - 2.0.17 released 2012/06/14
6
13
 
7
14
  - @andrehjr patch to make it work on Ruby 1.9.3
data/CREDITS.txt CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  == Contributors
6
6
 
7
+ - Andrew Davey (https://github.com/asdavey) "L" in cron lines
8
+ - Stig Kleppe-Jørgensen (https://github.com/stigkj)
9
+ - Danny "northox" Fullerton (https://github.com/northox) negative time strings
10
+ - Marcus Brito (https://github.com/pazustep) CronLine proofing
7
11
  - André Luis Leal Cardoso Junior (https://github.com/andrehjr) 1.9.3 patch
8
12
  - Anthony Lewis (https://github.com/anthonylewis) cron lines and 09 issue
9
13
  - concept47 (https://github.com/concept47) every and :discard_past
data/LICENSE.txt CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
data/README.rdoc CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  = rufus-scheduler
3
2
 
4
3
  rufus-scheduler is a Ruby gem for scheduling pieces of code (jobs). It understands running a job AT a certain time, IN a certain time, EVERY x time or simply via a CRON statement.
@@ -60,10 +59,10 @@ This PlainScheduler accepts a :thread_name option :
60
59
 
61
60
  scheduler = Rufus::Scheduler::PlainScheduler.start_new(:thread_name => 'my scheduler')
62
61
 
63
- might be helpful when tracking threads.
62
+ which might be helpful when tracking threads.
64
63
 
65
64
 
66
- Note that is there is EventMachine present and running,
65
+ Note that if there is an EventMachine present and running,
67
66
 
68
67
  scheduler = Rufus::Scheduler.start_new
69
68
 
@@ -78,12 +77,16 @@ This is a classical cron :
78
77
  # every day of the week at 22:00 (10pm)
79
78
  end
80
79
 
81
- Rufus-scheduler supports two variants to that notation : seconds and timezones.
80
+ Rufus-scheduler supports three variants to that notation : seconds, last day of month and timezones.
82
81
 
83
82
  scheduler.cron '13 0 22 * * 1-5' do
84
83
  # every day of the week at 22:00:13
85
84
  end
86
85
 
86
+ scheduler.cron '0 22 L * *' do
87
+ # every month on the last day at 22:00
88
+ end
89
+
87
90
  scheduler.cron '0 22 * * 1-5 Europe/Paris' do
88
91
  # every day of the week when it's 22:00 in Paris
89
92
  end
@@ -120,7 +123,7 @@ If you place
120
123
 
121
124
  scheduler.join
122
125
 
123
- at then end of it will make the current (main) thread join the scheduler and prevent the Ruby runtime from exiting.
126
+ at the end, it will make the current (main) thread join the scheduler and prevent the Ruby runtime from exiting.
124
127
 
125
128
  You shouldn't be exposed to this issue when using EventMachine, since while running EM, your runtime won't exit.
126
129
 
@@ -200,7 +203,7 @@ If at 4pm the scheduler is in a blocking task, there will be no four o'clock tea
200
203
  puts "order espresso"
201
204
  end
202
205
 
203
- the "order espresso" will only get triggered once the ristretto has been consumed. Rufus-scheduler, will create a 'that_mutex' mutex and keep track of it. Don't go on passing too many different mutex names, rufus-scheduler will keep track of each of them (they won't get garbage collected).
206
+ the "order espresso" will only get triggered once the ristretto has been consumed. Rufus-scheduler will create a 'that_mutex' mutex and keep track of it. Don't go on passing too many different mutex names, rufus-scheduler will keep track of each of them (they won't get garbage collected).
204
207
 
205
208
  It's OK to use a mutex directly:
206
209
 
@@ -240,7 +243,7 @@ By default, every and cron jobs will "overlap":
240
243
  end
241
244
  end
242
245
 
243
- You mind end up with something that looks like
246
+ You might end up with something that looks like
244
247
 
245
248
  hello 0
246
249
  hello 1
@@ -250,7 +253,7 @@ You mind end up with something that looks like
250
253
  hello 4
251
254
  ...
252
255
 
253
- This every job, will have overlaps. To prevent that:
256
+ This every job will have overlaps. To prevent that:
254
257
 
255
258
  scheduler.every '3s', :allow_overlapping => false do
256
259
  # ...
@@ -446,7 +449,7 @@ This timeout feature relies on an 'in' job scheduled at the moment the main job
446
449
 
447
450
  == exceptions in jobs
448
451
 
449
- By default, when exception occur when a job performs, the error message will be output to the STDOUT.
452
+ By default, when exceptions occur when a job performs, the error messages will be output to the STDOUT.
450
453
 
451
454
  It's easy to customize that behaviour :
452
455
 
@@ -564,7 +567,7 @@ http://github.com/jmettraux/rufus-scheduler/blob/master/CREDITS.txt
564
567
 
565
568
  == authors
566
569
 
567
- John Mettraux, jmettraux@gmail.com, http://jmettraux.wordpress.com
570
+ John Mettraux, jmettraux@gmail.com, http://jmettraux.github.com
568
571
 
569
572
 
570
573
  == the rest of Rufus
@@ -575,4 +578,3 @@ http://rufus.rubyforge.org
575
578
  == license
576
579
 
577
580
  MIT
578
-
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -69,6 +69,13 @@ module Rufus
69
69
  @days = parse_item(items[2 + offset], 1, 31)
70
70
  @months = parse_item(items[3 + offset], 1, 12)
71
71
  @weekdays, @monthdays = parse_weekdays(items[4 + offset])
72
+
73
+ [ @seconds, @minutes, @hours, @months ].each do |es|
74
+
75
+ raise ArgumentError.new(
76
+ "invalid cronline: '#{line}'"
77
+ ) if es && es.find { |e| ! e.is_a?(Integer) }
78
+ end
72
79
  end
73
80
 
74
81
  # Returns true if the given time matches this cron line.
@@ -79,9 +86,9 @@ module Rufus
79
86
 
80
87
  time = @timezone.utc_to_local(time.getutc) if @timezone
81
88
 
82
- return false unless sub_match?(time.sec, @seconds)
83
- return false unless sub_match?(time.min, @minutes)
84
- return false unless sub_match?(time.hour, @hours)
89
+ return false unless sub_match?(time, :sec, @seconds)
90
+ return false unless sub_match?(time, :min, @minutes)
91
+ return false unless sub_match?(time, :hour, @hours)
85
92
  return false unless date_match?(time)
86
93
  true
87
94
  end
@@ -126,15 +133,15 @@ module Rufus
126
133
  time += (24 - time.hour) * 3600 - time.min * 60 - time.sec
127
134
  next
128
135
  end
129
- unless sub_match?(time.hour, @hours)
136
+ unless sub_match?(time, :hour, @hours)
130
137
  time += (60 - time.min) * 60 - time.sec
131
138
  next
132
139
  end
133
- unless sub_match?(time.min, @minutes)
140
+ unless sub_match?(time, :min, @minutes)
134
141
  time += 60 - time.sec
135
142
  next
136
143
  end
137
- unless sub_match?(time.sec, @seconds)
144
+ unless sub_match?(time, :sec, @seconds)
138
145
  time += 1
139
146
  next
140
147
  end
@@ -192,10 +199,14 @@ module Rufus
192
199
  (monthdays ||= []) << it
193
200
 
194
201
  else
202
+ expr = it.dup
203
+ WEEKDAYS.each_with_index { |a, i| expr.gsub!(/#{a}/, i.to_s) }
195
204
 
196
- WEEKDAYS.each_with_index { |a, i| it.gsub!(/#{a}/, i.to_s) }
205
+ raise ArgumentError.new(
206
+ "invalid weekday expression (#{it})"
207
+ ) if expr !~ /^0*[0-7](-0*[0-7])?$/
197
208
 
198
- its = it.index('-') ? parse_range(it, 0, 7) : [ Integer(it) ]
209
+ its = expr.index('-') ? parse_range(expr, 0, 7) : [ Integer(expr) ]
199
210
  its = its.collect { |i| i == 7 ? 0 : i }
200
211
 
201
212
  (weekdays ||= []).concat(its)
@@ -210,8 +221,9 @@ module Rufus
210
221
  def parse_item(item, min, max)
211
222
 
212
223
  return nil if item == '*'
224
+ return [ 'L' ] if item == 'L'
213
225
  return parse_list(item, min, max) if item.index(',')
214
- return parse_range(item, min, max) if item.index('*') or item.index('-')
226
+ return parse_range(item, min, max) if item.match(/[*-\/]/)
215
227
 
216
228
  i = item.to_i
217
229
 
@@ -223,32 +235,36 @@ module Rufus
223
235
 
224
236
  def parse_list(item, min, max)
225
237
 
226
- item.split(',').inject([]) { |r, i|
227
- r.push(parse_range(i, min, max))
228
- }.flatten
238
+ l = item.split(',').collect { |i| parse_range(i, min, max) }.flatten
239
+
240
+ raise ArgumentError.new(
241
+ "found duplicates in #{item.inspect}"
242
+ ) if l.uniq.size < l.size
243
+
244
+ l
229
245
  end
230
246
 
231
247
  def parse_range(item, min, max)
232
248
 
233
- i = item.index('-')
234
- j = item.index('/')
249
+ dash = item.index('-')
250
+ slash = item.index('/')
235
251
 
236
- return item.to_i if (not i and not j)
252
+ return parse_item(item, min, max) if (not slash) and (not dash)
237
253
 
238
- inc = j ? item[j + 1..-1].to_i : 1
254
+ raise ArgumentError.new(
255
+ "'L' (end of month) is not accepted in ranges, " +
256
+ "#{item.inspect} is not valid"
257
+ ) if item.index('L')
258
+
259
+ inc = slash ? item[slash + 1..-1].to_i : 1
239
260
 
240
261
  istart = -1
241
262
  iend = -1
242
263
 
243
- if i
244
-
245
- istart = item[0..i - 1].to_i
264
+ if dash
246
265
 
247
- iend = if j
248
- item[i + 1..j - 1].to_i
249
- else
250
- item[i + 1..-1].to_i
251
- end
266
+ istart = item[0..dash - 1].to_i
267
+ iend = (slash ? item[dash + 1..slash - 1] : item[dash + 1..-1]).to_i
252
268
 
253
269
  else # case */x
254
270
 
@@ -271,22 +287,26 @@ module Rufus
271
287
  result
272
288
  end
273
289
 
274
- def sub_match?(value, values)
290
+ def sub_match?(time, accessor, values=:none)
275
291
 
276
- values.nil? || values.include?(value)
277
- end
292
+ value, values =
293
+ if values == :none
294
+ [ time, accessor ]
295
+ else
296
+ [ time.send(accessor), values ]
297
+ end
278
298
 
279
- def monthday_match(monthday, monthdays)
299
+ return true if values.nil?
300
+ return true if values.include?('L') && (time + 24 * 3600).day == 1
280
301
 
281
- return true if monthdays == nil
282
- return true if monthdays.include?(monthday)
302
+ values.include?(value)
283
303
  end
284
304
 
285
305
  def date_match?(date)
286
306
 
287
- return false unless sub_match?(date.day, @days)
288
- return false unless sub_match?(date.month, @months)
289
- return false unless sub_match?(date.wday, @weekdays)
307
+ return false unless sub_match?(date, :day, @days)
308
+ return false unless sub_match?(date, :month, @months)
309
+ return false unless sub_match?(date, :wday, @weekdays)
290
310
  return false unless sub_match?(CronLine.monthday(date), @monthdays)
291
311
  true
292
312
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
data/lib/rufus/sc/jobs.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -30,7 +30,7 @@ module Scheduler
30
30
  # The base class for all types of jobs.
31
31
  #
32
32
  class Job
33
-
33
+
34
34
  # A reference to the scheduler owning this job
35
35
  #
36
36
  attr_accessor :scheduler
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -96,8 +96,6 @@ module Rufus
96
96
  (Time.new.to_f * 1000).to_i
97
97
  end
98
98
 
99
- FLOAT_DURATION = /^\d*\.\d*$/
100
-
101
99
  # Turns a string like '1m10s' into a float like '70.0', more formally,
102
100
  # turns a time duration expressed as a string into a Float instance
103
101
  # (millisecond count).
@@ -120,24 +118,35 @@ module Rufus
120
118
  # Rufus.parse_time_string "1h10s" # => 3610.0
121
119
  # Rufus.parse_time_string "1w2d" # => 777600.0
122
120
  #
123
- def Rufus.parse_time_string(string)
124
-
125
- if m = string.match(/^(\d*)\.?(\d*)([A-Za-z])(.*)$/)
121
+ def self.parse_time_string(string)
126
122
 
127
- number = "#{m[1]}.#{m[2]}".to_f
128
- multiplier = DURATIONS[m[3]]
123
+ return 0.0 if string == ''
129
124
 
130
- raise ArgumentError.new("unknown time char '#{m[3]}'") unless multiplier
125
+ m = string.match(/^(-?)([\d\.#{DURATION_LETTERS}]+)$/)
131
126
 
132
- return number * multiplier + parse_time_string(m[4])
127
+ raise ArgumentError.new("cannot parse '#{string}'") unless m
133
128
 
134
- else
129
+ mod = m[1] == '-' ? -1.0 : 1.0
130
+ val = 0.0
135
131
 
136
- return string.to_i / 1000.0 if string.match(/^\d+$/)
137
- return string.to_f if string.match(/^\d*\.?\d*$/)
132
+ s = m[2]
138
133
 
139
- raise ArgumentError.new("cannot parse '#{string}'")
134
+ while s.length > 0
135
+ m = nil
136
+ if m = s.match(/^(\d+|\d+\.\d*|\d*\.\d+)([#{DURATION_LETTERS}])(.*)$/)
137
+ val += m[1].to_f * DURATIONS[m[2]]
138
+ elsif s.match(/^\d+$/)
139
+ val += s.to_i / 1000.0
140
+ elsif s.match(/^\d*\.\d*$/)
141
+ val += s.to_f
142
+ else
143
+ raise ArgumentError.new("cannot parse '#{string}' (especially '#{s}')")
144
+ end
145
+ break unless m && m[3]
146
+ s = m[3]
140
147
  end
148
+
149
+ mod * val
141
150
  end
142
151
 
143
152
  class << self
@@ -185,7 +194,7 @@ module Rufus
185
194
 
186
195
  def Rufus.to_local_time(dtime)
187
196
 
188
- to_ttime(dtime.new_offset(DateTime.now.offset-offset), :local)
197
+ to_ttime(dtime.new_offset(DateTime.now.offset - offset), :local)
189
198
  end
190
199
 
191
200
  def Rufus.to_ttime(d, method)
@@ -232,7 +241,7 @@ module Rufus
232
241
 
233
242
  return (options[:drop_seconds] ? '0m' : '0s') if seconds <= 0
234
243
 
235
- h = to_duration_hash seconds, options
244
+ h = to_duration_hash(seconds, options)
236
245
 
237
246
  s = DU_KEYS.inject('') { |r, key|
238
247
  count = h[key]
@@ -280,7 +289,7 @@ module Rufus
280
289
  end
281
290
 
282
291
  if options[:drop_seconds]
283
- h.delete :ms
292
+ h.delete(:ms)
284
293
  seconds = (seconds - seconds % 60)
285
294
  end
286
295
 
@@ -317,8 +326,8 @@ module Rufus
317
326
 
318
327
  # TODO : use chronic if present
319
328
 
320
- at = Rufus::to_ruby_time(at) if at.is_a?(String)
321
- at = Rufus::to_gm_time(at) if at.is_a?(DateTime)
329
+ at = to_ruby_time(at) if at.is_a?(String)
330
+ at = to_gm_time(at) if at.is_a?(DateTime)
322
331
  #at = at.to_f if at.is_a?(Time)
323
332
  at = at.to_f if at.respond_to?(:to_f)
324
333
 
@@ -329,7 +338,7 @@ module Rufus
329
338
  at
330
339
  end
331
340
 
332
- protected
341
+ protected # well, somehow
333
342
 
334
343
  DURATIONS2M = [
335
344
  [ 'y', 365 * 24 * 3600 ],
@@ -343,10 +352,8 @@ module Rufus
343
352
  DURATIONS2 = DURATIONS2M.dup
344
353
  DURATIONS2.delete_at(1)
345
354
 
346
- DURATIONS = DURATIONS2M.inject({}) do |r, (k, v)|
347
- r[k] = v
348
- r
349
- end
355
+ DURATIONS = DURATIONS2M.inject({}) { |r, (k, v)| r[k] = v; r }
356
+ DURATION_LETTERS = DURATIONS.keys.join
350
357
 
351
358
  DU_KEYS = DURATIONS2M.collect { |k, v| k.to_sym }
352
359
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -26,7 +26,7 @@
26
26
  module Rufus
27
27
  module Scheduler
28
28
 
29
- VERSION = '2.0.17'
29
+ VERSION = '2.0.18'
30
30
  end
31
31
  end
32
32
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -17,17 +17,18 @@ describe SCHEDULER_CLASS do
17
17
  stop_scheduler(@s)
18
18
  end
19
19
 
20
- JOB = Proc.new do |x|
21
- begin
22
- $var << "a#{x}"
23
- sleep 0.500
24
- $var << "b#{x}"
25
- rescue Exception => e
26
- puts '=' * 80
27
- p e
28
- puts '=' * 80
20
+ JOB =
21
+ Proc.new do |x|
22
+ begin
23
+ $var << "a#{x}"
24
+ sleep 0.500
25
+ $var << "b#{x}"
26
+ rescue Exception => e
27
+ puts '=' * 80
28
+ p e
29
+ puts '=' * 80
30
+ end
29
31
  end
30
- end
31
32
 
32
33
  context ':blocking => nil' do
33
34
 
@@ -37,9 +38,12 @@ describe SCHEDULER_CLASS do
37
38
  @s.in('1s') { JOB.call(1) }
38
39
  @s.in('1s') { JOB.call(2) }
39
40
 
40
- sleep 5.0
41
+ sleep 4.0
41
42
 
42
- [ %w{ a1 a2 b1 b2 }, %w{ a1 a2 b2 b1 } ].should include($var)
43
+ [
44
+ %w{ a1 a2 b1 b2 }, %w{ a1 a2 b2 b1 },
45
+ %w{ a2 a1 b2 b1 }, %w{ a2 a1 b1 b2 }
46
+ ].should include($var)
43
47
  end
44
48
  end
45
49
 
@@ -36,7 +36,7 @@ describe Rufus::CronLine do
36
36
  it 'interprets cron strings correctly' do
37
37
 
38
38
  to_a '* * * * *', [ [0], nil, nil, nil, nil, nil, nil, nil ]
39
- to_a '10-12 * * * *', [ [0], [10, 11, 12], nil, nil, nil, nil, nil, nil ]
39
+ to_a '10-12 * * * *', [ [0], [10, 11, 12], nil, nil, nil, nil, nil, nil ]
40
40
  to_a '* * * * sun,mon', [ [0], nil, nil, nil, nil, [0, 1], nil, nil ]
41
41
  to_a '* * * * mon-wed', [ [0], nil, nil, nil, nil, [1, 2, 3], nil, nil ]
42
42
  to_a '* * * * 7', [ [0], nil, nil, nil, nil, [0], nil, nil ]
@@ -56,6 +56,21 @@ describe Rufus::CronLine do
56
56
  to_a '0 0 1 1 *', [ [0], [0], [0], [1], [1], nil, nil, nil ]
57
57
  end
58
58
 
59
+ it 'rejects invalid weekday expressions' do
60
+
61
+ lambda { cl '0 17 * * MON_FRI' }.should raise_error
62
+ # underline instead of dash
63
+
64
+ lambda { cl '* * * * 9' }.should raise_error
65
+ lambda { cl '* * * * 0-12' }.should raise_error
66
+ lambda { cl '* * * * BLABLA' }.should raise_error
67
+ end
68
+
69
+ it 'rejects invalid cronlines' do
70
+
71
+ lambda { cl '* nada * * 9' }.should raise_error(ArgumentError)
72
+ end
73
+
59
74
  it 'interprets cron strings with TZ correctly' do
60
75
 
61
76
  to_a '* * * * * EST', [ [0], nil, nil, nil, nil, nil, nil, 'EST' ]
@@ -94,6 +109,29 @@ describe Rufus::CronLine do
94
109
  to_a '* 01-09/04 * * *', [ [0], nil, [1, 5, 9], nil, nil, nil, nil, nil ]
95
110
  to_a '* * * * 06', [ [0], nil, nil, nil, nil, [6], nil, nil ]
96
111
  end
112
+
113
+ it 'interprets cron strings with L correctly' do
114
+
115
+ to_a '* * L * *', [[0], nil, nil, ['L'], nil, nil, nil, nil ]
116
+ to_a '* * 2-5,L * *', [[0], nil, nil, [2,3,4,5,'L'], nil, nil, nil, nil ]
117
+ to_a '* * */8,L * *', [[0], nil, nil, [1,9,17,25,'L'], nil, nil, nil, nil ]
118
+ end
119
+
120
+ it 'does not support ranges for L' do
121
+
122
+ lambda { cl '* * 15-L * *'}.should raise_error(ArgumentError)
123
+ lambda { cl '* * L/4 * *'}.should raise_error(ArgumentError)
124
+ end
125
+
126
+ it 'does not support multiple Ls' do
127
+
128
+ lambda { cl '* * L,L * *'}.should raise_error(ArgumentError)
129
+ end
130
+
131
+ it 'raises if L is used for something else than days' do
132
+
133
+ lambda { cl '* L * * *'}.should raise_error(ArgumentError)
134
+ end
97
135
  end
98
136
 
99
137
  describe '#next_time' do
@@ -207,6 +245,14 @@ describe Rufus::CronLine do
207
245
 
208
246
  nt('* * * * sun#2,sun#3', now).should == local(1970, 1, 18)
209
247
  end
248
+
249
+ it 'computes the next time correctly when there is a L (last day of month)' do
250
+
251
+ nt('* * L * *', local(1970,1,1)).should == local(1970, 1, 31)
252
+ nt('* * L * *', local(1970,2,1)).should == local(1970, 2, 28)
253
+ nt('* * L * *', local(1972,2,1)).should == local(1972, 2, 29)
254
+ nt('* * L * *', local(1970,4,1)).should == local(1970, 4, 30)
255
+ end
210
256
  end
211
257
 
212
258
  describe '#matches?' do
@@ -264,6 +310,12 @@ describe Rufus::CronLine do
264
310
  no_match '* * 13 * fri#2', utc(1970, 2, 20)
265
311
  end
266
312
 
313
+ it 'matches correctly when there is a L involved' do
314
+
315
+ match '* * L * *', utc(1970, 1, 31)
316
+ no_match '* * L * *', utc(1970, 1, 30)
317
+ end
318
+
267
319
  it 'matches correctly when there is a sun#2,sun#3 involved' do
268
320
 
269
321
  no_match '* * * * sun#2,sun#3', local(1970, 1, 4)
data/spec/rtime_spec.rb CHANGED
@@ -24,6 +24,15 @@ describe 'rufus/rtime' do
24
24
 
25
25
  it 'parses duration strings' do
26
26
 
27
+ pts('-1.0d1.0w1.0d').should == -777600.0
28
+ pts('-1d1w1d').should == -777600.0
29
+ pts('-1w2d').should == -777600.0
30
+ pts('-1h10s').should == -3610.0
31
+ pts('-1h').should == -3600.0
32
+ pts('-5.').should == -5.0
33
+ pts('-2.5s').should == -2.5
34
+ pts('-1s').should == -1.0
35
+ pts('-500').should == -0.5
27
36
  pts('').should == 0.0
28
37
  pts('5.0').should == 5.0
29
38
  pts('0.5').should == 0.5
@@ -39,6 +48,21 @@ describe 'rufus/rtime' do
39
48
  pts('1w2d').should == 777600.0
40
49
  pts('1d1w1d').should == 777600.0
41
50
  pts('1.0d1.0w1.0d').should == 777600.0
51
+
52
+ pts('.5m').should == 30.0
53
+ pts('5.m').should == 300.0
54
+ pts('1m.5s').should == 60.5
55
+ pts('-.5m').should == -30.0
56
+ end
57
+
58
+ it 'raises on wrong duration strings' do
59
+
60
+ lambda { pts('-') }.should raise_error(ArgumentError)
61
+ lambda { pts('h') }.should raise_error(ArgumentError)
62
+ lambda { pts('whatever') }.should raise_error(ArgumentError)
63
+ lambda { pts('hms') }.should raise_error(ArgumentError)
64
+
65
+ lambda { pts(' 1h ') }.should raise_error(ArgumentError)
42
66
  end
43
67
 
44
68
  it 'generates duration strings' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.17
4
+ version: 2.0.18
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-13 00:00:00.000000000Z
12
+ date: 2013-03-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tzinfo
16
- requirement: &2153074260 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 0.3.23
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2153074260
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.23
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rake
27
- requirement: &2153072940 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *2153072940
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rspec
38
- requirement: &2153072180 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,7 +53,12 @@ dependencies:
43
53
  version: 2.7.0
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *2153072180
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.7.0
47
62
  description: job scheduler for Ruby (at, cron, in and every jobs).
48
63
  email:
49
64
  - jmettraux@gmail.com
@@ -52,39 +67,38 @@ extensions: []
52
67
  extra_rdoc_files: []
53
68
  files:
54
69
  - Rakefile
55
- - lib/rufus/otime.rb
56
- - lib/rufus/sc/cronline.rb
57
- - lib/rufus/sc/jobqueues.rb
58
- - lib/rufus/sc/jobs.rb
59
- - lib/rufus/sc/rtime.rb
70
+ - lib/rufus-scheduler.rb
71
+ - lib/rufus/scheduler.rb
60
72
  - lib/rufus/sc/scheduler.rb
73
+ - lib/rufus/sc/rtime.rb
61
74
  - lib/rufus/sc/version.rb
62
- - lib/rufus/scheduler.rb
63
- - lib/rufus-scheduler.rb
64
- - spec/at_in_spec.rb
65
- - spec/at_spec.rb
66
- - spec/blocking_spec.rb
67
- - spec/cron_spec.rb
68
- - spec/cronline_spec.rb
69
- - spec/every_spec.rb
75
+ - lib/rufus/sc/cronline.rb
76
+ - lib/rufus/sc/jobs.rb
77
+ - lib/rufus/sc/jobqueues.rb
78
+ - lib/rufus/otime.rb
79
+ - spec/job_spec.rb
80
+ - spec/stress_schedule_unschedule_spec.rb
81
+ - spec/schedulable_spec.rb
70
82
  - spec/exception_spec.rb
71
83
  - spec/in_spec.rb
72
- - spec/job_spec.rb
73
- - spec/mutex_spec.rb
84
+ - spec/timeout_spec.rb
85
+ - spec/at_spec.rb
86
+ - spec/at_in_spec.rb
87
+ - spec/spec_base.rb
88
+ - spec/cronline_spec.rb
74
89
  - spec/rtime_spec.rb
75
- - spec/schedulable_spec.rb
90
+ - spec/mutex_spec.rb
76
91
  - spec/scheduler_spec.rb
77
- - spec/spec_base.rb
78
- - spec/stress_schedule_unschedule_spec.rb
79
- - spec/timeout_spec.rb
80
- - test/kjw.rb
92
+ - spec/blocking_spec.rb
93
+ - spec/every_spec.rb
94
+ - spec/cron_spec.rb
81
95
  - test/t.rb
96
+ - test/kjw.rb
82
97
  - rufus-scheduler.gemspec
83
98
  - CHANGELOG.txt
84
- - CREDITS.txt
85
- - LICENSE.txt
86
- - out.txt
87
99
  - TODO.txt
100
+ - LICENSE.txt
101
+ - CREDITS.txt
88
102
  - README.rdoc
89
103
  homepage: http://github.com/jmettraux/rufus-scheduler
90
104
  licenses: []
@@ -98,15 +112,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
112
  - - ! '>='
99
113
  - !ruby/object:Gem::Version
100
114
  version: '0'
115
+ segments:
116
+ - 0
117
+ hash: 4543164608551708958
101
118
  required_rubygems_version: !ruby/object:Gem::Requirement
102
119
  none: false
103
120
  requirements:
104
121
  - - ! '>='
105
122
  - !ruby/object:Gem::Version
106
123
  version: '0'
124
+ segments:
125
+ - 0
126
+ hash: 4543164608551708958
107
127
  requirements: []
108
128
  rubyforge_project: rufus
109
- rubygems_version: 1.8.11
129
+ rubygems_version: 1.8.24
110
130
  signing_key:
111
131
  specification_version: 3
112
132
  summary: job scheduler for Ruby (at, cron, in and every jobs)
data/out.txt DELETED
@@ -1,4 +0,0 @@
1
- ruby-1.8.7-p249 :001 > nada
2
- NameError: undefined local variable or method `nada' for #<Object:0x1001d1298>
3
- from (irb):1
4
- ruby-1.8.7-p249 :002 > ^D