rufus-scheduler 3.1.4 → 3.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +410 -0
  3. data/CREDITS.md +142 -0
  4. data/LICENSE.txt +1 -1
  5. data/Makefile +27 -0
  6. data/README.md +407 -143
  7. data/lib/rufus/scheduler/job_array.rb +36 -66
  8. data/lib/rufus/scheduler/jobs_core.rb +369 -0
  9. data/lib/rufus/scheduler/jobs_one_time.rb +53 -0
  10. data/lib/rufus/scheduler/jobs_repeat.rb +335 -0
  11. data/lib/rufus/scheduler/locks.rb +41 -67
  12. data/lib/rufus/scheduler/util.rb +89 -179
  13. data/lib/rufus/scheduler.rb +545 -453
  14. data/rufus-scheduler.gemspec +22 -11
  15. metadata +44 -85
  16. data/CHANGELOG.txt +0 -243
  17. data/CREDITS.txt +0 -88
  18. data/Rakefile +0 -83
  19. data/TODO.txt +0 -151
  20. data/lib/rufus/scheduler/cronline.rb +0 -470
  21. data/lib/rufus/scheduler/jobs.rb +0 -633
  22. data/lib/rufus/scheduler/zones.rb +0 -174
  23. data/lib/rufus/scheduler/zotime.rb +0 -155
  24. data/spec/basics_spec.rb +0 -54
  25. data/spec/cronline_spec.rb +0 -915
  26. data/spec/error_spec.rb +0 -139
  27. data/spec/job_array_spec.rb +0 -39
  28. data/spec/job_at_spec.rb +0 -58
  29. data/spec/job_cron_spec.rb +0 -128
  30. data/spec/job_every_spec.rb +0 -104
  31. data/spec/job_in_spec.rb +0 -20
  32. data/spec/job_interval_spec.rb +0 -68
  33. data/spec/job_repeat_spec.rb +0 -357
  34. data/spec/job_spec.rb +0 -631
  35. data/spec/lock_custom_spec.rb +0 -47
  36. data/spec/lock_flock_spec.rb +0 -47
  37. data/spec/lock_lockfile_spec.rb +0 -61
  38. data/spec/lock_spec.rb +0 -59
  39. data/spec/parse_spec.rb +0 -263
  40. data/spec/schedule_at_spec.rb +0 -158
  41. data/spec/schedule_cron_spec.rb +0 -66
  42. data/spec/schedule_every_spec.rb +0 -109
  43. data/spec/schedule_in_spec.rb +0 -80
  44. data/spec/schedule_interval_spec.rb +0 -128
  45. data/spec/scheduler_spec.rb +0 -1067
  46. data/spec/spec_helper.rb +0 -126
  47. data/spec/threads_spec.rb +0 -96
  48. data/spec/zotime_spec.rb +0 -396
