rufus-scheduler 2.0.24 → 3.1.0
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 +76 -0
- data/CREDITS.txt +23 -0
- data/LICENSE.txt +1 -1
- data/README.md +1439 -0
- data/Rakefile +1 -5
- data/TODO.txt +149 -55
- data/lib/rufus/{sc → scheduler}/cronline.rb +167 -53
- data/lib/rufus/scheduler/job_array.rb +92 -0
- data/lib/rufus/scheduler/jobs.rb +633 -0
- data/lib/rufus/scheduler/locks.rb +95 -0
- data/lib/rufus/scheduler/util.rb +306 -0
- data/lib/rufus/scheduler/zones.rb +174 -0
- data/lib/rufus/scheduler/zotime.rb +154 -0
- data/lib/rufus/scheduler.rb +608 -27
- data/rufus-scheduler.gemspec +6 -4
- data/spec/basics_spec.rb +54 -0
- data/spec/cronline_spec.rb +479 -152
- data/spec/error_spec.rb +139 -0
- data/spec/job_array_spec.rb +39 -0
- data/spec/job_at_spec.rb +58 -0
- data/spec/job_cron_spec.rb +128 -0
- data/spec/job_every_spec.rb +104 -0
- data/spec/job_in_spec.rb +20 -0
- data/spec/job_interval_spec.rb +68 -0
- data/spec/job_repeat_spec.rb +357 -0
- data/spec/job_spec.rb +498 -109
- data/spec/lock_custom_spec.rb +47 -0
- data/spec/lock_flock_spec.rb +47 -0
- data/spec/lock_lockfile_spec.rb +61 -0
- data/spec/lock_spec.rb +59 -0
- data/spec/parse_spec.rb +263 -0
- data/spec/schedule_at_spec.rb +158 -0
- data/spec/schedule_cron_spec.rb +66 -0
- data/spec/schedule_every_spec.rb +109 -0
- data/spec/schedule_in_spec.rb +80 -0
- data/spec/schedule_interval_spec.rb +128 -0
- data/spec/scheduler_spec.rb +928 -124
- data/spec/spec_helper.rb +126 -0
- data/spec/threads_spec.rb +96 -0
- data/spec/zotime_spec.rb +396 -0
- metadata +56 -33
- data/README.rdoc +0 -661
- data/lib/rufus/otime.rb +0 -3
- data/lib/rufus/sc/jobqueues.rb +0 -160
- data/lib/rufus/sc/jobs.rb +0 -471
- data/lib/rufus/sc/rtime.rb +0 -363
- data/lib/rufus/sc/scheduler.rb +0 -636
- data/lib/rufus/sc/version.rb +0 -32
- data/spec/at_in_spec.rb +0 -47
- data/spec/at_spec.rb +0 -125
- data/spec/blocking_spec.rb +0 -64
- data/spec/cron_spec.rb +0 -134
- data/spec/every_spec.rb +0 -304
- data/spec/exception_spec.rb +0 -113
- data/spec/in_spec.rb +0 -150
- data/spec/mutex_spec.rb +0 -159
- data/spec/rtime_spec.rb +0 -137
- data/spec/schedulable_spec.rb +0 -97
- data/spec/spec_base.rb +0 -87
- data/spec/stress_schedule_unschedule_spec.rb +0 -159
- data/spec/timeout_spec.rb +0 -148
- data/test/kjw.rb +0 -113
- data/test/t.rb +0 -20
data/spec/cronline_spec.rb
CHANGED
@@ -5,23 +5,41 @@
|
|
5
5
|
# Sat Mar 21 12:55:27 JST 2009
|
6
6
|
#
|
7
7
|
|
8
|
-
require '
|
8
|
+
require 'spec_helper'
|
9
9
|
|
10
10
|
|
11
|
-
describe Rufus::CronLine do
|
11
|
+
describe Rufus::Scheduler::CronLine do
|
12
12
|
|
13
13
|
def cl(cronline_string)
|
14
|
-
Rufus::CronLine.new(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 }
|
15
33
|
end
|
16
34
|
|
17
35
|
def match(line, time)
|
18
|
-
cl(line).matches?(time).
|
36
|
+
expect(cl(line).matches?(time)).to eq(true)
|
19
37
|
end
|
20
38
|
def no_match(line, time)
|
21
|
-
cl(line).matches?(time).
|
39
|
+
expect(cl(line).matches?(time)).to eq(false)
|
22
40
|
end
|
23
41
|
def to_a(line, array)
|
24
|
-
cl(line).to_array.
|
42
|
+
expect(cl(line).to_array).to eq(array)
|
25
43
|
end
|
26
44
|
|
27
45
|
describe '.new' do
|
@@ -48,43 +66,61 @@ describe Rufus::CronLine do
|
|
48
66
|
|
49
67
|
to_a '0 0 1 1 *', [ [0], [0], [0], [1], [1], nil, nil, nil ]
|
50
68
|
|
51
|
-
|
69
|
+
if ruby18?
|
70
|
+
to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
|
71
|
+
else
|
72
|
+
to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
|
73
|
+
end
|
52
74
|
#
|
53
75
|
# as reported by Aimee Rose in
|
54
76
|
# https://github.com/jmettraux/rufus-scheduler/issues/56
|
55
77
|
|
56
|
-
|
78
|
+
if ruby18?
|
79
|
+
to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
|
80
|
+
else
|
81
|
+
to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
|
82
|
+
end
|
57
83
|
end
|
58
84
|
|
59
85
|
it 'rejects invalid weekday expressions' do
|
60
86
|
|
61
|
-
|
87
|
+
expect { cl '0 17 * * MON_FRI' }.to raise_error
|
62
88
|
# underline instead of dash
|
63
89
|
|
64
|
-
|
65
|
-
|
66
|
-
|
90
|
+
expect { cl '* * * * 9' }.to raise_error
|
91
|
+
expect { cl '* * * * 0-12' }.to raise_error
|
92
|
+
expect { cl '* * * * BLABLA' }.to raise_error
|
67
93
|
end
|
68
94
|
|
69
95
|
it 'rejects invalid cronlines' do
|
70
96
|
|
71
|
-
|
97
|
+
expect { cl '* nada * * 9' }.to raise_error(ArgumentError)
|
72
98
|
end
|
73
99
|
|
74
100
|
it 'interprets cron strings with TZ correctly' do
|
75
101
|
|
76
|
-
to_a
|
77
|
-
to_a
|
102
|
+
to_a('* * * * * EST', [ [0], nil, nil, nil, nil, nil, nil, 'EST' ])
|
103
|
+
to_a('* * * * * * EST', [ nil, nil, nil, nil, nil, nil, nil, 'EST' ])
|
104
|
+
|
105
|
+
to_a(
|
106
|
+
'* * * * * * America/Chicago',
|
107
|
+
[ nil, nil, nil, nil, nil, nil, nil, 'America/Chicago' ])
|
108
|
+
to_a(
|
109
|
+
'* * * * * * America/New_York',
|
110
|
+
[ nil, nil, nil, nil, nil, nil, nil, 'America/New_York' ])
|
78
111
|
|
79
|
-
|
80
|
-
|
112
|
+
expect { cl '* * * * * NotATimeZone' }.to raise_error
|
113
|
+
expect { cl '* * * * * * NotATimeZone' }.to raise_error
|
81
114
|
end
|
82
115
|
|
83
116
|
it 'interprets cron strings with / (slashes) correctly' do
|
84
117
|
|
85
118
|
to_a(
|
86
119
|
'0 */2 * * *',
|
87
|
-
[ [0], [0], (0..
|
120
|
+
[ [0], [0], (0..23).select { |e| e.even? }, nil, nil, nil, nil, nil ])
|
121
|
+
to_a(
|
122
|
+
'0 0-23/2 * * *',
|
123
|
+
[ [0], [0], (0..23).select { |e| e.even? }, nil, nil, nil, nil, nil ])
|
88
124
|
to_a(
|
89
125
|
'0 7-23/2 * * *',
|
90
126
|
[ [0], [0], (7..23).select { |e| e.odd? }, nil, nil, nil, nil, nil ])
|
@@ -108,54 +144,71 @@ describe Rufus::CronLine do
|
|
108
144
|
[ [0], [ 0, 10, 20, 30, 40, 50], nil, nil, nil, nil, nil, nil ])
|
109
145
|
end
|
110
146
|
|
147
|
+
it 'rejects / for days (every other wednesday)' do
|
148
|
+
|
149
|
+
expect {
|
150
|
+
Rufus::Scheduler::CronLine.new('* * * * wed/2')
|
151
|
+
}.to raise_error(ArgumentError)
|
152
|
+
end
|
153
|
+
|
111
154
|
it 'does not support ranges for monthdays (sun#1-sun#2)' do
|
112
155
|
|
113
|
-
|
114
|
-
Rufus::CronLine.new('* * * * sun#1-sun#2')
|
115
|
-
}.
|
156
|
+
expect {
|
157
|
+
Rufus::Scheduler::CronLine.new('* * * * sun#1-sun#2')
|
158
|
+
}.to raise_error(ArgumentError)
|
116
159
|
end
|
117
160
|
|
118
161
|
it 'accepts items with initial 0' do
|
119
162
|
|
120
|
-
to_a
|
121
|
-
|
122
|
-
to_a
|
123
|
-
|
124
|
-
to_a
|
125
|
-
|
126
|
-
to_a
|
163
|
+
to_a(
|
164
|
+
'09 * * * *', [ [0], [9], nil, nil, nil, nil, nil, nil ])
|
165
|
+
to_a(
|
166
|
+
'09-12 * * * *', [ [0], [9, 10, 11, 12], nil, nil, nil, nil, nil, nil ])
|
167
|
+
to_a(
|
168
|
+
'07-08 * * * *', [ [0], [7, 8], nil, nil, nil, nil, nil, nil ])
|
169
|
+
to_a(
|
170
|
+
'* */08 * * *', [ [0], nil, [0, 8, 16], nil, nil, nil, nil, nil ])
|
171
|
+
to_a(
|
172
|
+
'* */07 * * *', [ [0], nil, [0, 7, 14, 21], nil, nil, nil, nil, nil ])
|
173
|
+
to_a(
|
174
|
+
'* 01-09/04 * * *', [ [0], nil, [1, 5, 9], nil, nil, nil, nil, nil ])
|
175
|
+
to_a(
|
176
|
+
'* * * * 06', [ [0], nil, nil, nil, nil, [6], nil, nil ])
|
127
177
|
end
|
128
178
|
|
129
179
|
it 'interprets cron strings with L correctly' do
|
130
180
|
|
131
|
-
to_a
|
132
|
-
|
133
|
-
to_a
|
181
|
+
to_a(
|
182
|
+
'* * L * *', [[0], nil, nil, ['L'], nil, nil, nil, nil ])
|
183
|
+
to_a(
|
184
|
+
'* * 2-5,L * *', [[0], nil, nil, [2,3,4,5,'L'], nil, nil, nil, nil ])
|
185
|
+
to_a(
|
186
|
+
'* * */8,L * *', [[0], nil, nil, [1,9,17,25,'L'], nil, nil, nil, nil ])
|
134
187
|
end
|
135
188
|
|
136
189
|
it 'does not support ranges for L' do
|
137
190
|
|
138
|
-
|
139
|
-
|
191
|
+
expect { cl '* * 15-L * *'}.to raise_error(ArgumentError)
|
192
|
+
expect { cl '* * L/4 * *'}.to raise_error(ArgumentError)
|
140
193
|
end
|
141
194
|
|
142
195
|
it 'does not support multiple Ls' do
|
143
196
|
|
144
|
-
|
197
|
+
expect { cl '* * L,L * *'}.to raise_error(ArgumentError)
|
145
198
|
end
|
146
199
|
|
147
200
|
it 'raises if L is used for something else than days' do
|
148
201
|
|
149
|
-
|
202
|
+
expect { cl '* L * * *'}.to raise_error(ArgumentError)
|
150
203
|
end
|
151
204
|
|
152
205
|
it 'raises for out of range input' do
|
153
206
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
207
|
+
expect { cl '60-62 * * * *'}.to raise_error(ArgumentError)
|
208
|
+
expect { cl '62 * * * *'}.to raise_error(ArgumentError)
|
209
|
+
expect { cl '60 * * * *'}.to raise_error(ArgumentError)
|
210
|
+
expect { cl '* 25-26 * * *'}.to raise_error(ArgumentError)
|
211
|
+
expect { cl '* 25 * * *'}.to raise_error(ArgumentError)
|
159
212
|
#
|
160
213
|
# as reported by Aimee Rose in
|
161
214
|
# https://github.com/jmettraux/rufus-scheduler/pull/58
|
@@ -164,171 +217,223 @@ describe Rufus::CronLine do
|
|
164
217
|
|
165
218
|
describe '#next_time' do
|
166
219
|
|
167
|
-
def nt(cronline, now)
|
168
|
-
Rufus::CronLine.new(cronline).next_time(now)
|
169
|
-
end
|
170
|
-
|
171
220
|
it 'computes the next occurence correctly' do
|
172
221
|
|
173
|
-
|
222
|
+
in_zone 'Europe/Berlin' do
|
174
223
|
|
175
|
-
|
176
|
-
nt('* * * * sun', now).should == now + 259200
|
177
|
-
nt('* * * * * *', now).should == now + 1
|
178
|
-
nt('* * 13 * fri', now).should == now + 3715200
|
224
|
+
now = Time.at(0) - 3600
|
179
225
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
# (comment made in 2006 or 2007, the underlying libs got better and
|
185
|
-
# that slowness is gone)
|
186
|
-
|
187
|
-
nt('0 0 * * thu', now).should == now + 604800
|
188
|
-
|
189
|
-
nt('0 0 * * *', now).should == now + 24 * 3600
|
190
|
-
nt('0 24 * * *', now).should == now + 24 * 3600
|
226
|
+
expect(nt('* * * * *', now)).to eq(now + 60)
|
227
|
+
expect(nt('* * * * sun', now)).to eq(now + 259200)
|
228
|
+
expect(nt('* * * * * *', now)).to eq(now + 1)
|
229
|
+
expect(nt('* * 13 * fri', now)).to eq(now + 3715200)
|
191
230
|
|
192
|
-
|
231
|
+
expect(nt('10 12 13 12 *', now)).to eq(now + 29938200)
|
232
|
+
# this one is slow (1 year == 3 seconds)
|
233
|
+
#
|
234
|
+
# historical note:
|
235
|
+
# (comment made in 2006 or 2007, the underlying libs got better and
|
236
|
+
# that slowness is gone)
|
193
237
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
it 'computes the next occurence correctly in UTC (TZ not specified)' do
|
238
|
+
expect(nt('0 0 * * thu', now)).to eq(now + 604800)
|
239
|
+
expect(nt('00 0 * * thu', now)).to eq(now + 604800)
|
198
240
|
|
199
|
-
|
241
|
+
expect(nt('0 0 * * *', now)).to eq(now + 24 * 3600)
|
242
|
+
expect(nt('0 24 * * *', now)).to eq(now + 24 * 3600)
|
200
243
|
|
201
|
-
|
202
|
-
nt('* * * * sun', now).should == utc(1970, 1, 4)
|
203
|
-
nt('* * * * * *', now).should == utc(1970, 1, 1, 0, 0, 1)
|
204
|
-
nt('* * 13 * fri', now).should == utc(1970, 2, 13)
|
205
|
-
|
206
|
-
nt('10 12 13 12 *', now).should == utc(1970, 12, 13, 12, 10)
|
207
|
-
# this one is slow (1 year == 3 seconds)
|
208
|
-
nt('* * 1 6 *', now).should == utc(1970, 6, 1)
|
244
|
+
now = local(2008, 12, 31, 23, 59, 59, 0)
|
209
245
|
|
210
|
-
|
246
|
+
expect(nt('* * * * *', now)).to eq(now + 1)
|
247
|
+
end
|
211
248
|
end
|
212
249
|
|
213
250
|
it 'computes the next occurence correctly in local TZ (TZ not specified)' do
|
214
251
|
|
215
252
|
now = local(1970, 1, 1)
|
216
253
|
|
217
|
-
nt('* * * * *', now).
|
218
|
-
nt('* * * * sun', now).
|
219
|
-
nt('* * * * * *', now).
|
220
|
-
nt('* * 13 * fri', now).
|
254
|
+
expect(nt('* * * * *', now)).to eq(local(1970, 1, 1, 0, 1))
|
255
|
+
expect(nt('* * * * sun', now)).to eq(local(1970, 1, 4))
|
256
|
+
expect(nt('* * * * * *', now)).to eq(local(1970, 1, 1, 0, 0, 1))
|
257
|
+
expect(nt('* * 13 * fri', now)).to eq(local(1970, 2, 13))
|
221
258
|
|
222
|
-
nt('10 12 13 12 *', now).
|
259
|
+
expect(nt('10 12 13 12 *', now)).to eq(local(1970, 12, 13, 12, 10))
|
223
260
|
# this one is slow (1 year == 3 seconds)
|
224
|
-
nt('* * 1 6 *', now).
|
261
|
+
expect(nt('* * 1 6 *', now)).to eq(local(1970, 6, 1))
|
225
262
|
|
226
|
-
nt('0 0 * * thu', now).
|
263
|
+
expect(nt('0 0 * * thu', now)).to eq(local(1970, 1, 8))
|
227
264
|
end
|
228
265
|
|
229
266
|
it 'computes the next occurence correctly in UTC (TZ specified)' do
|
230
267
|
|
231
268
|
zone = 'Europe/Stockholm'
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
nt("* * * * * #{zone}", now).
|
237
|
-
nt("* *
|
238
|
-
|
239
|
-
nt("
|
240
|
-
|
241
|
-
|
242
|
-
nt("* *
|
243
|
-
|
244
|
-
nt("0 0 * * thu #{zone}", now).should == utc(1970, 1, 7, 23)
|
245
|
-
end
|
246
|
-
|
247
|
-
#it 'computes the next occurence correctly in local TZ (TZ specified)' do
|
248
|
-
# zone = 'Europe/Stockholm'
|
249
|
-
# tz = TZInfo::Timezone.get(zone)
|
250
|
-
# now = tz.local_to_utc(utc(1970, 1, 1)).localtime
|
251
|
-
# # Midnight in zone, local time
|
252
|
-
# nt("* * * * * #{zone}", now).should == local(1969, 12, 31, 18, 1)
|
253
|
-
# nt("* * * * sun #{zone}", now).should == local(1970, 1, 3, 18)
|
254
|
-
# nt("* * * * * * #{zone}", now).should == local(1969, 12, 31, 18, 0, 1)
|
255
|
-
# nt("* * 13 * fri #{zone}", now).should == local(1970, 2, 12, 18)
|
256
|
-
# nt("10 12 13 12 * #{zone}", now).should == local(1970, 12, 13, 6, 10)
|
257
|
-
# nt("* * 1 6 * #{zone}", now).should == local(1970, 5, 31, 19)
|
258
|
-
# nt("0 0 * * thu #{zone}", now).should == local(1970, 1, 7, 18)
|
259
|
-
#end
|
269
|
+
now = in_zone(zone) { Time.local(1970, 1, 1) }
|
270
|
+
|
271
|
+
expect(nt("* * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 1))
|
272
|
+
expect(nt("* * * * sun #{zone}", now)).to eq(utc(1970, 1, 3, 23))
|
273
|
+
expect(nt("* * * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 0, 1))
|
274
|
+
expect(nt("* * 13 * fri #{zone}", now)).to eq(utc(1970, 2, 12, 23))
|
275
|
+
|
276
|
+
expect(nt("10 12 13 12 * #{zone}", now)).to eq(utc(1970, 12, 13, 11, 10))
|
277
|
+
expect(nt("* * 1 6 * #{zone}", now)).to eq(utc(1970, 5, 31, 23))
|
278
|
+
|
279
|
+
expect(nt("0 0 * * thu #{zone}", now)).to eq(utc(1970, 1, 7, 23))
|
280
|
+
end
|
260
281
|
|
261
282
|
it 'computes the next time correctly when there is a sun#2 involved' do
|
262
283
|
|
263
|
-
nt('* * * * sun#1', local(1970, 1, 1)).
|
264
|
-
nt('* * * * sun#2', local(1970, 1, 1)).
|
284
|
+
expect(nt('* * * * sun#1', local(1970, 1, 1))).to eq(local(1970, 1, 4))
|
285
|
+
expect(nt('* * * * sun#2', local(1970, 1, 1))).to eq(local(1970, 1, 11))
|
265
286
|
|
266
|
-
nt('* * * * sun#2', local(1970, 1, 12)).
|
287
|
+
expect(nt('* * * * sun#2', local(1970, 1, 12))).to eq(local(1970, 2, 8))
|
267
288
|
end
|
268
289
|
|
269
|
-
it 'computes
|
290
|
+
it 'computes next time correctly when there is a sun#2,sun#3 involved' do
|
270
291
|
|
271
|
-
|
272
|
-
|
292
|
+
expect(
|
293
|
+
nt('* * * * sun#2,sun#3', local(1970, 1, 1))).to eq(local(1970, 1, 11))
|
294
|
+
expect(
|
295
|
+
nt('* * * * sun#2,sun#3', local(1970, 1, 12))).to eq(local(1970, 1, 18))
|
273
296
|
end
|
274
297
|
|
275
298
|
it 'understands sun#L' do
|
276
299
|
|
277
|
-
nt('* * * * sun#L', local(1970, 1, 1)).
|
300
|
+
expect(nt('* * * * sun#L', local(1970, 1, 1))).to eq(local(1970, 1, 25))
|
278
301
|
end
|
279
302
|
|
280
303
|
it 'understands sun#-1' do
|
281
304
|
|
282
|
-
nt('* * * * sun#-1', local(1970, 1, 1)).
|
305
|
+
expect(nt('* * * * sun#-1', local(1970, 1, 1))).to eq(local(1970, 1, 25))
|
283
306
|
end
|
284
307
|
|
285
308
|
it 'understands sun#-2' do
|
286
309
|
|
287
|
-
nt('* * * * sun#-2', local(1970, 1, 1)).
|
310
|
+
expect(nt('* * * * sun#-2', local(1970, 1, 1))).to eq(local(1970, 1, 18))
|
288
311
|
end
|
289
312
|
|
290
313
|
it 'computes the next time correctly when "L" (last day of month)' do
|
291
314
|
|
292
|
-
nt('* * L * *', lo(1970, 1, 1)).
|
293
|
-
nt('* * L * *', lo(1970, 2, 1)).
|
294
|
-
nt('* * L * *', lo(1972, 2, 1)).
|
295
|
-
nt('* * L * *', lo(1970, 4, 1)).
|
315
|
+
expect(nt('* * L * *', lo(1970, 1, 1))).to eq(lo(1970, 1, 31))
|
316
|
+
expect(nt('* * L * *', lo(1970, 2, 1))).to eq(lo(1970, 2, 28))
|
317
|
+
expect(nt('* * L * *', lo(1972, 2, 1))).to eq(lo(1972, 2, 29))
|
318
|
+
expect(nt('* * L * *', lo(1970, 4, 1))).to eq(lo(1970, 4, 30))
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'returns a time with subseconds chopped off' do
|
322
|
+
|
323
|
+
expect(
|
324
|
+
nt('* * * * *', Time.now).usec).to eq(0)
|
325
|
+
expect(
|
326
|
+
nt('* * * * *', Time.now).iso8601(10).match(/\.0+[^\d]/)).not_to eq(nil)
|
327
|
+
end
|
328
|
+
|
329
|
+
# New York EST: UTC-5
|
330
|
+
# summer (dst) EDT: UTC-4
|
331
|
+
|
332
|
+
# gh-127
|
333
|
+
#
|
334
|
+
it 'survives TZInfo::AmbiguousTime' do
|
335
|
+
|
336
|
+
if ruby18? or jruby?
|
337
|
+
expect(
|
338
|
+
ntz(
|
339
|
+
'30 1 31 10 * America/New_York',
|
340
|
+
ltz('America/New_York', 2004, 10, 1)
|
341
|
+
).strftime('%Y-%m-%d %H:%M:%S')
|
342
|
+
).to eq('2004-10-31 01:30:00')
|
343
|
+
else
|
344
|
+
expect(
|
345
|
+
ntz(
|
346
|
+
'30 1 31 10 * America/New_York',
|
347
|
+
ltz('America/New_York', 2004, 10, 1)
|
348
|
+
)
|
349
|
+
).to eq(ltz('America/New_York', 2004, 10, 31, 1, 30, 0))
|
350
|
+
end
|
296
351
|
end
|
297
|
-
end
|
298
352
|
|
299
|
-
|
353
|
+
# gh-127
|
354
|
+
#
|
355
|
+
it 'survives TZInfo::PeriodNotFound' do
|
300
356
|
|
301
|
-
|
302
|
-
|
357
|
+
expect(
|
358
|
+
ntz(
|
359
|
+
'0 2 9 3 * America/New_York',
|
360
|
+
ltz('America/New_York', 2014, 3, 1)
|
361
|
+
)
|
362
|
+
).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
|
303
363
|
end
|
364
|
+
end
|
365
|
+
|
366
|
+
describe '#previous_time' do
|
304
367
|
|
305
368
|
it 'returns the previous time the cron should have triggered' do
|
306
369
|
|
307
|
-
|
308
|
-
|
309
|
-
|
370
|
+
expect(
|
371
|
+
pt('* * * * sun', lo(1970, 1, 1))).to eq(lo(1969, 12, 28, 23, 59, 00))
|
372
|
+
expect(
|
373
|
+
pt('* * 13 * *', lo(1970, 1, 1))).to eq(lo(1969, 12, 13, 23, 59, 00))
|
374
|
+
expect(
|
375
|
+
pt('0 12 13 * *', lo(1970, 1, 1))).to eq(lo(1969, 12, 13, 12, 00))
|
376
|
+
expect(
|
377
|
+
pt('0 0 2 1 *', lo(1970, 1, 1))).to eq(lo(1969, 1, 2, 0, 00))
|
378
|
+
|
379
|
+
expect(
|
380
|
+
pt('* * * * * sun', lo(1970, 1, 1))).to eq(lo(1969, 12, 28, 23, 59, 59))
|
381
|
+
end
|
382
|
+
|
383
|
+
# New York EST: UTC-5
|
384
|
+
# summer (dst) EDT: UTC-4
|
385
|
+
|
386
|
+
# gh-127
|
387
|
+
#
|
388
|
+
it 'survives TZInfo::AmbiguousTime' do
|
389
|
+
|
390
|
+
if ruby18? or jruby?
|
391
|
+
expect(
|
392
|
+
ptz(
|
393
|
+
'30 1 31 10 * America/New_York',
|
394
|
+
ltz('America/New_York', 2004, 10, 31, 14, 30, 0)
|
395
|
+
).strftime('%Y-%m-%d %H:%M:%S')
|
396
|
+
).to eq('2004-10-31 01:30:00')
|
397
|
+
else
|
398
|
+
expect(
|
399
|
+
ptz(
|
400
|
+
'30 1 31 10 * America/New_York',
|
401
|
+
ltz('America/New_York', 2004, 10, 31, 14, 30, 0)
|
402
|
+
)
|
403
|
+
).to eq(ltz('America/New_York', 2004, 10, 31, 1, 30, 0))
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# gh-127
|
408
|
+
#
|
409
|
+
it 'survives TZInfo::PeriodNotFound' do
|
310
410
|
|
311
|
-
|
411
|
+
expect(
|
412
|
+
ptz(
|
413
|
+
'0 2 9 3 * America/New_York',
|
414
|
+
ltz('America/New_York', 2015, 3, 9, 12, 0, 0)
|
415
|
+
)
|
416
|
+
).to eq(ltz('America/New_York', 2015, 3, 9, 2, 0, 0))
|
312
417
|
end
|
313
418
|
end
|
314
419
|
|
315
420
|
describe '#matches?' do
|
316
421
|
|
317
|
-
it 'matches correctly in UTC (TZ not specified)' do
|
318
|
-
|
319
|
-
match '* * * * *', utc(1970, 1, 1, 0, 1)
|
320
|
-
match '* * * * sun', utc(1970, 1, 4)
|
321
|
-
match '* * * * * *', utc(1970, 1, 1, 0, 0, 1)
|
322
|
-
match '* * 13 * fri', utc(1970, 2, 13)
|
323
|
-
|
324
|
-
match '10 12 13 12 *', utc(1970, 12, 13, 12, 10)
|
325
|
-
match '* * 1 6 *', utc(1970, 6, 1)
|
326
|
-
|
327
|
-
match '0 0 * * thu', utc(1970, 1, 8)
|
328
|
-
|
329
|
-
match '0 0 1 1 *', utc(2012, 1, 1)
|
330
|
-
no_match '0 0 1 1 *', utc(2012, 1, 1, 1, 0)
|
331
|
-
end
|
422
|
+
# it 'matches correctly in UTC (TZ not specified)' do
|
423
|
+
#
|
424
|
+
# match '* * * * *', utc(1970, 1, 1, 0, 1)
|
425
|
+
# match '* * * * sun', utc(1970, 1, 4)
|
426
|
+
# match '* * * * * *', utc(1970, 1, 1, 0, 0, 1)
|
427
|
+
# match '* * 13 * fri', utc(1970, 2, 13)
|
428
|
+
#
|
429
|
+
# match '10 12 13 12 *', utc(1970, 12, 13, 12, 10)
|
430
|
+
# match '* * 1 6 *', utc(1970, 6, 1)
|
431
|
+
#
|
432
|
+
# match '0 0 * * thu', utc(1970, 1, 8)
|
433
|
+
#
|
434
|
+
# match '0 0 1 1 *', utc(2012, 1, 1)
|
435
|
+
# no_match '0 0 1 1 *', utc(2012, 1, 1, 1, 0)
|
436
|
+
# end
|
332
437
|
|
333
438
|
it 'matches correctly in local TZ (TZ not specified)' do
|
334
439
|
|
@@ -380,23 +485,245 @@ describe Rufus::CronLine do
|
|
380
485
|
match '* * * * sun#2,sun#3', local(1970, 1, 18)
|
381
486
|
no_match '* * * * sun#2,sun#3', local(1970, 1, 25)
|
382
487
|
end
|
488
|
+
|
489
|
+
it 'matches correctly for seconds' do
|
490
|
+
|
491
|
+
match '* * * * * *', local(1970, 1, 11)
|
492
|
+
match '* * * * * *', local(1970, 1, 11, 0, 0, 13)
|
493
|
+
end
|
494
|
+
|
495
|
+
it 'matches correctly for seconds / interval' do
|
496
|
+
|
497
|
+
match '*/2 * * * * *', local(1970, 1, 11)
|
498
|
+
match '*/5 * * * * *', local(1970, 1, 11)
|
499
|
+
match '*/5 * * * * *', local(1970, 1, 11, 0, 0, 0)
|
500
|
+
no_match '*/5 * * * * *', local(1970, 1, 11, 0, 0, 1)
|
501
|
+
match '*/5 * * * * *', local(1970, 1, 11, 0, 0, 5)
|
502
|
+
match '*/2 * * * * *', local(1970, 1, 11, 0, 0, 2)
|
503
|
+
match '*/2 * * * * *', local(1970, 1, 11, 0, 0, 2, 500)
|
504
|
+
end
|
383
505
|
end
|
384
506
|
|
385
507
|
describe '#monthdays' do
|
386
508
|
|
387
509
|
it 'returns the appropriate "sun#2"-like string' do
|
388
510
|
|
389
|
-
class Rufus::CronLine
|
511
|
+
class Rufus::Scheduler::CronLine
|
390
512
|
public :monthdays
|
391
513
|
end
|
392
514
|
|
393
|
-
cl = Rufus::CronLine.new('* * * * *')
|
515
|
+
cl = Rufus::Scheduler::CronLine.new('* * * * *')
|
516
|
+
|
517
|
+
expect(cl.monthdays(local(1970, 1, 1))).to eq(%w[ thu#1 thu#-5 ])
|
518
|
+
expect(cl.monthdays(local(1970, 1, 7))).to eq(%w[ wed#1 wed#-4 ])
|
519
|
+
expect(cl.monthdays(local(1970, 1, 14))).to eq(%w[ wed#2 wed#-3 ])
|
520
|
+
|
521
|
+
expect(cl.monthdays(local(2011, 3, 11))).to eq(%w[ fri#2 fri#-3 ])
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
describe '#frequency' do
|
394
526
|
|
395
|
-
|
396
|
-
cl.monthdays(local(1970, 1, 7)).should == %w[ wed#1 wed#-4 ]
|
397
|
-
cl.monthdays(local(1970, 1, 14)).should == %w[ wed#2 wed#-3 ]
|
527
|
+
it 'returns the shortest delta between two occurrences' do
|
398
528
|
|
399
|
-
|
529
|
+
expect(Rufus::Scheduler::CronLine.new(
|
530
|
+
'* * * * *').frequency).to eq(60)
|
531
|
+
expect(Rufus::Scheduler::CronLine.new(
|
532
|
+
'* * * * * *').frequency).to eq(1)
|
533
|
+
|
534
|
+
expect(Rufus::Scheduler::CronLine.new(
|
535
|
+
'5 23 * * *').frequency).to eq(24 * 3600)
|
536
|
+
expect(Rufus::Scheduler::CronLine.new(
|
537
|
+
'5 * * * *').frequency).to eq(3600)
|
538
|
+
expect(Rufus::Scheduler::CronLine.new(
|
539
|
+
'10,20,30 * * * *').frequency).to eq(600)
|
540
|
+
|
541
|
+
expect(Rufus::Scheduler::CronLine.new(
|
542
|
+
'10,20,30 * * * * *').frequency).to eq(10)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
546
|
+
describe '#brute_frequency' do
|
547
|
+
|
548
|
+
it 'returns the shortest delta between two occurrences' do
|
549
|
+
|
550
|
+
expect(Rufus::Scheduler::CronLine.new(
|
551
|
+
'* * * * *').brute_frequency).to eq(60)
|
552
|
+
expect(Rufus::Scheduler::CronLine.new(
|
553
|
+
'* * * * * *').brute_frequency).to eq(1)
|
554
|
+
|
555
|
+
expect(Rufus::Scheduler::CronLine.new(
|
556
|
+
'5 23 * * *').brute_frequency).to eq(24 * 3600)
|
557
|
+
expect(Rufus::Scheduler::CronLine.new(
|
558
|
+
'5 * * * *').brute_frequency).to eq(3600)
|
559
|
+
expect(Rufus::Scheduler::CronLine.new(
|
560
|
+
'10,20,30 * * * *').brute_frequency).to eq(600)
|
561
|
+
|
562
|
+
#Rufus::Scheduler::CronLine.new(
|
563
|
+
# '10,20,30 * * * * *').brute_frequency.should == 10
|
564
|
+
#
|
565
|
+
# takes > 20s ...
|
566
|
+
end
|
567
|
+
|
568
|
+
# some combos only appear every other year...
|
569
|
+
#
|
570
|
+
it 'does not go into an infinite loop' do
|
571
|
+
|
572
|
+
expect(Rufus::Scheduler::CronLine.new(
|
573
|
+
'1 2 3 4 5').brute_frequency).to eq(31622400)
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
context 'summer time' do
|
578
|
+
|
579
|
+
# let's assume summer time jumps always occur on sundays
|
580
|
+
|
581
|
+
# cf gh-114
|
582
|
+
#
|
583
|
+
it 'schedules correctly through a switch into summer time' do
|
584
|
+
|
585
|
+
in_zone 'Europe/Berlin' do
|
586
|
+
|
587
|
+
# find the summer jump
|
588
|
+
|
589
|
+
j = Time.parse('2014-02-28 12:00')
|
590
|
+
loop do
|
591
|
+
jj = j + 24 * 3600
|
592
|
+
break if jj.isdst
|
593
|
+
j = jj
|
594
|
+
end
|
595
|
+
|
596
|
+
# test
|
597
|
+
|
598
|
+
friday = j - 24 * 3600 # one day before
|
599
|
+
|
600
|
+
# verify the playground...
|
601
|
+
#
|
602
|
+
expect(friday.isdst).to eq(false)
|
603
|
+
expect((friday + 24 * 3600 * 3).isdst).to eq(true)
|
604
|
+
|
605
|
+
cl0 = Rufus::Scheduler::CronLine.new('02 00 * * 1,2,3,4,5')
|
606
|
+
cl1 = Rufus::Scheduler::CronLine.new('45 08 * * 1,2,3,4,5')
|
607
|
+
|
608
|
+
n0 = cl0.next_time(friday)
|
609
|
+
n1 = cl1.next_time(friday)
|
610
|
+
|
611
|
+
expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 TUE')
|
612
|
+
expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
|
613
|
+
|
614
|
+
expect(n0.isdst).to eq(true)
|
615
|
+
expect(n1.isdst).to eq(true)
|
616
|
+
|
617
|
+
expect(
|
618
|
+
(n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('23:02:00 FRI')
|
619
|
+
expect(
|
620
|
+
(n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('07:45:00 FRI')
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
it 'schedules correctly through a switch out of summer time' do
|
625
|
+
|
626
|
+
in_zone 'Europe/Berlin' do
|
627
|
+
|
628
|
+
# find the winter jump
|
629
|
+
|
630
|
+
j = Time.parse('2014-08-31 12:00')
|
631
|
+
loop do
|
632
|
+
jj = j + 24 * 3600
|
633
|
+
break if jj.isdst == false
|
634
|
+
j = jj
|
635
|
+
end
|
636
|
+
|
637
|
+
# test
|
638
|
+
|
639
|
+
friday = j - 24 * 3600 # one day before
|
640
|
+
|
641
|
+
# verify the playground...
|
642
|
+
#
|
643
|
+
expect(friday.isdst).to eq(true)
|
644
|
+
expect((friday + 24 * 3600 * 3).isdst).to eq(false)
|
645
|
+
|
646
|
+
cl0 = Rufus::Scheduler::CronLine.new('02 00 * * 1,2,3,4,5')
|
647
|
+
cl1 = Rufus::Scheduler::CronLine.new('45 08 * * 1,2,3,4,5')
|
648
|
+
|
649
|
+
n0 = cl0.next_time(friday)
|
650
|
+
n1 = cl1.next_time(friday)
|
651
|
+
|
652
|
+
expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 MON')
|
653
|
+
expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
|
654
|
+
|
655
|
+
expect(n0.isdst).to eq(false)
|
656
|
+
expect(n1.isdst).to eq(false)
|
657
|
+
|
658
|
+
expect(
|
659
|
+
(n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('01:02:00 FRI')
|
660
|
+
expect(
|
661
|
+
(n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('09:45:00 FRI')
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
it 'correctly increments through a DST transition' do
|
666
|
+
|
667
|
+
expect(
|
668
|
+
nt('* * * * * America/Los_Angeles', Time.utc(2015, 3, 8, 9, 59))
|
669
|
+
).to eq(Time.utc(2015, 3, 8, 10, 00))
|
670
|
+
end
|
671
|
+
|
672
|
+
it 'correctly increments every minute through a DST transition' do
|
673
|
+
|
674
|
+
in_zone 'America/Los_Angeles' do
|
675
|
+
|
676
|
+
line = cl('* * * * * America/Los_Angeles')
|
677
|
+
|
678
|
+
t = Time.local(2015, 3, 8, 1, 57)
|
679
|
+
|
680
|
+
points =
|
681
|
+
[ 0, 1, 2, 3 ].collect do
|
682
|
+
t = line.next_time(t)
|
683
|
+
t.strftime('%H:%M:%Sl') + ' ' + t.dup.utc.strftime('%H:%M:%Su')
|
684
|
+
end
|
685
|
+
|
686
|
+
expect(points).to eq(
|
687
|
+
[
|
688
|
+
'01:58:00l 09:58:00u',
|
689
|
+
'01:59:00l 09:59:00u',
|
690
|
+
'03:00:00l 10:00:00u',
|
691
|
+
'03:01:00l 10:01:00u'
|
692
|
+
]
|
693
|
+
)
|
694
|
+
end
|
695
|
+
end
|
696
|
+
|
697
|
+
it 'correctly decrements through a DST transition' do
|
698
|
+
|
699
|
+
expect(
|
700
|
+
pt('* * * * * America/Los_Angeles', Time.utc(2015, 3, 8, 10, 00))
|
701
|
+
).to eq(Time.utc(2015, 3, 8, 9, 59))
|
702
|
+
end
|
703
|
+
|
704
|
+
it 'correctly decrements every minute through a DST transition' do
|
705
|
+
|
706
|
+
in_zone 'America/Los_Angeles' do
|
707
|
+
|
708
|
+
line = cl('* * * * * America/Los_Angeles')
|
709
|
+
|
710
|
+
t = Time.local(2015, 3, 8, 3, 2)
|
711
|
+
|
712
|
+
points =
|
713
|
+
[ 0, 1, 2, 3 ].collect do
|
714
|
+
t = line.previous_time(t)
|
715
|
+
t.strftime('%H:%M:%Sl') + ' ' + t.dup.utc.strftime('%H:%M:%Su')
|
716
|
+
end
|
717
|
+
|
718
|
+
expect(points).to eq(
|
719
|
+
[
|
720
|
+
'03:01:00l 10:01:00u',
|
721
|
+
'03:00:00l 10:00:00u',
|
722
|
+
'01:59:00l 09:59:00u',
|
723
|
+
'01:58:00l 09:58:00u'
|
724
|
+
]
|
725
|
+
)
|
726
|
+
end
|
400
727
|
end
|
401
728
|
end
|
402
729
|
end
|