rufus-scheduler 1.0.12 → 1.0.13

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.
data/CHANGELOG.txt CHANGED
@@ -1,7 +1,18 @@
1
1
 
2
2
  = rufus-scheduler CHANGELOG.txt
3
3
 
4
- == rufus-scheduler - 1.0.12 not yet released
4
+
5
+ == rufus-scheduler - 1.0.13 released 2009/02/02
6
+
7
+ - todo #23779 : removed lib/openwfe/ and restructured to lib/rufus/scheduler/
8
+ - todo #23774 : adapted to Ruby 1.9.1
9
+ - todo #23483 : removed gemspec from Rakefile
10
+ - bug #23458 : :timeout not working on JRuby (reported by Chris Evans). Fixed.
11
+ - patch #23430 : gemspec patch by Ryan Sonnek
12
+ - patch #23412 : faster CronLine#next_time patch by TobyH
13
+
14
+
15
+ == rufus-scheduler - 1.0.12 released 2008/12/18
5
16
 
6
17
  - todo #23257 : added :timeout parameter for cron/in/at/every
7
18
  - bug #22546 : added note about CronLine#next_time, K Liu
data/CREDITS.txt CHANGED
@@ -1,8 +1,15 @@
1
1
 
2
2
  = CREDITS.txt
3
3
 