@@ -1,915 +0,0 @@
1
-
2
- #
3
- # Specifying rufus-scheduler
4
- #
5
- # Sat Mar 21 12:55:27 JST 2009
6
- #
7
-
8
- require 'spec_helper'
9
-
10
-
11
- describe Rufus::Scheduler::CronLine do
12
-
13
- def cl(cronline_string)
14
- Rufus::Scheduler::CronLine.new(cronline_string)
15
- end
16
-
17
- def nt(cronline, now)
18
- Rufus::Scheduler::CronLine.new(cronline).next_time(now)
19
- end
20
- def ntz(cronline, now)
21
- tz = cronline.split.last
22
- tu = nt(cronline, now).utc
23
- in_zone(tz) { tu.getlocal }
24
- end
25
-
26
- def pt(cronline, now)
27
- Rufus::Scheduler::CronLine.new(cronline).previous_time(now)
28
- end
29
- def ptz(cronline, now)
30
- tz = cronline.split.last
31
- tu = pt(cronline, now).utc
32
- in_zone(tz) { tu.getlocal }
33
- end
34
-
35
- def ns(cronline, now)
36
- Rufus::Scheduler::CronLine.new(cronline).next_second(now)
37
- end
38
-
39
- def match(line, time)
40
- expect(cl(line).matches?(time)).to eq(true)
41
- end
42
- def no_match(line, time)
43
- expect(cl(line).matches?(time)).to eq(false)
44
- end
45
- def to_a(line, array)
46
- expect(cl(line).to_array).to eq(array)
47
- end
48
-
49
- describe '.new' do
50
-
51
- it 'interprets cron strings correctly' do
52
-
53
- to_a '* * * * *', [ [0], nil, nil, nil, nil, nil, nil, nil ]
54
- to_a '10-12 * * * *', [ [0], [10, 11, 12], nil, nil, nil, nil, nil, nil ]
55
- to_a '* * * * sun,mon', [ [0], nil, nil, nil, nil, [0, 1], nil, nil ]
56
- to_a '* * * * mon-wed', [ [0], nil, nil, nil, nil, [1, 2, 3], nil, nil ]
57
- to_a '* * * * 7', [ [0], nil, nil, nil, nil, [0], nil, nil ]
58
- to_a '* * * * 0', [ [0], nil, nil, nil, nil, [0], nil, nil ]
59
- to_a '* * * * 0,1', [ [0], nil, nil, nil, nil, [0,1], nil, nil ]
60
- to_a '* * * * 7,1', [ [0], nil, nil, nil, nil, [0,1], nil, nil ]
61
- to_a '* * * * 7,0', [ [0], nil, nil, nil, nil, [0], nil, nil ]
62
- to_a '* * * * sun,2-4', [ [0], nil, nil, nil, nil, [0, 2, 3, 4], nil, nil ]
63
-
64
- to_a '* * * * sun,mon-tue', [ [0], nil, nil, nil, nil, [0, 1, 2], nil, nil ]
65
-
66
- to_a '* * * * * *', [ nil, nil, nil, nil, nil, nil, nil, nil ]
67
- to_a '1 * * * * *', [ [1], nil, nil, nil, nil, nil, nil, nil ]
68
- to_a '7 10-12 * * * *', [ [7], [10, 11, 12], nil, nil, nil, nil, nil, nil ]
69
- to_a '1-5 * * * * *', [ [1,2,3,4,5], nil, nil, nil, nil, nil, nil, nil ]
70
-
71
- to_a '0 0 1 1 *', [ [0], [0], [0], [1], [1], nil, nil, nil ]
72
-
73
- to_a '52 0 * * *', [ [0], [52], [0], nil, nil, nil, nil, nil ]
74
-
75
- #if ruby18?
76
- # to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
77
- #else
78
- # to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
79
- #end
80
- #
81
- # as reported by Aimee Rose in
82
- # https://github.com/jmettraux/rufus-scheduler/issues/56
83
- to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
84
-
85
- #if ruby18?
86
- # to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
87
- #else
88
- # to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
89
- #end
90
- to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
91
-
92
- # modulo forms work for five-field forms
93
- to_a '*/17 * * * *', [[0], [0, 17, 34, 51], nil, nil, nil, nil, nil, nil]
94
- to_a '13 */17 * * *', [[0], [13], [0, 17], nil, nil, nil, nil, nil]
95
-
96
- # modulo forms work for six-field forms
97
- to_a '*/17 * * * * *', [[0, 17, 34, 51], nil, nil, nil, nil, nil, nil, nil]
98
- to_a '13 */17 * * * *', [[13], [0, 17, 34, 51], nil, nil, nil, nil, nil, nil]
99
- end
100
-
101
- it 'rejects invalid weekday expressions' do
102
-
103
- expect { cl '0 17 * * MON_FRI' }.to raise_error
104
- # underline instead of dash
105
-
106
- expect { cl '* * * * 9' }.to raise_error
107
- expect { cl '* * * * 0-12' }.to raise_error
108
- expect { cl '* * * * BLABLA' }.to raise_error
109
- end
110
-
111
- it 'rejects invalid cronlines' do
112
-
113
- expect { cl '* nada * * 9' }.to raise_error(ArgumentError)
114
- end
115
-
116
- it 'interprets cron strings with TZ correctly' do
117
-
118
- to_a('* * * * * EST', [ [0], nil, nil, nil, nil, nil, nil, 'EST' ])
119
- to_a('* * * * * * EST', [ nil, nil, nil, nil, nil, nil, nil, 'EST' ])
120
-
121
- to_a(
122
- '* * * * * * America/Chicago',
123
- [ nil, nil, nil, nil, nil, nil, nil, 'America/Chicago' ])
124
- to_a(
125
- '* * * * * * America/New_York',
126
- [ nil, nil, nil, nil, nil, nil, nil, 'America/New_York' ])
127
-
128
- expect { cl '* * * * * NotATimeZone' }.to raise_error
129
- expect { cl '* * * * * * NotATimeZone' }.to raise_error
130
- end
131
-
132
- it 'interprets cron strings with / (slashes) correctly' do
133
-
134
- to_a(
135
- '0 */2 * * *',
136
- [ [0], [0], (0..23).select { |e| e.even? }, nil, nil, nil, nil, nil ])
137
- to_a(
138
- '0 0-23/2 * * *',
139
- [ [0], [0], (0..23).select { |e| e.even? }, nil, nil, nil, nil, nil ])
140
- to_a(
141
- '0 7-23/2 * * *',
142
- [ [0], [0], (7..23).select { |e| e.odd? }, nil, nil, nil, nil, nil ])
143
- to_a(
144
- '*/10 * * * *',
145
- [ [0], [0, 10, 20, 30, 40, 50], nil, nil, nil, nil, nil, nil ])
146
-
147
- # fighting https://github.com/jmettraux/rufus-scheduler/issues/65
148
- #
149
- to_a(
150
- '*/10 * * * * Europe/Berlin',
151
- [ [0], [ 0, 10, 20, 30, 40, 50], nil, nil, nil, nil, nil, 'Europe/Berlin' ])
152
- end
153
-
154
- it 'accepts lonely / (slashes) (like <= 2.0.19 did)' do
155
-
156
- # fighting https://github.com/jmettraux/rufus-scheduler/issues/65
157
-
158
- to_a(
159
- '/10 * * * *',
160
- [ [0], [ 0, 10, 20, 30, 40, 50], nil, nil, nil, nil, nil, nil ])
161
- end
162
-
163
- it 'rejects / for days (every other wednesday)' do
164
-
165
- expect {
166
- Rufus::Scheduler::CronLine.new('* * * * wed/2')
167
- }.to raise_error(ArgumentError)
168
- end
169
-
170
- it 'does not support ranges for monthdays (sun#1-sun#2)' do
171
-
172
- expect {
173
- Rufus::Scheduler::CronLine.new('* * * * sun#1-sun#2')
174
- }.to raise_error(ArgumentError)
175
- end
176
-
177
- it 'accepts items with initial 0' do
178
-
179
- to_a(
180
- '09 * * * *', [ [0], [9], nil, nil, nil, nil, nil, nil ])
181
- to_a(
182
- '09-12 * * * *', [ [0], [9, 10, 11, 12], nil, nil, nil, nil, nil, nil ])
183
- to_a(
184
- '07-08 * * * *', [ [0], [7, 8], nil, nil, nil, nil, nil, nil ])
185
- to_a(
186
- '* */08 * * *', [ [0], nil, [0, 8, 16], nil, nil, nil, nil, nil ])
187
- to_a(
188
- '* */07 * * *', [ [0], nil, [0, 7, 14, 21], nil, nil, nil, nil, nil ])
189
- to_a(
190
- '* 01-09/04 * * *', [ [0], nil, [1, 5, 9], nil, nil, nil, nil, nil ])
191
- to_a(
192
- '* * * * 06', [ [0], nil, nil, nil, nil, [6], nil, nil ])
193
- end
194
-
195
- it 'interprets cron strings with L correctly' do
196
-
197
- to_a(
198
- '* * L * *', [[0], nil, nil, ['L'], nil, nil, nil, nil ])
199
- to_a(
200
- '* * 2-5,L * *', [[0], nil, nil, [2,3,4,5,'L'], nil, nil, nil, nil ])
201
- to_a(
202
- '* * */8,L * *', [[0], nil, nil, [1,9,17,25,'L'], nil, nil, nil, nil ])
203
- end
204
-
205
- it 'does not support ranges for L' do
206
-
207
- expect { cl '* * 15-L * *'}.to raise_error(ArgumentError)
208
- expect { cl '* * L/4 * *'}.to raise_error(ArgumentError)
209
- end
210
-
211
- it 'does not support multiple Ls' do
212
-
213
- expect { cl '* * L,L * *'}.to raise_error(ArgumentError)
214
- end
215
-
216
- it 'raises if L is used for something else than days' do
217
-
218
- expect { cl '* L * * *'}.to raise_error(ArgumentError)
219
- end
220
-
221
- it 'raises for out of range input' do
222
-
223
- expect { cl '60-62 * * * *'}.to raise_error(ArgumentError)
224
- expect { cl '62 * * * *'}.to raise_error(ArgumentError)
225
- expect { cl '60 * * * *'}.to raise_error(ArgumentError)
226
- expect { cl '* 25-26 * * *'}.to raise_error(ArgumentError)
227
- expect { cl '* 25 * * *'}.to raise_error(ArgumentError)
228
- #
229
- # as reported by Aimee Rose in
230
- # https://github.com/jmettraux/rufus-scheduler/pull/58
231
- end
232
-
233
- it 'sorts seconds' do
234
-
235
- to_a(
236
- '23,30,10 * * * * *', [ [10,23,30], nil, nil, nil, nil, nil, nil, nil ])
237
- end
238
-
239
- it 'sorts minutes' do
240
-
241
- to_a(
242
- '23,30,10 * * * * ', [ [0], [10,23,30], nil, nil, nil, nil, nil, nil ])
243
- end
244
-
245
- it 'sorts days' do
246
-
247
- to_a(
248
- '* * 14,7 * * ', [ [0], nil, nil, [7, 14], nil, nil, nil, nil ])
249
- end
250
-
251
- it 'sorts months' do
252
-
253
- to_a(
254
- '* * * 11,3,4 * ', [ [0], nil, nil, nil, [3,4,11], nil, nil, nil ])
255
- end
256
-
257
- it 'sorts days of week' do
258
-
259
- to_a(
260
- '* * * * Sun,Fri,2 ', [ [0], nil, nil, nil, nil, [0, 2, 5], nil, nil ])
261
- end
262
- end
263
-
264
- describe '#next_time' do
265
-
266
- it 'computes the next occurence correctly' do
267
-
268
- in_zone 'Europe/Berlin' do
269
-
270
- now = Time.at(0) - 3600
271
-
272
- expect(nt('* * * * *', now)).to eq(now + 60)
273
- expect(nt('* * * * sun', now)).to eq(now + 259200)
274
- expect(nt('* * * * * *', now)).to eq(now + 1)
275
- expect(nt('* * 13 * fri', now)).to eq(now + 3715200)
276
-
277
- expect(nt('10 12 13 12 *', now)).to eq(now + 29938200)
278
- # this one is slow (1 year == 3 seconds)
279
- #
280
- # historical note:
281
- # (comment made in 2006 or 2007, the underlying libs got better and
282
- # that slowness is gone)
283
-
284
- expect(nt('0 0 * * thu', now)).to eq(now + 604800)
285
- expect(nt('00 0 * * thu', now)).to eq(now + 604800)
286
-
287
- expect(nt('0 0 * * *', now)).to eq(now + 24 * 3600)
288
- expect(nt('0 24 * * *', now)).to eq(now + 24 * 3600)
289
-
290
- now = local(2008, 12, 31, 23, 59, 59, 0)
291
-
292
- expect(nt('* * * * *', now)).to eq(now + 1)
293
- end
294
- end
295
-
296
- it 'computes the next occurence correctly in local TZ (TZ not specified)' do
297
-
298
- now = local(1970, 1, 1)
299
-
300
- expect(nt('* * * * *', now)).to eq(local(1970, 1, 1, 0, 1))
301
- expect(nt('* * * * sun', now)).to eq(local(1970, 1, 4))
302
- expect(nt('* * * * * *', now)).to eq(local(1970, 1, 1, 0, 0, 1))
303
- expect(nt('* * 13 * fri', now)).to eq(local(1970, 2, 13))
304
-
305
- expect(nt('10 12 13 12 *', now)).to eq(local(1970, 12, 13, 12, 10))
306
- # this one is slow (1 year == 3 seconds)
307
- expect(nt('* * 1 6 *', now)).to eq(local(1970, 6, 1))
308
-
309
- expect(nt('0 0 * * thu', now)).to eq(local(1970, 1, 8))
310
- end
311
-
312
- it 'computes the next occurence correctly in UTC (TZ specified)' do
313
-
314
- zone = 'Europe/Stockholm'
315
- now = in_zone(zone) { Time.local(1970, 1, 1) }
316
-
317
- expect(nt("* * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 1))
318
- expect(nt("* * * * sun #{zone}", now)).to eq(utc(1970, 1, 3, 23))
319
- expect(nt("* * * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 0, 1))
320
- expect(nt("* * 13 * fri #{zone}", now)).to eq(utc(1970, 2, 12, 23))
321
-
322
- expect(nt("10 12 13 12 * #{zone}", now)).to eq(utc(1970, 12, 13, 11, 10))
323
- expect(nt("* * 1 6 * #{zone}", now)).to eq(utc(1970, 5, 31, 23))
324
-
325
- expect(nt("0 0 * * thu #{zone}", now)).to eq(utc(1970, 1, 7, 23))
326
- end
327
-
328
- it 'computes the next time correctly when there is a sun#2 involved' do
329
-
330
- expect(nt('* * * * sun#1', local(1970, 1, 1))).to eq(local(1970, 1, 4))
331
- expect(nt('* * * * sun#2', local(1970, 1, 1))).to eq(local(1970, 1, 11))
332
-
333
- expect(nt('* * * * sun#2', local(1970, 1, 12))).to eq(local(1970, 2, 8))
334
- end
335
-
336
- it 'computes next time correctly when there is a sun#2,sun#3 involved' do
337
-
338
- expect(
339
- nt('* * * * sun#2,sun#3', local(1970, 1, 1))).to eq(local(1970, 1, 11))
340
- expect(
341
- nt('* * * * sun#2,sun#3', local(1970, 1, 12))).to eq(local(1970, 1, 18))
342
- end
343
-
344
- it 'understands sun#L' do
345
-
346
- expect(nt('* * * * sun#L', local(1970, 1, 1))).to eq(local(1970, 1, 25))
347
- end
348
-
349
- it 'understands sun#-1' do
350
-
351
- expect(nt('* * * * sun#-1', local(1970, 1, 1))).to eq(local(1970, 1, 25))
352
- end
353
-
354
- it 'understands sun#-2' do
355
-
356
- expect(nt('* * * * sun#-2', local(1970, 1, 1))).to eq(local(1970, 1, 18))
357
- end
358
-
359
- it 'computes the next time correctly when "L" (last day of month)' do
360
-
361
- expect(nt('* * L * *', lo(1970, 1, 1))).to eq(lo(1970, 1, 31))
362
- expect(nt('* * L * *', lo(1970, 2, 1))).to eq(lo(1970, 2, 28))
363
- expect(nt('* * L * *', lo(1972, 2, 1))).to eq(lo(1972, 2, 29))
364
- expect(nt('* * L * *', lo(1970, 4, 1))).to eq(lo(1970, 4, 30))
365
- end
366
-
367
- it 'returns a time with subseconds chopped off' do
368
-
369
- expect(
370
- nt('* * * * *', Time.now).usec).to eq(0)
371
- expect(
372
- nt('* * * * *', Time.now).iso8601(10).match(/\.0+[^\d]/)).not_to eq(nil)
373
- end
374
-
375
- # New York EST: UTC-5
376
- # summer (dst) EDT: UTC-4
377
-
378
- # gh-127
379
- #
380
- it 'survives TZInfo::AmbiguousTime' do
381
-
382
- if ruby18? or jruby?
383
- expect(
384
- ntz(
385
- '30 1 31 10 * America/New_York',
386
- ltz('America/New_York', 2004, 10, 1)
387
- ).strftime('%Y-%m-%d %H:%M:%S')
388
- ).to eq('2004-10-31 01:30:00')
389
- else
390
- expect(
391
- ntz(
392
- '30 1 31 10 * America/New_York',
393
- ltz('America/New_York', 2004, 10, 1)
394
- )
395
- ).to eq(ltz('America/New_York', 2004, 10, 31, 1, 30, 0))
396
- end
397
- end
398
-
399
- # gh-127
400
- #
401
- it 'survives TZInfo::PeriodNotFound' do
402
-
403
- expect(
404
- ntz(
405
- '0 2 9 3 * America/New_York',
406
- ltz('America/New_York', 2014, 3, 1)
407
- )
408
- ).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
409
- end
410
-
411
- it 'understands six-field crontabs' do
412
-
413
- expect(nt('* * * * * *',local(1970,1,1,1,1,1))).to(
414
- eq(local(1970,1,1,1,1,2))
415
- )
416
- expect(nt('* * * * * *',local(1970,1,1,1,1,2))).to(
417
- eq(local(1970,1,1,1,1,3))
418
- )
419
- expect(nt('*/10 * * * * *',local(1970,1,1,1,1,0))).to(
420
- eq(local(1970,1,1,1,1,10))
421
- )
422
- expect(nt('*/10 * * * * *',local(1970,1,1,1,1,9))).to(
423
- eq(local(1970,1,1,1,1,10))
424
- )
425
- expect(nt('*/10 * * * * *',local(1970,1,1,1,1,10))).to(
426
- eq(local(1970,1,1,1,1,20))
427
- )
428
- expect(nt('*/10 * * * * *',local(1970,1,1,1,1,40))).to(
429
- eq(local(1970,1,1,1,1,50))
430
- )
431
- expect(nt('*/10 * * * * *',local(1970,1,1,1,1,49))).to(
432
- eq(local(1970,1,1,1,1,50))
433
- )
434
- expect(nt('*/10 * * * * *',local(1970,1,1,1,1,50))).to(
435
- eq(local(1970,1,1,1,2,00)) # FAILS: skips a minute to 2:50, not 2:00
436
- )
437
- end
438
- end
439
-
440
- describe '#next_second' do
441
- [
442
- [ '*/10 * * * * *', local(1970,1,1,1,1, 0), 0 ], # 0 sec to 0s mark
443
- [ '*/10 * * * * *', local(1970,1,1,1,1, 1), 9 ], # 9 sec to 10s mark
444
- [ '*/10 * * * * *', local(1970,1,1,1,1, 9), 1 ], # 1 sec to 10s mark
445
- [ '*/10 * * * * *', local(1970,1,1,1,1,10), 0 ], # 0 sec to 10s mark
446
- [ '*/10 * * * * *', local(1970,1,1,1,1,11), 9 ], # 9 sec to 20s mark
447
- [ '*/10 * * * * *', local(1970,1,1,1,1,19), 1 ], # 1 sec to 20s mark
448
- [ '*/10 * * * * *', local(1970,1,1,1,1,20), 0 ], # 0 sec to 20s mark
449
- [ '*/10 * * * * *', local(1970,1,1,1,1,21), 9 ], # 1 sec to 30s mark
450
- # ...
451
- [ '*/10 * * * * *', local(1970,1,1,1,1,49), 1 ], # 9 sec to 50s mark
452
- [ '*/10 * * * * *', local(1970,1,1,1,1,50), 0 ], # 0 sec to 50s mark
453
- [ '*/10 * * * * *', local(1970,1,1,1,1,51), 9 ], # FAILS: gives 59
454
- ].each do |cronline,now,sec|
455
- it "understands that next_second('#{cronline}',#{now}) is #{sec}" do
456
- expect(ns(cronline,now)).to eq(sec)
457
- end
458
- end
459
- end
460
-
461
- describe '#previous_time' do
462
-
463
- it 'returns the previous time the cron should have triggered' do
464
-
465
- expect(
466
- pt('* * * * sun', lo(1970, 1, 1))).to eq(lo(1969, 12, 28, 23, 59, 00))
467
- expect(
468
- pt('* * 13 * *', lo(1970, 1, 1))).to eq(lo(1969, 12, 13, 23, 59, 00))
469
- expect(
470
- pt('0 12 13 * *', lo(1970, 1, 1))).to eq(lo(1969, 12, 13, 12, 00))
471
- expect(
472
- pt('0 0 2 1 *', lo(1970, 1, 1))).to eq(lo(1969, 1, 2, 0, 00))
473
-
474
- expect(
475
- pt('* * * * * sun', lo(1970, 1, 1))).to eq(lo(1969, 12, 28, 23, 59, 59))
476
- end
477
-
478
- # New York EST: UTC-5
479
- # summer (dst) EDT: UTC-4
480
-
481
- # gh-127
482
- #
483
- it 'survives TZInfo::AmbiguousTime' do
484
-
485
- if ruby18? or jruby?
486
- expect(
487
- ptz(
488
- '30 1 31 10 * America/New_York',
489
- ltz('America/New_York', 2004, 10, 31, 14, 30, 0)
490
- ).strftime('%Y-%m-%d %H:%M:%S')
491
- ).to eq('2004-10-31 01:30:00')
492
- else
493
- expect(
494
- ptz(
495
- '30 1 31 10 * America/New_York',
496
- ltz('America/New_York', 2004, 10, 31, 14, 30, 0)
497
- )
498
- ).to eq(ltz('America/New_York', 2004, 10, 31, 1, 30, 0))
499
- end
500
- end
501
-
502
- # gh-127
503
- #
504
- it 'survives TZInfo::PeriodNotFound' do
505
-
506
- expect(
507
- ptz(
508
- '0 2 9 3 * America/New_York',
509
- ltz('America/New_York', 2015, 3, 9, 12, 0, 0)
510
- )
511
- ).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
512
- end
513
-
514
- it 'computes correctly when * 0,10,20' do
515
-
516
- expect(
517
- pt('* 0,10,20 * * *', lo(2000, 1, 1))).to eq(
518
- lo(1999, 12, 31, 20, 59, 00))
519
- end
520
-
521
- it 'computes correctly when * */10' do
522
-
523
- expect(
524
- pt('* */10 * * *', lo(2000, 1, 1))).to eq(
525
- lo(1999, 12, 31, 20, 59, 00))
526
- end
527
- end
528
-
529
- describe '#matches?' do
530
-
531
- # it 'matches correctly in UTC (TZ not specified)' do
532
- #
533
- # match '* * * * *', utc(1970, 1, 1, 0, 1)
534
- # match '* * * * sun', utc(1970, 1, 4)
535
- # match '* * * * * *', utc(1970, 1, 1, 0, 0, 1)
536
- # match '* * 13 * fri', utc(1970, 2, 13)
537
- #
538
- # match '10 12 13 12 *', utc(1970, 12, 13, 12, 10)
539
- # match '* * 1 6 *', utc(1970, 6, 1)
540
- #
541
- # match '0 0 * * thu', utc(1970, 1, 8)
542
- #
543
- # match '0 0 1 1 *', utc(2012, 1, 1)
544
- # no_match '0 0 1 1 *', utc(2012, 1, 1, 1, 0)
545
- # end
546
-
547
- it 'matches correctly in local TZ (TZ not specified)' do
548
-
549
- match '* * * * *', local(1970, 1, 1, 0, 1)
550
- match '* * * * sun', local(1970, 1, 4)
551
- match '* * * * * *', local(1970, 1, 1, 0, 0, 1)
552
- match '* * 13 * fri', local(1970, 2, 13)
553
-
554
- match '10 12 13 12 *', local(1970, 12, 13, 12, 10)
555
- match '* * 1 6 *', local(1970, 6, 1)
556
-
557
- match '0 0 * * thu', local(1970, 1, 8)
558
-
559
- match '0 0 1 1 *', local(2012, 1, 1)
560
- no_match '0 0 1 1 *', local(2012, 1, 1, 1, 0)
561
- end
562
-
563
- it 'matches correctly in UTC (TZ specified)' do
564
-
565
- zone = 'Europe/Stockholm'
566
-
567
- match "* * * * * #{zone}", utc(1969, 12, 31, 23, 1)
568
- match "* * * * sun #{zone}", utc(1970, 1, 3, 23)
569
- match "* * * * * * #{zone}", utc(1969, 12, 31, 23, 0, 1)
570
- match "* * 13 * fri #{zone}", utc(1970, 2, 12, 23)
571
-
572
- match "10 12 13 12 * #{zone}", utc(1970, 12, 13, 11, 10)
573
- match "* * 1 6 * #{zone}", utc(1970, 5, 31, 23)
574
-
575
- match "0 0 * * thu #{zone}", utc(1970, 1, 7, 23)
576
- end
577
-
578
- it 'matches correctly when there is a sun#2 involved' do
579
-
580
- match '* * 13 * fri#2', utc(1970, 2, 13)
581
- no_match '* * 13 * fri#2', utc(1970, 2, 20)
582
- end
583
-
584
- it 'matches correctly when there is a L involved' do
585
-
586
- match '* * L * *', utc(1970, 1, 31)
587
- no_match '* * L * *', utc(1970, 1, 30)
588
- end
589
-
590
- it 'matches correctly when there is a sun#2,sun#3 involved' do
591
-
592
- no_match '* * * * sun#2,sun#3', local(1970, 1, 4)
593
- match '* * * * sun#2,sun#3', local(1970, 1, 11)
594
- match '* * * * sun#2,sun#3', local(1970, 1, 18)
595
- no_match '* * * * sun#2,sun#3', local(1970, 1, 25)
596
- end
597
-
598
- it 'matches correctly for seconds' do
599
-
600
- match '* * * * * *', local(1970, 1, 11)
601
- match '* * * * * *', local(1970, 1, 11, 0, 0, 13)
602
- end
603
-
604
- it 'matches correctly for seconds / interval' do
605
-
606
- match '*/2 * * * * *', local(1970, 1, 11)
607
- match '*/5 * * * * *', local(1970, 1, 11)
608
- match '*/5 * * * * *', local(1970, 1, 11, 0, 0, 0)
609
- no_match '*/5 * * * * *', local(1970, 1, 11, 0, 0, 1)
610
- match '*/5 * * * * *', local(1970, 1, 11, 0, 0, 5)
611
- match '*/2 * * * * *', local(1970, 1, 11, 0, 0, 2)
612
- match '*/2 * * * * *', local(1970, 1, 11, 0, 0, 2, 500)
613
- end
614
- end
615
-
616
- describe '#monthdays' do
617
-
618
- it 'returns the appropriate "sun#2"-like string' do
619
-
620
- class Rufus::Scheduler::CronLine
621
- public :monthdays
622
- end
623
-
624
- cl = Rufus::Scheduler::CronLine.new('* * * * *')
625
-
626
- expect(cl.monthdays(local(1970, 1, 1))).to eq(%w[ thu#1 thu#-5 ])
627
- expect(cl.monthdays(local(1970, 1, 7))).to eq(%w[ wed#1 wed#-4 ])
628
- expect(cl.monthdays(local(1970, 1, 14))).to eq(%w[ wed#2 wed#-3 ])
629
-
630
- expect(cl.monthdays(local(2011, 3, 11))).to eq(%w[ fri#2 fri#-3 ])
631
- end
632
- end
633
-
634
- describe '#frequency' do
635
-
636
- it 'returns the shortest delta between two occurrences' do
637
-
638
- expect(Rufus::Scheduler::CronLine.new(
639
- '* * * * *').frequency).to eq(60)
640
- expect(Rufus::Scheduler::CronLine.new(
641
- '* * * * * *').frequency).to eq(1)
642
-
643
- expect(Rufus::Scheduler::CronLine.new(
644
- '5 23 * * *').frequency).to eq(24 * 3600)
645
- expect(Rufus::Scheduler::CronLine.new(
646
- '5 * * * *').frequency).to eq(3600)
647
- expect(Rufus::Scheduler::CronLine.new(
648
- '10,20,30 * * * *').frequency).to eq(600)
649
-
650
- expect(Rufus::Scheduler::CronLine.new(
651
- '10,20,30 * * * * *').frequency).to eq(10)
652
- end
653
-
654
- it 'spots B-A vs C-B asymmetry in five-field forms' do
655
-
656
- expect(Rufus::Scheduler::CronLine.new(
657
- '10,17,30 * * * *').frequency).to eq(7 * 60)
658
- expect(Rufus::Scheduler::CronLine.new(
659
- '10,23,30 * * * *').frequency).to eq(7 * 60)
660
- expect(Rufus::Scheduler::CronLine.new(
661
- '23,10,30 * * * *').frequency).to eq(7 * 60)
662
- end
663
-
664
- it 'spots B-A vs C-B asymmetry in six-field forms' do
665
-
666
- expect(Rufus::Scheduler::CronLine.new(
667
- '10,17,30 * * * * *').frequency).to eq(7)
668
- expect(Rufus::Scheduler::CronLine.new(
669
- '10,23,30 * * * * *').frequency).to eq(7)
670
- expect(Rufus::Scheduler::CronLine.new(
671
- '23,10,30 * * * * *').frequency).to eq(7)
672
- end
673
-
674
- it 'handles crontab steps syntax in five-field forms' do
675
-
676
- expect(Rufus::Scheduler::CronLine.new(
677
- '*/10 * * * *').frequency).to eq(10 * 60)
678
- expect(Rufus::Scheduler::CronLine.new(
679
- '* */10 * * *').frequency).to eq(60) # "*" all minutes [0..59]
680
- expect(Rufus::Scheduler::CronLine.new(
681
- '0 */10 * * *').frequency).to eq(4 * 60 * 60) # 2000 to 0000
682
- end
683
-
684
- it 'handles crontab steps syntax in six-field forms' do
685
-
686
- expect(Rufus::Scheduler::CronLine.new(
687
- '*/10 * * * * *').frequency).to eq(10)
688
- expect(Rufus::Scheduler::CronLine.new(
689
- '* */10 * * * *').frequency).to eq(1) # "*" all seconds [0..59]
690
- expect(Rufus::Scheduler::CronLine.new(
691
- '0 */10 * * * *').frequency).to eq(10 * 60)
692
- end
693
- end
694
-
695
- describe '#brute_frequency' do
696
-
697
- it 'returns the shortest delta between two occurrences' do
698
-
699
- expect(Rufus::Scheduler::CronLine.new(
700
- '* * * * *').brute_frequency).to eq(60)
701
- expect(Rufus::Scheduler::CronLine.new(
702
- '* * * * * *').brute_frequency).to eq(1)
703
-
704
- expect(Rufus::Scheduler::CronLine.new(
705
- '5 23 * * *').brute_frequency).to eq(24 * 3600)
706
- expect(Rufus::Scheduler::CronLine.new(
707
- '5 * * * *').brute_frequency).to eq(3600)
708
- expect(Rufus::Scheduler::CronLine.new(
709
- '10,20,30 * * * *').brute_frequency).to eq(600)
710
-
711
- #Rufus::Scheduler::CronLine.new(
712
- # '10,20,30 * * * * *').brute_frequency.should == 10
713
- #
714
- # takes > 20s ...
715
- end
716
-
717
- # some combos only appear every other year...
718
- #
719
- it 'does not go into an infinite loop' do
720
-
721
- expect(Rufus::Scheduler::CronLine.new(
722
- '1 2 3 4 5').brute_frequency).to eq(31622400)
723
- end
724
-
725
- it 'spots B-A vs C-B asymmetry in five-field forms' do
726
-
727
- expect(Rufus::Scheduler::CronLine.new(
728
- '10,17,30 * * * *').brute_frequency).to eq(7 * 60)
729
- expect(Rufus::Scheduler::CronLine.new(
730
- '10,23,30 * * * *').brute_frequency).to eq(7 * 60)
731
- end
732
-
733
- it 'spots B-A vs C-B asymmetry in six-field forms' do
734
-
735
- expect(Rufus::Scheduler::CronLine.new(
736
- '10,17,30 * * * * *').brute_frequency).to eq(7)
737
- expect(Rufus::Scheduler::CronLine.new(
738
- '10,23,30 * * * * *').brute_frequency).to eq(7)
739
- end
740
-
741
- it 'handles crontab modulo syntax in five-field forms' do
742
-
743
- expect(Rufus::Scheduler::CronLine.new(
744
- '*/10 * * * *').brute_frequency).to eq(10 * 60)
745
- expect(Rufus::Scheduler::CronLine.new(
746
- '* */10 * * *').brute_frequency).to eq(60) # "*" all minutes [0..59]
747
- expect(Rufus::Scheduler::CronLine.new(
748
- '0 */10 * * *').brute_frequency).to eq(4 * 60 * 60) # 2000 to 0000
749
- end
750
-
751
- it 'handles crontab modulo syntax in six-field forms' do
752
-
753
- expect(Rufus::Scheduler::CronLine.new(
754
- '*/10 * * * * *').brute_frequency).to eq(10)
755
- expect(Rufus::Scheduler::CronLine.new(
756
- '* */10 * * * *').brute_frequency).to eq(1) # "*" all seconds [0..59]
757
- expect(Rufus::Scheduler::CronLine.new(
758
- '0 */10 * * * *').brute_frequency).to eq(10 * 60)
759
- end
760
- end
761
-
762
- context 'summer time' do
763
-
764
- # let's assume summer time jumps always occur on sundays
765
-
766
- # cf gh-114
767
- #
768
- it 'schedules correctly through a switch into summer time' do
769
-
770
- in_zone 'Europe/Berlin' do
771
-
772
- # find the summer jump
773
-
774
- j = Time.parse('2014-02-28 12:00')
775
- loop do
776
- jj = j + 24 * 3600
777
- break if jj.isdst
778
- j = jj
779
- end
780
-
781
- # test
782
-
783
- friday = j - 24 * 3600 # one day before
784
-
785
- # verify the playground...
786
- #
787
- expect(friday.isdst).to eq(false)
788
- expect((friday + 24 * 3600 * 3).isdst).to eq(true)
789
-
790
- cl0 = Rufus::Scheduler::CronLine.new('02 00 * * 1,2,3,4,5')
791
- cl1 = Rufus::Scheduler::CronLine.new('45 08 * * 1,2,3,4,5')
792
-
793
- n0 = cl0.next_time(friday)
794
- n1 = cl1.next_time(friday)
795
-
796
- expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 TUE')
797
- expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
798
-
799
- expect(n0.isdst).to eq(true)
800
- expect(n1.isdst).to eq(true)
801
-
802
- expect(
803
- (n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('23:02:00 FRI')
804
- expect(
805
- (n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('07:45:00 FRI')
806
- end
807
- end
808
-
809
- it 'schedules correctly through a switch out of summer time' do
810
-
811
- in_zone 'Europe/Berlin' do
812
-
813
- # find the winter jump
814
-
815
- j = Time.parse('2014-08-31 12:00')
816
- loop do
817
- jj = j + 24 * 3600
818
- break if jj.isdst == false
819
- j = jj
820
- end
821
-
822
- # test
823
-
824
- friday = j - 24 * 3600 # one day before
825
-
826
- # verify the playground...
827
- #
828
- expect(friday.isdst).to eq(true)
829
- expect((friday + 24 * 3600 * 3).isdst).to eq(false)
830
-
831
- cl0 = Rufus::Scheduler::CronLine.new('02 00 * * 1,2,3,4,5')
832
- cl1 = Rufus::Scheduler::CronLine.new('45 08 * * 1,2,3,4,5')
833
-
834
- n0 = cl0.next_time(friday)
835
- n1 = cl1.next_time(friday)
836
-
837
- expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 MON')
838
- expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
839
-
840
- expect(n0.isdst).to eq(false)
841
- expect(n1.isdst).to eq(false)
842
-
843
- expect(
844
- (n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('01:02:00 FRI')
845
- expect(
846
- (n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('09:45:00 FRI')
847
- end
848
- end
849
-
850
- it 'correctly increments through a DST transition' do
851
-
852
- expect(
853
- nt('* * * * * America/Los_Angeles', Time.utc(2015, 3, 8, 9, 59))
854
- ).to eq(Time.utc(2015, 3, 8, 10, 00))
855
- end
856
-
857
- it 'correctly increments every minute through a DST transition' do
858
-
859
- in_zone 'America/Los_Angeles' do
860
-
861
- line = cl('* * * * * America/Los_Angeles')
862
-
863
- t = Time.local(2015, 3, 8, 1, 57)
864
-
865
- points =
866
- [ 0, 1, 2, 3 ].collect do
867
- t = line.next_time(t)
868
- t.strftime('%H:%M:%Sl') + ' ' + t.dup.utc.strftime('%H:%M:%Su')
869
- end
870
-
871
- expect(points).to eq(
872
- [
873
- '01:58:00l 09:58:00u',
874
- '01:59:00l 09:59:00u',
875
- '03:00:00l 10:00:00u',
876
- '03:01:00l 10:01:00u'
877
- ]
878
- )
879
- end
880
- end
881
-
882
- it 'correctly decrements through a DST transition' do
883
-
884
- expect(
885
- pt('* * * * * America/Los_Angeles', Time.utc(2015, 3, 8, 10, 00))
886
- ).to eq(Time.utc(2015, 3, 8, 9, 59))
887
- end
888
-
889
- it 'correctly decrements every minute through a DST transition' do
890
-
891
- in_zone 'America/Los_Angeles' do
892
-
893
- line = cl('* * * * * America/Los_Angeles')
894
-
895
- t = Time.local(2015, 3, 8, 3, 2)
896
-
897
- points =
898
- [ 0, 1, 2, 3 ].collect do
899
- t = line.previous_time(t)
900
- t.strftime('%H:%M:%Sl') + ' ' + t.dup.utc.strftime('%H:%M:%Su')
901
- end
902
-
903
- expect(points).to eq(
904
- [
905
- '03:01:00l 10:01:00u',
906
- '03:00:00l 10:00:00u',
907
- '01:59:00l 09:59:00u',
908
- '01:58:00l 09:58:00u'
909
- ]
910
- )
911
- end
912
- end
913
- end
914
- end
915
-