rufus-scheduler 3.0.7 → 3.0.8
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 +9 -1
- data/CREDITS.txt +2 -0
- data/README.md +7 -3
- data/TODO.txt +4 -0
- data/lib/rufus/scheduler.rb +12 -7
- data/lib/rufus/scheduler/cronline.rb +18 -2
- data/lib/rufus/scheduler/jobs.rb +6 -3
- data/lib/rufus/scheduler/util.rb +6 -5
- data/rufus-scheduler.gemspec +1 -0
- data/spec/basics_spec.rb +49 -0
- data/spec/cronline_spec.rb +231 -126
- data/spec/custom_locks_spec.rb +2 -2
- data/spec/error_spec.rb +12 -12
- data/spec/job_array_spec.rb +2 -2
- data/spec/job_at_spec.rb +4 -4
- data/spec/job_cron_spec.rb +7 -7
- data/spec/job_every_spec.rb +9 -9
- data/spec/job_interval_spec.rb +5 -5
- data/spec/job_repeat_spec.rb +45 -44
- data/spec/job_spec.rb +67 -67
- data/spec/lockfile_spec.rb +5 -5
- data/spec/parse_spec.rb +120 -78
- data/spec/schedule_at_spec.rb +46 -17
- data/spec/schedule_cron_spec.rb +6 -6
- data/spec/schedule_every_spec.rb +12 -12
- data/spec/schedule_in_spec.rb +8 -8
- data/spec/schedule_interval_spec.rb +13 -13
- data/spec/scheduler_spec.rb +134 -118
- data/spec/spec_helper.rb +50 -1
- data/spec/threads_spec.rb +4 -4
- metadata +20 -9
data/CHANGELOG.txt
CHANGED
@@ -2,13 +2,21 @@
|
|
2
2
|
= rufus-scheduler CHANGELOG.txt
|
3
3
|
|
4
4
|
|
5
|
+
== rufus-scheduler - 3.0.8 released 2014/06/09
|
6
|
+
|
7
|
+
- handle TZInfo errors on DST transitions, thanks https://github.com/junhanamaki
|
8
|
+
- implement Scheduler#up?
|
9
|
+
- let schedule and schedule_at use Chronic if present
|
10
|
+
- let Rufus::Scheduler.parse use Chronic if present
|
11
|
+
|
12
|
+
|
5
13
|
== rufus-scheduler - 3.0.7 released 2014/03/18
|
6
14
|
|
7
15
|
- implement Scheduler #occurrences and #timeline, inspired by kreynolds
|
8
16
|
- implement Job #last_work_time and #mean_work_time
|
9
17
|
- implement Job#count
|
10
18
|
- add more info to the stderr error output (scheduler/tz info)
|
11
|
-
- prevent skipping a day on
|
19
|
+
- prevent skipping a day on switch to summertime, gh-114, thanks Matteo
|
12
20
|
|
13
21
|
|
14
22
|
== rufus-scheduler - 3.0.6 released 2014/02/14
|
data/CREDITS.txt
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
== Contributors
|
6
6
|
|
7
|
+
- Adam Jonas (https://github.com/adamjonas) migrate specs to "expect"
|
7
8
|
- Yassen Bantchev (https://github.com/yassenb) CronLine#previous_time rewrite
|
8
9
|
- Eric Lindvall (https://github.com/eric) Zookeeper locked example
|
9
10
|
- Ted Pennings (https://github.com/tedpennings) typo in post_install_message
|
@@ -30,6 +31,7 @@
|
|
30
31
|
|
31
32
|
== Feedback
|
32
33
|
|
34
|
+
- junhanamaki - https://github.com/junhanamaki - #next_time and dst ambiguities
|
33
35
|
- kreynolds (tossrock) - inspiration for #occurrences
|
34
36
|
- Matteo - https://github.com/m4ce - dst and cron issue
|
35
37
|
- Tobias Bielohlawek - https://github.com/rngtng - missing assertion
|
data/README.md
CHANGED
@@ -394,8 +394,8 @@ This option is for repeat jobs (cron / every) only.
|
|
394
394
|
|
395
395
|
It's used to specify the first time after which the repeat job should trigger for the first time.
|
396
396
|
|
397
|
-
In the case of an "every" job, this will be the first time (
|
398
|
-
For a "cron" job, it's the time after which the first schedule will trigger.
|
397
|
+
In the case of an "every" job, this will be the first time (modulo the scheduler frequency) the job triggers.
|
398
|
+
For a "cron" job, it's the time *after* which the first schedule will trigger.
|
399
399
|
|
400
400
|
```ruby
|
401
401
|
scheduler.every '2d', :first_at => Time.now + 10 * 3600 do
|
@@ -405,6 +405,10 @@ end
|
|
405
405
|
scheduler.every '2d', :first_in => '10h' do
|
406
406
|
# ... every two days, but start in 10 hours
|
407
407
|
end
|
408
|
+
|
409
|
+
scheduler.cron '00 14 * * *', :first_in => '3d' do
|
410
|
+
# ... every day at 14h00, but start after 3 * 24 hours
|
411
|
+
end
|
408
412
|
```
|
409
413
|
|
410
414
|
:first, :first_at and :first_in all accept a point in time or a duration (number or time string). Use the symbol you think make your schedule more readable.
|
@@ -1135,7 +1139,7 @@ Rufus::Scheduler.s.every '10s' { puts "hello, world!" }
|
|
1135
1139
|
|
1136
1140
|
## advanced lock schemes
|
1137
1141
|
|
1138
|
-
As seen above, rufus-scheduler proposes the :lockfile system out of the box. If in a group of schedulers only one is supposed to run, the lockfile mecha prevents schedulers that have not set/created the lockfile from running.
|
1142
|
+
As seen above, rufus-scheduler proposes the [:lockfile](#lockfile--mylockfiletxt) system out of the box. If in a group of schedulers only one is supposed to run, the lockfile mecha prevents schedulers that have not set/created the lockfile from running.
|
1139
1143
|
|
1140
1144
|
There are situation where this is not sufficient.
|
1141
1145
|
|
data/TODO.txt
CHANGED
data/lib/rufus/scheduler.rb
CHANGED
@@ -38,7 +38,7 @@ module Rufus
|
|
38
38
|
require 'rufus/scheduler/cronline'
|
39
39
|
require 'rufus/scheduler/job_array'
|
40
40
|
|
41
|
-
VERSION = '3.0.
|
41
|
+
VERSION = '3.0.8'
|
42
42
|
|
43
43
|
#
|
44
44
|
# A common error class for rufus-scheduler
|
@@ -165,6 +165,11 @@ module Rufus
|
|
165
165
|
! @started_at
|
166
166
|
end
|
167
167
|
|
168
|
+
def up?
|
169
|
+
|
170
|
+
!! @started_at
|
171
|
+
end
|
172
|
+
|
168
173
|
def paused?
|
169
174
|
|
170
175
|
@paused
|
@@ -236,9 +241,9 @@ module Rufus
|
|
236
241
|
|
237
242
|
def schedule(arg, callable=nil, opts={}, &block)
|
238
243
|
|
239
|
-
|
244
|
+
opts[:_t] = Scheduler.parse(arg, opts)
|
240
245
|
|
241
|
-
case
|
246
|
+
case opts[:_t]
|
242
247
|
when CronLine then schedule_cron(arg, callable, opts, &block)
|
243
248
|
when Time then schedule_at(arg, callable, opts, &block)
|
244
249
|
else schedule_in(arg, callable, opts, &block)
|
@@ -247,9 +252,9 @@ module Rufus
|
|
247
252
|
|
248
253
|
def repeat(arg, callable=nil, opts={}, &block)
|
249
254
|
|
250
|
-
|
255
|
+
opts[:_t] = Scheduler.parse(arg, opts)
|
251
256
|
|
252
|
-
case
|
257
|
+
case opts[:_t]
|
253
258
|
when CronLine then schedule_cron(arg, callable, opts, &block)
|
254
259
|
else schedule_every(arg, callable, opts, &block)
|
255
260
|
end
|
@@ -612,8 +617,8 @@ module Rufus
|
|
612
617
|
job_class =
|
613
618
|
case job_type
|
614
619
|
when :once
|
615
|
-
|
616
|
-
|
620
|
+
opts[:_t] ||= Rufus::Scheduler.parse(t, opts)
|
621
|
+
opts[:_t].is_a?(Time) ? AtJob : InJob
|
617
622
|
when :every
|
618
623
|
EveryJob
|
619
624
|
when :interval
|
@@ -149,6 +149,10 @@ class Rufus::Scheduler
|
|
149
149
|
end
|
150
150
|
|
151
151
|
global_time(time, from.utc?)
|
152
|
+
|
153
|
+
rescue TZInfo::PeriodNotFound
|
154
|
+
|
155
|
+
next_time(from + 3600)
|
152
156
|
end
|
153
157
|
|
154
158
|
# Returns the previous time the cronline matched. It's like next_time, but
|
@@ -180,6 +184,10 @@ class Rufus::Scheduler
|
|
180
184
|
end
|
181
185
|
|
182
186
|
global_time(time, from.utc?)
|
187
|
+
|
188
|
+
rescue TZInfo::PeriodNotFound
|
189
|
+
|
190
|
+
previous_time(time)
|
183
191
|
end
|
184
192
|
|
185
193
|
# Returns an array of 6 arrays (seconds, minutes, hours, days,
|
@@ -429,12 +437,19 @@ class Rufus::Scheduler
|
|
429
437
|
end
|
430
438
|
|
431
439
|
def local_time(time)
|
432
|
-
|
440
|
+
|
441
|
+
@timezone ? @timezone.utc_to_local(time.getutc) : time
|
433
442
|
end
|
434
443
|
|
435
444
|
def global_time(time, from_in_utc)
|
445
|
+
|
436
446
|
if @timezone
|
437
|
-
time =
|
447
|
+
time =
|
448
|
+
begin
|
449
|
+
@timezone.local_to_utc(time)
|
450
|
+
rescue TZInfo::AmbiguousTime
|
451
|
+
@timezone.local_to_utc(time, time.isdst)
|
452
|
+
end
|
438
453
|
time = time.getlocal unless from_in_utc
|
439
454
|
end
|
440
455
|
|
@@ -442,6 +457,7 @@ class Rufus::Scheduler
|
|
442
457
|
end
|
443
458
|
|
444
459
|
def round_to_seconds(time)
|
460
|
+
|
445
461
|
# Ruby 1.8 doesn't have #round
|
446
462
|
time.respond_to?(:round) ? time.round : time - time.usec * 1e-6
|
447
463
|
end
|
data/lib/rufus/scheduler/jobs.rb
CHANGED
@@ -368,7 +368,8 @@ module Rufus
|
|
368
368
|
|
369
369
|
super(scheduler, time, opts, block)
|
370
370
|
|
371
|
-
@next_time =
|
371
|
+
@next_time =
|
372
|
+
opts[:_t] || Rufus::Scheduler.parse_at(time, opts)
|
372
373
|
end
|
373
374
|
end
|
374
375
|
|
@@ -378,7 +379,9 @@ module Rufus
|
|
378
379
|
|
379
380
|
super(scheduler, duration, opts, block)
|
380
381
|
|
381
|
-
@next_time =
|
382
|
+
@next_time =
|
383
|
+
@scheduled_at +
|
384
|
+
opts[:_t] || Rufus::Scheduler.parse_in(duration, opts)
|
382
385
|
end
|
383
386
|
end
|
384
387
|
|
@@ -597,7 +600,7 @@ module Rufus
|
|
597
600
|
|
598
601
|
super(scheduler, cronline, opts, block)
|
599
602
|
|
600
|
-
@cron_line = CronLine.new(cronline)
|
603
|
+
@cron_line = opts[:_t] || CronLine.new(cronline)
|
601
604
|
@next_time = @cron_line.next_time
|
602
605
|
end
|
603
606
|
|
data/lib/rufus/scheduler/util.rb
CHANGED
@@ -31,9 +31,9 @@ module Rufus
|
|
31
31
|
# time and string methods
|
32
32
|
#++
|
33
33
|
|
34
|
-
def self.parse(o)
|
34
|
+
def self.parse(o, opts={})
|
35
35
|
|
36
|
-
opts
|
36
|
+
opts[:no_error] = true
|
37
37
|
|
38
38
|
parse_cron(o, opts) ||
|
39
39
|
parse_in(o, opts) || # covers 'every' schedule strings
|
@@ -52,6 +52,9 @@ module Rufus
|
|
52
52
|
|
53
53
|
return o if o.is_a?(Time)
|
54
54
|
|
55
|
+
# TODO: deal with tz if suffixed to Chronic string?
|
56
|
+
return Chronic.parse(o, opts) if defined?(Chronic)
|
57
|
+
|
55
58
|
tz = nil
|
56
59
|
s =
|
57
60
|
o.to_s.gsub(TZ_REGEX) { |m|
|
@@ -68,9 +71,7 @@ module Rufus
|
|
68
71
|
|
69
72
|
t = Time.parse(s)
|
70
73
|
|
71
|
-
|
72
|
-
|
73
|
-
t
|
74
|
+
tz ? tz.local_to_utc(t) : t
|
74
75
|
|
75
76
|
rescue StandardError => se
|
76
77
|
|
data/rufus-scheduler.gemspec
CHANGED
data/spec/basics_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Specifying rufus-scheduler
|
4
|
+
#
|
5
|
+
# Sun Jun 1 05:52:24 JST 2014
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'spec_helper'
|
9
|
+
|
10
|
+
|
11
|
+
describe 'basics' do
|
12
|
+
|
13
|
+
def tts(time)
|
14
|
+
|
15
|
+
time.strftime('%Y-%m-%d %H:%M:%S %z') + (time.dst? ? ' dst' : '')
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'Time.new' do
|
19
|
+
|
20
|
+
it 'accepts a timezone final argument' do
|
21
|
+
|
22
|
+
pending if jruby? or ruby18?
|
23
|
+
|
24
|
+
expect(
|
25
|
+
tts(Time.new(2014, 1, 1, 1, 0, 0, '+01:00'))
|
26
|
+
).to eq('2014-01-01 01:00:00 +0100')
|
27
|
+
expect(
|
28
|
+
tts(Time.new(2014, 8, 1, 1, 0, 0, '+01:00'))
|
29
|
+
).to eq('2014-08-01 01:00:00 +0100')
|
30
|
+
expect(
|
31
|
+
tts(Time.new(2014, 8, 1, 1, 0, 0, '+01:00'))
|
32
|
+
).to eq('2014-08-01 01:00:00 +0100')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'Time.local' do
|
37
|
+
|
38
|
+
it 'works as expected' do
|
39
|
+
|
40
|
+
expect(
|
41
|
+
tts(in_zone('Europe/Berlin') { Time.local(2014, 1, 1, 1, 0, 0) })
|
42
|
+
).to eq('2014-01-01 01:00:00 +0100')
|
43
|
+
expect(
|
44
|
+
tts(in_zone('Europe/Berlin') { Time.local(2014, 8, 1, 1, 0, 0) })
|
45
|
+
).to eq('2014-08-01 01:00:00 +0200 dst')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
data/spec/cronline_spec.rb
CHANGED
@@ -16,13 +16,13 @@ describe Rufus::Scheduler::CronLine do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def match(line, time)
|
19
|
-
cl(line).matches?(time).
|
19
|
+
expect(cl(line).matches?(time)).to eq(true)
|
20
20
|
end
|
21
21
|
def no_match(line, time)
|
22
|
-
cl(line).matches?(time).
|
22
|
+
expect(cl(line).matches?(time)).to eq(false)
|
23
23
|
end
|
24
24
|
def to_a(line, array)
|
25
|
-
cl(line).to_array.
|
25
|
+
expect(cl(line).to_array).to eq(array)
|
26
26
|
end
|
27
27
|
|
28
28
|
describe '.new' do
|
@@ -59,17 +59,17 @@ describe Rufus::Scheduler::CronLine do
|
|
59
59
|
|
60
60
|
it 'rejects invalid weekday expressions' do
|
61
61
|
|
62
|
-
|
62
|
+
expect { cl '0 17 * * MON_FRI' }.to raise_error
|
63
63
|
# underline instead of dash
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
expect { cl '* * * * 9' }.to raise_error
|
66
|
+
expect { cl '* * * * 0-12' }.to raise_error
|
67
|
+
expect { cl '* * * * BLABLA' }.to raise_error
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'rejects invalid cronlines' do
|
71
71
|
|
72
|
-
|
72
|
+
expect { cl '* nada * * 9' }.to raise_error(ArgumentError)
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'interprets cron strings with TZ correctly' do
|
@@ -84,8 +84,8 @@ describe Rufus::Scheduler::CronLine do
|
|
84
84
|
'* * * * * * America/New_York',
|
85
85
|
[ nil, nil, nil, nil, nil, nil, nil, 'America/New_York' ])
|
86
86
|
|
87
|
-
|
88
|
-
|
87
|
+
expect { cl '* * * * * NotATimeZone' }.to raise_error
|
88
|
+
expect { cl '* * * * * * NotATimeZone' }.to raise_error
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'interprets cron strings with / (slashes) correctly' do
|
@@ -118,59 +118,69 @@ describe Rufus::Scheduler::CronLine do
|
|
118
118
|
|
119
119
|
it 'rejects / for days (every other wednesday)' do
|
120
120
|
|
121
|
-
|
121
|
+
expect {
|
122
122
|
Rufus::Scheduler::CronLine.new('* * * * wed/2')
|
123
|
-
}.
|
123
|
+
}.to raise_error(ArgumentError)
|
124
124
|
end
|
125
125
|
|
126
126
|
it 'does not support ranges for monthdays (sun#1-sun#2)' do
|
127
127
|
|
128
|
-
|
128
|
+
expect {
|
129
129
|
Rufus::Scheduler::CronLine.new('* * * * sun#1-sun#2')
|
130
|
-
}.
|
130
|
+
}.to raise_error(ArgumentError)
|
131
131
|
end
|
132
132
|
|
133
133
|
it 'accepts items with initial 0' do
|
134
134
|
|
135
|
-
to_a
|
136
|
-
|
137
|
-
to_a
|
138
|
-
|
139
|
-
to_a
|
140
|
-
|
141
|
-
to_a
|
135
|
+
to_a(
|
136
|
+
'09 * * * *', [ [0], [9], nil, nil, nil, nil, nil, nil ])
|
137
|
+
to_a(
|
138
|
+
'09-12 * * * *', [ [0], [9, 10, 11, 12], nil, nil, nil, nil, nil, nil ])
|
139
|
+
to_a(
|
140
|
+
'07-08 * * * *', [ [0], [7, 8], nil, nil, nil, nil, nil, nil ])
|
141
|
+
to_a(
|
142
|
+
'* */08 * * *', [ [0], nil, [0, 8, 16], nil, nil, nil, nil, nil ])
|
143
|
+
to_a(
|
144
|
+
'* */07 * * *', [ [0], nil, [0, 7, 14, 21], nil, nil, nil, nil, nil ])
|
145
|
+
to_a(
|
146
|
+
'* 01-09/04 * * *', [ [0], nil, [1, 5, 9], nil, nil, nil, nil, nil ])
|
147
|
+
to_a(
|
148
|
+
'* * * * 06', [ [0], nil, nil, nil, nil, [6], nil, nil ])
|
142
149
|
end
|
143
150
|
|
144
151
|
it 'interprets cron strings with L correctly' do
|
145
152
|
|
146
|
-
to_a
|
147
|
-
|
148
|
-
to_a
|
153
|
+
to_a(
|
154
|
+
'* * L * *', [[0], nil, nil, ['L'], nil, nil, nil, nil ])
|
155
|
+
to_a(
|
156
|
+
'* * 2-5,L * *', [[0], nil, nil, [2,3,4,5,'L'], nil, nil, nil, nil ])
|
157
|
+
to_a(
|
158
|
+
'* * */8,L * *', [[0], nil, nil, [1,9,17,25,'L'], nil, nil, nil, nil ])
|
149
159
|
end
|
150
160
|
|
151
161
|
it 'does not support ranges for L' do
|
152
162
|
|
153
|
-
|
154
|
-
|
163
|
+
expect { cl '* * 15-L * *'}.to raise_error(ArgumentError)
|
164
|
+
expect { cl '* * L/4 * *'}.to raise_error(ArgumentError)
|
155
165
|
end
|
156
166
|
|
157
167
|
it 'does not support multiple Ls' do
|
158
168
|
|
159
|
-
|
169
|
+
expect { cl '* * L,L * *'}.to raise_error(ArgumentError)
|
160
170
|
end
|
161
171
|
|
162
172
|
it 'raises if L is used for something else than days' do
|
163
173
|
|
164
|
-
|
174
|
+
expect { cl '* L * * *'}.to raise_error(ArgumentError)
|
165
175
|
end
|
166
176
|
|
167
177
|
it 'raises for out of range input' do
|
168
178
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
179
|
+
expect { cl '60-62 * * * *'}.to raise_error(ArgumentError)
|
180
|
+
expect { cl '62 * * * *'}.to raise_error(ArgumentError)
|
181
|
+
expect { cl '60 * * * *'}.to raise_error(ArgumentError)
|
182
|
+
expect { cl '* 25-26 * * *'}.to raise_error(ArgumentError)
|
183
|
+
expect { cl '* 25 * * *'}.to raise_error(ArgumentError)
|
174
184
|
#
|
175
185
|
# as reported by Aimee Rose in
|
176
186
|
# https://github.com/jmettraux/rufus-scheduler/pull/58
|
@@ -182,64 +192,69 @@ describe Rufus::Scheduler::CronLine do
|
|
182
192
|
def nt(cronline, now)
|
183
193
|
Rufus::Scheduler::CronLine.new(cronline).next_time(now)
|
184
194
|
end
|
195
|
+
def ntz(cronline, now)
|
196
|
+
tz = cronline.split.last
|
197
|
+
tu = nt(cronline, now).utc
|
198
|
+
in_zone(tz) { tu.getlocal }
|
199
|
+
end
|
185
200
|
|
186
201
|
it 'computes the next occurence correctly' do
|
187
202
|
|
188
203
|
now = Time.at(0).getutc # Thu Jan 01 00:00:00 UTC 1970
|
189
204
|
|
190
|
-
nt('* * * * *', now).
|
191
|
-
nt('* * * * sun', now).
|
192
|
-
nt('* * * * * *', now).
|
193
|
-
nt('* * 13 * fri', now).
|
205
|
+
expect(nt('* * * * *', now)).to eq(now + 60)
|
206
|
+
expect(nt('* * * * sun', now)).to eq(now + 259200)
|
207
|
+
expect(nt('* * * * * *', now)).to eq(now + 1)
|
208
|
+
expect(nt('* * 13 * fri', now)).to eq(now + 3715200)
|
194
209
|
|
195
|
-
nt('10 12 13 12 *', now).
|
210
|
+
expect(nt('10 12 13 12 *', now)).to eq(now + 29938200)
|
196
211
|
# this one is slow (1 year == 3 seconds)
|
197
212
|
#
|
198
213
|
# historical note:
|
199
214
|
# (comment made in 2006 or 2007, the underlying libs got better and
|
200
215
|
# that slowness is gone)
|
201
216
|
|
202
|
-
nt('0 0 * * thu', now).
|
203
|
-
nt('00 0 * * thu', now).
|
217
|
+
expect(nt('0 0 * * thu', now)).to eq(now + 604800)
|
218
|
+
expect(nt('00 0 * * thu', now)).to eq(now + 604800)
|
204
219
|
|
205
|
-
nt('0 0 * * *', now).
|
206
|
-
nt('0 24 * * *', now).
|
220
|
+
expect(nt('0 0 * * *', now)).to eq(now + 24 * 3600)
|
221
|
+
expect(nt('0 24 * * *', now)).to eq(now + 24 * 3600)
|
207
222
|
|
208
223
|
now = local(2008, 12, 31, 23, 59, 59, 0)
|
209
224
|
|
210
|
-
nt('* * * * *', now).
|
225
|
+
expect(nt('* * * * *', now)).to eq(now + 1)
|
211
226
|
end
|
212
227
|
|
213
228
|
it 'computes the next occurence correctly in UTC (TZ not specified)' do
|
214
229
|
|
215
230
|
now = utc(1970, 1, 1)
|
216
231
|
|
217
|
-
nt('* * * * *', now).
|
218
|
-
nt('* * * * sun', now).
|
219
|
-
nt('* * * * * *', now).
|
220
|
-
nt('* * 13 * fri', now).
|
232
|
+
expect(nt('* * * * *', now)).to eq(utc(1970, 1, 1, 0, 1))
|
233
|
+
expect(nt('* * * * sun', now)).to eq(utc(1970, 1, 4))
|
234
|
+
expect(nt('* * * * * *', now)).to eq(utc(1970, 1, 1, 0, 0, 1))
|
235
|
+
expect(nt('* * 13 * fri', now)).to eq(utc(1970, 2, 13))
|
221
236
|
|
222
|
-
nt('10 12 13 12 *', now).
|
237
|
+
expect(nt('10 12 13 12 *', now)).to eq(utc(1970, 12, 13, 12, 10))
|
223
238
|
# this one is slow (1 year == 3 seconds)
|
224
|
-
nt('* * 1 6 *', now).
|
239
|
+
expect(nt('* * 1 6 *', now)).to eq(utc(1970, 6, 1))
|
225
240
|
|
226
|
-
nt('0 0 * * thu', now).
|
241
|
+
expect(nt('0 0 * * thu', now)).to eq(utc(1970, 1, 8))
|
227
242
|
end
|
228
243
|
|
229
244
|
it 'computes the next occurence correctly in local TZ (TZ not specified)' do
|
230
245
|
|
231
246
|
now = local(1970, 1, 1)
|
232
247
|
|
233
|
-
nt('* * * * *', now).
|
234
|
-
nt('* * * * sun', now).
|
235
|
-
nt('* * * * * *', now).
|
236
|
-
nt('* * 13 * fri', now).
|
248
|
+
expect(nt('* * * * *', now)).to eq(local(1970, 1, 1, 0, 1))
|
249
|
+
expect(nt('* * * * sun', now)).to eq(local(1970, 1, 4))
|
250
|
+
expect(nt('* * * * * *', now)).to eq(local(1970, 1, 1, 0, 0, 1))
|
251
|
+
expect(nt('* * 13 * fri', now)).to eq(local(1970, 2, 13))
|
237
252
|
|
238
|
-
nt('10 12 13 12 *', now).
|
253
|
+
expect(nt('10 12 13 12 *', now)).to eq(local(1970, 12, 13, 12, 10))
|
239
254
|
# this one is slow (1 year == 3 seconds)
|
240
|
-
nt('* * 1 6 *', now).
|
255
|
+
expect(nt('* * 1 6 *', now)).to eq(local(1970, 6, 1))
|
241
256
|
|
242
|
-
nt('0 0 * * thu', now).
|
257
|
+
expect(nt('0 0 * * thu', now)).to eq(local(1970, 1, 8))
|
243
258
|
end
|
244
259
|
|
245
260
|
it 'computes the next occurence correctly in UTC (TZ specified)' do
|
@@ -249,15 +264,15 @@ describe Rufus::Scheduler::CronLine do
|
|
249
264
|
now = tz.local_to_utc(local(1970, 1, 1))
|
250
265
|
# Midnight in zone, UTC
|
251
266
|
|
252
|
-
nt("* * * * * #{zone}", now).
|
253
|
-
nt("* * * * sun #{zone}", now).
|
254
|
-
nt("* * * * * * #{zone}", now).
|
255
|
-
nt("* * 13 * fri #{zone}", now).
|
267
|
+
expect(nt("* * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 1))
|
268
|
+
expect(nt("* * * * sun #{zone}", now)).to eq(utc(1970, 1, 3, 23))
|
269
|
+
expect(nt("* * * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 0, 1))
|
270
|
+
expect(nt("* * 13 * fri #{zone}", now)).to eq(utc(1970, 2, 12, 23))
|
256
271
|
|
257
|
-
nt("10 12 13 12 * #{zone}", now).
|
258
|
-
nt("* * 1 6 * #{zone}", now).
|
272
|
+
expect(nt("10 12 13 12 * #{zone}", now)).to eq(utc(1970, 12, 13, 11, 10))
|
273
|
+
expect(nt("* * 1 6 * #{zone}", now)).to eq(utc(1970, 5, 31, 23))
|
259
274
|
|
260
|
-
nt("0 0 * * thu #{zone}", now).
|
275
|
+
expect(nt("0 0 * * thu #{zone}", now)).to eq(utc(1970, 1, 7, 23))
|
261
276
|
end
|
262
277
|
|
263
278
|
#it 'computes the next occurence correctly in local TZ (TZ specified)' do
|
@@ -276,45 +291,85 @@ describe Rufus::Scheduler::CronLine do
|
|
276
291
|
|
277
292
|
it 'computes the next time correctly when there is a sun#2 involved' do
|
278
293
|
|
279
|
-
nt('* * * * sun#1', local(1970, 1, 1)).
|
280
|
-
nt('* * * * sun#2', local(1970, 1, 1)).
|
294
|
+
expect(nt('* * * * sun#1', local(1970, 1, 1))).to eq(local(1970, 1, 4))
|
295
|
+
expect(nt('* * * * sun#2', local(1970, 1, 1))).to eq(local(1970, 1, 11))
|
281
296
|
|
282
|
-
nt('* * * * sun#2', local(1970, 1, 12)).
|
297
|
+
expect(nt('* * * * sun#2', local(1970, 1, 12))).to eq(local(1970, 2, 8))
|
283
298
|
end
|
284
299
|
|
285
|
-
it 'computes
|
300
|
+
it 'computes next time correctly when there is a sun#2,sun#3 involved' do
|
286
301
|
|
287
|
-
|
288
|
-
|
302
|
+
expect(
|
303
|
+
nt('* * * * sun#2,sun#3', local(1970, 1, 1))).to eq(local(1970, 1, 11))
|
304
|
+
expect(
|
305
|
+
nt('* * * * sun#2,sun#3', local(1970, 1, 12))).to eq(local(1970, 1, 18))
|
289
306
|
end
|
290
307
|
|
291
308
|
it 'understands sun#L' do
|
292
309
|
|
293
|
-
nt('* * * * sun#L', local(1970, 1, 1)).
|
310
|
+
expect(nt('* * * * sun#L', local(1970, 1, 1))).to eq(local(1970, 1, 25))
|
294
311
|
end
|
295
312
|
|
296
313
|
it 'understands sun#-1' do
|
297
314
|
|
298
|
-
nt('* * * * sun#-1', local(1970, 1, 1)).
|
315
|
+
expect(nt('* * * * sun#-1', local(1970, 1, 1))).to eq(local(1970, 1, 25))
|
299
316
|
end
|
300
317
|
|
301
318
|
it 'understands sun#-2' do
|
302
319
|
|
303
|
-
nt('* * * * sun#-2', local(1970, 1, 1)).
|
320
|
+
expect(nt('* * * * sun#-2', local(1970, 1, 1))).to eq(local(1970, 1, 18))
|
304
321
|
end
|
305
322
|
|
306
323
|
it 'computes the next time correctly when "L" (last day of month)' do
|
307
324
|
|
308
|
-
nt('* * L * *', lo(1970, 1, 1)).
|
309
|
-
nt('* * L * *', lo(1970, 2, 1)).
|
310
|
-
nt('* * L * *', lo(1972, 2, 1)).
|
311
|
-
nt('* * L * *', lo(1970, 4, 1)).
|
325
|
+
expect(nt('* * L * *', lo(1970, 1, 1))).to eq(lo(1970, 1, 31))
|
326
|
+
expect(nt('* * L * *', lo(1970, 2, 1))).to eq(lo(1970, 2, 28))
|
327
|
+
expect(nt('* * L * *', lo(1972, 2, 1))).to eq(lo(1972, 2, 29))
|
328
|
+
expect(nt('* * L * *', lo(1970, 4, 1))).to eq(lo(1970, 4, 30))
|
312
329
|
end
|
313
330
|
|
314
331
|
it 'returns a time with subseconds chopped off' do
|
315
332
|
|
316
|
-
|
317
|
-
|
333
|
+
expect(
|
334
|
+
nt('* * * * *', Time.now).usec).to eq(0)
|
335
|
+
expect(
|
336
|
+
nt('* * * * *', Time.now).iso8601(10).match(/\.0+[^\d]/)).not_to eq(nil)
|
337
|
+
end
|
338
|
+
|
339
|
+
# New York EST: UTC-5
|
340
|
+
# summer (dst) EDT: UTC-4
|
341
|
+
|
342
|
+
# gh-127
|
343
|
+
#
|
344
|
+
it 'survives TZInfo::AmbiguousTime' do
|
345
|
+
|
346
|
+
if ruby18? or jruby?
|
347
|
+
expect(
|
348
|
+
ntz(
|
349
|
+
'30 1 31 10 * America/New_York',
|
350
|
+
ltz('America/New_York', 2004, 10, 1)
|
351
|
+
).strftime('%Y-%m-%d %H:%M:%S')
|
352
|
+
).to eq('2004-10-31 01:30:00')
|
353
|
+
else
|
354
|
+
expect(
|
355
|
+
ntz(
|
356
|
+
'30 1 31 10 * America/New_York',
|
357
|
+
ltz('America/New_York', 2004, 10, 1)
|
358
|
+
)
|
359
|
+
).to eq(ltz('America/New_York', 2004, 10, 31, 1, 30, 0))
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# gh-127
|
364
|
+
#
|
365
|
+
it 'survives TZInfo::PeriodNotFound' do
|
366
|
+
|
367
|
+
expect(
|
368
|
+
ntz(
|
369
|
+
'0 2 9 3 * America/New_York',
|
370
|
+
ltz('America/New_York', 2014, 3, 1)
|
371
|
+
)
|
372
|
+
).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
|
318
373
|
end
|
319
374
|
end
|
320
375
|
|
@@ -323,15 +378,61 @@ describe Rufus::Scheduler::CronLine do
|
|
323
378
|
def pt(cronline, now)
|
324
379
|
Rufus::Scheduler::CronLine.new(cronline).previous_time(now)
|
325
380
|
end
|
381
|
+
def ptz(cronline, now)
|
382
|
+
tz = cronline.split.last
|
383
|
+
tu = pt(cronline, now).utc
|
384
|
+
in_zone(tz) { tu.getlocal }
|
385
|
+
end
|
326
386
|
|
327
387
|
it 'returns the previous time the cron should have triggered' do
|
328
388
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
389
|
+
expect(
|
390
|
+
pt('* * * * sun', lo(1970, 1, 1))).to eq(lo(1969, 12, 28, 23, 59, 00))
|
391
|
+
expect(
|
392
|
+
pt('* * 13 * *', lo(1970, 1, 1))).to eq(lo(1969, 12, 13, 23, 59, 00))
|
393
|
+
expect(
|
394
|
+
pt('0 12 13 * *', lo(1970, 1, 1))).to eq(lo(1969, 12, 13, 12, 00))
|
395
|
+
expect(
|
396
|
+
pt('0 0 2 1 *', lo(1970, 1, 1))).to eq(lo(1969, 1, 2, 0, 00))
|
397
|
+
|
398
|
+
expect(
|
399
|
+
pt('* * * * * sun', lo(1970, 1, 1))).to eq(lo(1969, 12, 28, 23, 59, 59))
|
400
|
+
end
|
401
|
+
|
402
|
+
# New York EST: UTC-5
|
403
|
+
# summer (dst) EDT: UTC-4
|
404
|
+
|
405
|
+
# gh-127
|
406
|
+
#
|
407
|
+
it 'survives TZInfo::AmbiguousTime' do
|
408
|
+
|
409
|
+
if ruby18? or jruby?
|
410
|
+
expect(
|
411
|
+
ptz(
|
412
|
+
'30 1 31 10 * America/New_York',
|
413
|
+
ltz('America/New_York', 2004, 10, 31, 14, 30, 0)
|
414
|
+
).strftime('%Y-%m-%d %H:%M:%S')
|
415
|
+
).to eq('2004-10-31 01:30:00')
|
416
|
+
else
|
417
|
+
expect(
|
418
|
+
ptz(
|
419
|
+
'30 1 31 10 * America/New_York',
|
420
|
+
ltz('America/New_York', 2004, 10, 31, 14, 30, 0)
|
421
|
+
)
|
422
|
+
).to eq(ltz('America/New_York', 2004, 10, 31, 1, 30, 0))
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
# gh-127
|
427
|
+
#
|
428
|
+
it 'survives TZInfo::PeriodNotFound' do
|
333
429
|
|
334
|
-
|
430
|
+
expect(
|
431
|
+
ptz(
|
432
|
+
'0 2 9 3 * America/New_York',
|
433
|
+
ltz('America/New_York', 2015, 3, 9, 12, 0, 0)
|
434
|
+
)
|
435
|
+
).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
|
335
436
|
end
|
336
437
|
end
|
337
438
|
|
@@ -432,11 +533,11 @@ describe Rufus::Scheduler::CronLine do
|
|
432
533
|
|
433
534
|
cl = Rufus::Scheduler::CronLine.new('* * * * *')
|
434
535
|
|
435
|
-
cl.monthdays(local(1970, 1, 1)).
|
436
|
-
cl.monthdays(local(1970, 1, 7)).
|
437
|
-
cl.monthdays(local(1970, 1, 14)).
|
536
|
+
expect(cl.monthdays(local(1970, 1, 1))).to eq(%w[ thu#1 thu#-5 ])
|
537
|
+
expect(cl.monthdays(local(1970, 1, 7))).to eq(%w[ wed#1 wed#-4 ])
|
538
|
+
expect(cl.monthdays(local(1970, 1, 14))).to eq(%w[ wed#2 wed#-3 ])
|
438
539
|
|
439
|
-
cl.monthdays(local(2011, 3, 11)).
|
540
|
+
expect(cl.monthdays(local(2011, 3, 11))).to eq(%w[ fri#2 fri#-3 ])
|
440
541
|
end
|
441
542
|
end
|
442
543
|
|
@@ -444,20 +545,20 @@ describe Rufus::Scheduler::CronLine do
|
|
444
545
|
|
445
546
|
it 'returns the shortest delta between two occurrences' do
|
446
547
|
|
447
|
-
Rufus::Scheduler::CronLine.new(
|
448
|
-
'* * * * *').frequency.
|
449
|
-
Rufus::Scheduler::CronLine.new(
|
450
|
-
'* * * * * *').frequency.
|
548
|
+
expect(Rufus::Scheduler::CronLine.new(
|
549
|
+
'* * * * *').frequency).to eq(60)
|
550
|
+
expect(Rufus::Scheduler::CronLine.new(
|
551
|
+
'* * * * * *').frequency).to eq(1)
|
451
552
|
|
452
|
-
Rufus::Scheduler::CronLine.new(
|
453
|
-
'5 23 * * *').frequency.
|
454
|
-
Rufus::Scheduler::CronLine.new(
|
455
|
-
'5 * * * *').frequency.
|
456
|
-
Rufus::Scheduler::CronLine.new(
|
457
|
-
'10,20,30 * * * *').frequency.
|
553
|
+
expect(Rufus::Scheduler::CronLine.new(
|
554
|
+
'5 23 * * *').frequency).to eq(24 * 3600)
|
555
|
+
expect(Rufus::Scheduler::CronLine.new(
|
556
|
+
'5 * * * *').frequency).to eq(3600)
|
557
|
+
expect(Rufus::Scheduler::CronLine.new(
|
558
|
+
'10,20,30 * * * *').frequency).to eq(600)
|
458
559
|
|
459
|
-
Rufus::Scheduler::CronLine.new(
|
460
|
-
'10,20,30 * * * * *').frequency.
|
560
|
+
expect(Rufus::Scheduler::CronLine.new(
|
561
|
+
'10,20,30 * * * * *').frequency).to eq(10)
|
461
562
|
end
|
462
563
|
end
|
463
564
|
|
@@ -465,17 +566,17 @@ describe Rufus::Scheduler::CronLine do
|
|
465
566
|
|
466
567
|
it 'returns the shortest delta between two occurrences' do
|
467
568
|
|
468
|
-
Rufus::Scheduler::CronLine.new(
|
469
|
-
'* * * * *').brute_frequency.
|
470
|
-
Rufus::Scheduler::CronLine.new(
|
471
|
-
'* * * * * *').brute_frequency.
|
569
|
+
expect(Rufus::Scheduler::CronLine.new(
|
570
|
+
'* * * * *').brute_frequency).to eq(60)
|
571
|
+
expect(Rufus::Scheduler::CronLine.new(
|
572
|
+
'* * * * * *').brute_frequency).to eq(1)
|
472
573
|
|
473
|
-
Rufus::Scheduler::CronLine.new(
|
474
|
-
'5 23 * * *').brute_frequency.
|
475
|
-
Rufus::Scheduler::CronLine.new(
|
476
|
-
'5 * * * *').brute_frequency.
|
477
|
-
Rufus::Scheduler::CronLine.new(
|
478
|
-
'10,20,30 * * * *').brute_frequency.
|
574
|
+
expect(Rufus::Scheduler::CronLine.new(
|
575
|
+
'5 23 * * *').brute_frequency).to eq(24 * 3600)
|
576
|
+
expect(Rufus::Scheduler::CronLine.new(
|
577
|
+
'5 * * * *').brute_frequency).to eq(3600)
|
578
|
+
expect(Rufus::Scheduler::CronLine.new(
|
579
|
+
'10,20,30 * * * *').brute_frequency).to eq(600)
|
479
580
|
|
480
581
|
#Rufus::Scheduler::CronLine.new(
|
481
582
|
# '10,20,30 * * * * *').brute_frequency.should == 10
|
@@ -513,8 +614,8 @@ describe Rufus::Scheduler::CronLine do
|
|
513
614
|
|
514
615
|
# verify the playground...
|
515
616
|
#
|
516
|
-
friday.isdst.
|
517
|
-
(friday + 24 * 3600 * 3).isdst.
|
617
|
+
expect(friday.isdst).to eq(false)
|
618
|
+
expect((friday + 24 * 3600 * 3).isdst).to eq(true)
|
518
619
|
|
519
620
|
cl0 = Rufus::Scheduler::CronLine.new('02 00 * * 1,2,3,4,5')
|
520
621
|
cl1 = Rufus::Scheduler::CronLine.new('45 08 * * 1,2,3,4,5')
|
@@ -522,14 +623,16 @@ describe Rufus::Scheduler::CronLine do
|
|
522
623
|
n0 = cl0.next_time(friday)
|
523
624
|
n1 = cl1.next_time(friday)
|
524
625
|
|
525
|
-
n0.strftime('%H:%M:%S %^a').
|
526
|
-
n1.strftime('%H:%M:%S %^a').
|
626
|
+
expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 MON')
|
627
|
+
expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
|
527
628
|
|
528
|
-
n0.isdst.
|
529
|
-
n1.isdst.
|
629
|
+
expect(n0.isdst).to eq(true)
|
630
|
+
expect(n1.isdst).to eq(true)
|
530
631
|
|
531
|
-
(
|
532
|
-
|
632
|
+
expect(
|
633
|
+
(n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('23:02:00 THU')
|
634
|
+
expect(
|
635
|
+
(n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('07:45:00 FRI')
|
533
636
|
end
|
534
637
|
end
|
535
638
|
|
@@ -552,8 +655,8 @@ describe Rufus::Scheduler::CronLine do
|
|
552
655
|
|
553
656
|
# verify the playground...
|
554
657
|
#
|
555
|
-
friday.isdst.
|
556
|
-
(friday + 24 * 3600 * 3).isdst.
|
658
|
+
expect(friday.isdst).to eq(true)
|
659
|
+
expect((friday + 24 * 3600 * 3).isdst).to eq(false)
|
557
660
|
|
558
661
|
cl0 = Rufus::Scheduler::CronLine.new('02 00 * * 1,2,3,4,5')
|
559
662
|
cl1 = Rufus::Scheduler::CronLine.new('45 08 * * 1,2,3,4,5')
|
@@ -561,14 +664,16 @@ describe Rufus::Scheduler::CronLine do
|
|
561
664
|
n0 = cl0.next_time(friday)
|
562
665
|
n1 = cl1.next_time(friday)
|
563
666
|
|
564
|
-
n0.strftime('%H:%M:%S %^a').
|
565
|
-
n1.strftime('%H:%M:%S %^a').
|
667
|
+
expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 MON')
|
668
|
+
expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
|
566
669
|
|
567
|
-
n0.isdst.
|
568
|
-
n1.isdst.
|
670
|
+
expect(n0.isdst).to eq(false)
|
671
|
+
expect(n1.isdst).to eq(false)
|
569
672
|
|
570
|
-
(
|
571
|
-
|
673
|
+
expect(
|
674
|
+
(n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('01:02:00 FRI')
|
675
|
+
expect(
|
676
|
+
(n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('09:45:00 FRI')
|
572
677
|
end
|
573
678
|
end
|
574
679
|
end
|