4
+ == Contributors
5
+
6
+ - TobyH (http://github.com/tobyh), faster and cleaner CronLine#next_time
7
+ - Ryan Sonnek (http://github.com/wireframe), gemspec
8
+
9
+
4
10
  == Feedback
5
11
 
12
+ - Chris Evans, :timeout tests on JRuby
6
13
  - Tim Uckun, :timeout concept
7
14
  - K Liu, for the note about CronLine#next_time
8
15
  - Xianhang Zhang, find_jobs(tag=nil) patch
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+
2
+ Copyright (c) 2005-2008, John Mettraux, jmettraux@gmail.com
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of 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 be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
data/lib/rufus/otime.rb CHANGED
@@ -1,375 +1,3 @@
1
- #
2
- #--
3
- # Copyright (c) 2005-2008, John Mettraux, jmettraux@gmail.com
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
- #++
23
- #
24
1
 
25
- #
26
- # "hecho en Costa Rica"
27
- #
28
- # john.mettraux@openwfe.org
29
- #
30
-
31
- require 'date'
32
- #require 'parsedate'
33
-
34
-
35
- module Rufus
36
-
37
- #TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
38
-
39
- #
40
- # Returns the current time as an ISO date string
41
- #
42
- def Rufus.now
43
-
44
- to_iso8601_date(Time.new())
45
- end
46
-
47
- #
48
- # As the name implies.
49
- #
50
- def Rufus.to_iso8601_date (date)
51
-
52
- if date.kind_of? Float
53
- date = to_datetime(Time.at(date))
54
- elsif date.kind_of? Time
55
- date = to_datetime(date)
56
- elsif not date.kind_of? Date
57
- date = DateTime.parse(date)
58
- end
59
-
60
- s = date.to_s # this is costly
61
- s[10] = " "
62
-
63
- s
64
- end
65
-
66
- #
67
- # the old method we used to generate our ISO datetime strings
68
- #
69
- def Rufus.time_to_iso8601_date (time)
70
-
71
- s = time.getutc().strftime(TIME_FORMAT)
72
- o = time.utc_offset / 3600
73
- o = o.to_s + "00"
74
- o = "0" + o if o.length < 4
75
- o = "+" + o unless o[0..1] == '-'
76
-
77
- s + " " + o.to_s
78
- end
79
-
80
- #
81
- # Returns a Ruby time
82
- #
83
- def Rufus.to_ruby_time (iso_date)
84
-
85
- DateTime.parse(iso_date)
86
- end
87
-
88
- #def Rufus.parse_date (date)
89
- #end
90
-
91
- #
92
- # equivalent to java.lang.System.currentTimeMillis()
93
- #
94
- def Rufus.current_time_millis
95
-
96
- (Time.new.to_f * 1000).to_i
97
- end
98
-
99
- #
100
- # Turns a string like '1m10s' into a float like '70.0', more formally,
101
- # turns a time duration expressed as a string into a Float instance
102
- # (millisecond count).
103
- #
104
- # w -> week
105
- # d -> day
106
- # h -> hour
107
- # m -> minute
108
- # s -> second
109
- # M -> month
110
- # y -> year
111
- # 'nada' -> millisecond
112
- #
113
- # Some examples :
114
- #
115
- # Rufus.parse_time_string "500" # => 0.5
116
- # Rufus.parse_time_string "1000" # => 1.0
117
- # Rufus.parse_time_string "1h" # => 3600.0
118
- # Rufus.parse_time_string "1h10s" # => 3610.0
119
- # Rufus.parse_time_string "1w2d" # => 777600.0
120
- #
121
- def Rufus.parse_time_string (string)
122
-
123
- string = string.strip
124
-
125
- index = -1
126
- result = 0.0
127
-
128
- number = ""
129
-
130
- loop do
131
-
132
- index = index + 1
133
-
134
- if index >= string.length
135
- result = result + (Float(number) / 1000.0) if number.length > 0
136
- break
137
- end
138
-
139
- c = string[index, 1]
140
-
141
- #if is_digit?(c)
142
- if (c >= "0" and c <= "9")
143
- number = number + c
144
- next
145
- end
146
-
147
- value = Integer(number)
148
- number = ""
149
-
150
- multiplier = DURATIONS[c]
151
-
152
- raise "unknown time char '#{c}'" \
153
- if not multiplier
154
-
155
- result = result + (value * multiplier)
156
- end
157
-
158
- result
159
- end
160
-
161
- class << self
162
- alias_method :parse_duration_string, :parse_time_string
163
- end
164
-
165
- #
166
- # Returns true if the character c is a digit
167
- #
168
- # (probably better served by a regex)
169
- #
170
- def Rufus.is_digit? (c)
171
-
172
- return false if not c.kind_of?(String)
173
- return false if c.length > 1
174
- (c >= "0" and c <= "9")
175
- end
176
-
177
- #
178
- # conversion methods between Date[Time] and Time
179
-
180
- #
181
- # Ruby Cookbook 1st edition p.111
182
- # http://www.oreilly.com/catalog/rubyckbk/
183
- # a must
184
- #
185
-
186
- #
187
- # converts a Time instance to a DateTime one
188
- #
189
- def Rufus.to_datetime (time)
190
-
191
- s = time.sec + Rational(time.usec, 10**6)
192
- o = Rational(time.utc_offset, 3600 * 24)
193
-
194
- begin
195
-
196
- DateTime.new(
197
- time.year,
198
- time.month,
199
- time.day,
200
- time.hour,
201
- time.min,
202
- s,
203
- o)
204
-
205
- rescue Exception => e
206
-
207
- DateTime.new(
208
- time.year,
209
- time.month,
210
- time.day,
211
- time.hour,
212
- time.min,
213
- time.sec,
214
- time.utc_offset)
215
- end
216
- end
217
-
218
- def Rufus.to_gm_time (dtime)
219
-
220
- to_ttime(dtime.new_offset, :gm)
221
- end
222
-
223
- def Rufus.to_local_time (dtime)
224
-
225
- to_ttime(dtime.new_offset(DateTime.now.offset-offset), :local)
226
- end
227
-
228
- def Rufus.to_ttime (d, method)
229
-
230
- usec = (d.sec_fraction * 3600 * 24 * (10**6)).to_i
231
- Time.send(method, d.year, d.month, d.day, d.hour, d.min, d.sec, usec)
232
- end
233
-
234
- #
235
- # Turns a number of seconds into a a time string
236
- #
237
- # Rufus.to_duration_string 0 # => '0s'
238
- # Rufus.to_duration_string 60 # => '1m'
239
- # Rufus.to_duration_string 3661 # => '1h1m1s'
240
- # Rufus.to_duration_string 7 * 24 * 3600 # => '1w'
241
- # Rufus.to_duration_string 30 * 24 * 3600 + 1 # => "4w2d1s"
242
- #
243
- # It goes from seconds to the year. Months are not counted (as they
244
- # are of variable length). Weeks are counted.
245
- #
246
- # For 30 days months to be counted, the second parameter of this
247
- # method can be set to true.
248
- #
249
- # Rufus.to_time_string 30 * 24 * 3600 + 1, true # => "1M1s"
250
- #
251
- # (to_time_string is an alias for to_duration_string)
252
- #
253
- # If a Float value is passed, milliseconds will be displayed without
254
- # 'marker'
255
- #
256
- # Rufus.to_duration_string 0.051 # =>"51"
257
- # Rufus.to_duration_string 7.051 # =>"7s51"
258
- # Rufus.to_duration_string 0.120 + 30 * 24 * 3600 + 1 # =>"4w2d1s120"
259
- #
260
- # (this behaviour mirrors the one found for parse_time_string()).
261
- #
262
- # Options are :
263
- #
264
- # * :months, if set to true, months (M) of 30 days will be taken into
265
- # account when building up the result
266
- # * :drop_seconds, if set to true, seconds and milliseconds will be trimmed
267
- # from the result
268
- #
269
- def Rufus.to_duration_string (seconds, options={})
270
-
271
- return (options[:drop_seconds] ? '0m' : '0s') if seconds <= 0
272
-
273
- h = to_duration_hash seconds, options
274
-
275
- s = DU_KEYS.inject("") do |r, key|
276
- count = h[key]
277
- count = nil if count == 0
278
- r << "#{count}#{key}" if count
279
- r
280
- end
281
-
282
- ms = h[:ms]
283
- s << ms.to_s if ms
284
-
285
- s
286
- end
287
-
288
- class << self
289
- alias_method :to_time_string, :to_duration_string
290
- end
291
-
292
- #
293
- # Turns a number of seconds (integer or Float) into a hash like in :
294
- #
295
- # Rufus.to_duration_hash 0.051
296
- # # => { :ms => "51" }
297
- # Rufus.to_duration_hash 7.051
298
- # # => { :s => 7, :ms => "51" }
299
- # Rufus.to_duration_hash 0.120 + 30 * 24 * 3600 + 1
300
- # # => { :w => 4, :d => 2, :s => 1, :ms => "120" }
301
- #
302
- # This method is used by to_duration_string (to_time_string) behind
303
- # the scene.
304
- #
305
- # Options are :
306
- #
307
- # * :months, if set to true, months (M) of 30 days will be taken into
308
- # account when building up the result
309
- # * :drop_seconds, if set to true, seconds and milliseconds will be trimmed
310
- # from the result
311
- #
312
- def Rufus.to_duration_hash (seconds, options={})
313
-
314
- h = {}
315
-
316
- if seconds.is_a?(Float)
317
- h[:ms] = (seconds % 1 * 1000).to_i
318
- seconds = seconds.to_i
319
- end
320
-
321
- if options[:drop_seconds]
322
- h.delete :ms
323
- seconds = (seconds - seconds % 60)
324
- end
325
-
326
- durations = options[:months] ? DURATIONS2M : DURATIONS2
327
-
328
- durations.each do |key, duration|
329
-
330
- count = seconds / duration
331
- seconds = seconds % duration
332
-
333
- h[key.to_sym] = count if count > 0
334
- end
335
-
336
- h
337
- end
338
-
339
- #
340
- # Ensures that a duration is a expressed as a Float instance.
341
- #
342
- # duration_to_f("10s")
343
- #
344
- # will yield 10.0
345
- #
346
- def Rufus.duration_to_f (s)
347
-
348
- return s if s.kind_of?(Float)
349
- return parse_time_string(s) if s.kind_of?(String)
350
- Float(s.to_s)
351
- end
352
-
353
- protected
354
-
355
- DURATIONS2M = [
356
- [ "y", 365 * 24 * 3600 ],
357
- [ "M", 30 * 24 * 3600 ],
358
- [ "w", 7 * 24 * 3600 ],
359
- [ "d", 24 * 3600 ],
360
- [ "h", 3600 ],
361
- [ "m", 60 ],
362
- [ "s", 1 ]
363
- ]
364
- DURATIONS2 = DURATIONS2M.dup
365
- DURATIONS2.delete_at 1
366
-
367
- DURATIONS = DURATIONS2M.inject({}) do |r, (k, v)|
368
- r[k] = v
369
- r
370
- end
371
-
372
- DU_KEYS = DURATIONS2M.collect { |k, v| k.to_sym }
373
-
374
- end
2
+ require 'rufus/scheduler/otime'
375
3
 
@@ -90,21 +90,12 @@ module Rufus
90
90
 
91
91
  time = Time.at(time) unless time.kind_of?(Time)
92
92
 
93
- return false \
94
- if no_match?(time.sec, @seconds)
95
- #if precision <= 1 and no_match?(time.sec, @seconds)
96
- return false \
97
- if no_match?(time.min, @minutes)
98
- #if precision <= 60 and no_match?(time.min, @minutes)
99
- return false \
100
- if no_match?(time.hour, @hours)
101
- return false \
102
- if no_match?(time.day, @days)
103
- return false \
104
- if no_match?(time.month, @months)
105
- return false \
106
- if no_match?(time.wday, @weekdays)
107
-
93
+ return false unless sub_match? time.sec, @seconds
94
+ return false unless sub_match? time.min, @minutes
95
+ return false unless sub_match? time.hour, @hours
96
+ return false unless sub_match? time.day, @days
97
+ return false unless sub_match? time.month, @months
98
+ return false unless sub_match? time.wday, @weekdays
108
99
  true
109
100
  end
110
101
 
@@ -142,59 +133,35 @@ module Rufus
142
133
  #
143
134
  # (Thanks to K Liu for the note and the examples)
144
135
  #
145
- def next_time (now = Time.now)
146
-
147
- #
148
- # position now to the next cron second
136
+ def next_time time=Time.now
137
+ time -= time.usec * 1e-6
138
+ time += 1
149
139
 
150
- if @seconds
151
- next_sec = @seconds.find { |s| s > now.sec } || 60 + @seconds.first
152
- now += next_sec - now.sec
153
- else
154
- now += 1
155
- end
156
-
157
- #
158
- # prepare sec jump array
159
-
160
- sjarray = nil
161
-
162
- if @seconds
163
-
164
- sjarray = []
165
-
166
- i = @seconds.index(now.sec)
167
- ii = i
168
-
169
- loop do
170
- cur = @seconds[ii]
171
- ii += 1
172
- ii = 0 if ii == @seconds.size
173
- nxt = @seconds[ii]
174
- nxt += 60 if ii == 0
175
- sjarray << (nxt - cur)
176
- break if ii == i
140
+ loop do
141
+ unless date_match? time
142
+ time += (24 - time.hour) * 3600 - time.min * 60 - time.sec
143
+ next
177
144
  end
178
145
 
179
- else
180
-
181
- sjarray = [ 1 ]
182
- end
146
+ unless sub_match? time.hour, @hours
147
+ time += (60 - time.min) * 60 - time.sec
148
+ next
149
+ end
183
150
 
184
- #
185
- # ok, seek...
151
+ unless sub_match? time.min, @minutes
152
+ time += 60 - time.sec
153
+ next
154
+ end
186
155
 
187
- i = 0
156
+ unless sub_match? time.sec, @seconds
157
+ time += 1
158
+ next
159
+ end
188
160
 
189
- loop do
190
- return now if matches?(now)
191
- now += sjarray[i]
192
- i += 1
193
- i = 0 if i == sjarray.size
194
- # danger... potentially no exit...
161
+ break
195
162
  end
196
163
 
197
- nil
164
+ time
198
165
  end
199
166
 
200
167
  private
@@ -307,15 +274,15 @@ module Rufus
307
274
  result
308
275
  end
309
276
 
310
- def no_match? (value, cron_values)
311
-
312
- return false if not cron_values
313
-
314
- cron_values.each do |v|
315
- return false if value == v # ok, it matches
316
- end
277
+ def sub_match? value, values
278
+ values.nil? || values.include?(value)
279
+ end
317
280
 
318
- true # no match found
281
+ def date_match? date
282
+ return false unless sub_match? date.day, @days
283
+ return false unless sub_match? date.month, @months
284
+ return false unless sub_match? date.wday, @weekdays
285
+ true
319
286
  end
320
287
  end
321
288