ggoodale-recurring 0.5.3

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/History.txt ADDED
@@ -0,0 +1,32 @@
1
+ == 0.5.3 / 2009-8-12
2
+
3
+ * fixed issue with schedules of the form 'every n months on the first <weekday>' due to inconsistent handling of week starting day.
4
+
5
+ == 0.5.2 / 2008-3-7
6
+
7
+ * fixes to time corner-cases.
8
+
9
+ == 0.4.4 / 2006-1-24
10
+
11
+ * Recurring::DateLanguage is an experiment for making a dsl for Recurring::Schedule. Not yet usable.
12
+
13
+ == 0.3.5 / 2006-12-14
14
+
15
+ * documentation / hoe
16
+
17
+ == 0.3.2 / 2006-12-13
18
+
19
+ * initialization bugfixes
20
+
21
+ == 0.2.0 / 2006-12-11
22
+
23
+ * Documentation
24
+ * find_before
25
+ * bugfixes
26
+
27
+
28
+ == 0.1.0 / 2006-12-09
29
+
30
+ * Initial release
31
+ * Handles the basic API: include? find_in_range
32
+
data/Manifest.txt ADDED
@@ -0,0 +1,9 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/date_language.rb
6
+ lib/recurring.rb
7
+ lib/schedule.rb
8
+ spec/date_language_spec.rb
9
+ spec/schedule_spec.rb
data/README.txt ADDED
@@ -0,0 +1,63 @@
1
+ Recurring::Schedule
2
+ by Chris Anderson
3
+ http://recurring.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Recurring allows you to define Schedules, which can tell you whether or not a given Time falls in the Schedule, as well as being able to return a list of times which match the Schedule within a given range.
8
+
9
+ Schedules can be like:
10
+ * Every Tuesday at 5pm
11
+ * The 1st and 15th of every other month
12
+ * Every 2 hours
13
+ * The first Friday of every month at 11:15am and 4:45:15pm
14
+
15
+ = See more examples at Recurring::Schedule documentation
16
+
17
+ # This Schedule will match every Tuesday at 5pm
18
+ @rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => 'tuesday', :times => '5pm'
19
+ @rs.include?(Time.utc(2006,12,12,17)) #=> true
20
+ @rs.include?(Time.utc(2006,12,13,17)) #=> false
21
+
22
+ = Features
23
+ * Fast searching of long ranges for matching times.
24
+ * Ability to define Schedules in a few flexible ways.
25
+ * Extensive RSpec specifications (run "rake spec" to see them)
26
+ * Extensive RSpec specifications (run "rake spec" to see them)
27
+
28
+ = Problems / Todo
29
+ * Untested timezone support
30
+ * Plans to offer complex Schedule and Masks
31
+
32
+ == REQUIREMENTS:
33
+
34
+ * RSpec >= 0.7.4 to run the specs.
35
+
36
+ == INSTALL:
37
+
38
+ * just run <tt>gem install recurring</tt>
39
+
40
+ == LICENSE:
41
+
42
+ (The MIT License)
43
+
44
+ Copyright (c) 2006 Chris Anderson
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining
47
+ a copy of this software and associated documentation files (the
48
+ 'Software'), to deal in the Software without restriction, including
49
+ without limitation the rights to use, copy, modify, merge, publish,
50
+ distribute, sublicense, and/or sell copies of the Software, and to
51
+ permit persons to whom the Software is furnished to do so, subject to
52
+ the following conditions:
53
+
54
+ The above copyright notice and this permission notice shall be
55
+ included in all copies or substantial portions of the Software.
56
+
57
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
58
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
59
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
60
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
61
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
62
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
63
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require './lib/recurring'
5
+ require 'spec/rake/spectask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+
9
+ Spec::Rake::SpecTask.new :spec do |t|
10
+ t.spec_files = FileList['spec/**/*_spec.rb']
11
+ t.spec_opts << "-f s"
12
+ end
13
+
14
+ task :default => :spec
15
+
16
+ specification = Gem::Specification.new do |s|
17
+ s.name = %q{recurring}
18
+ s.version = Recurring::VERSION
19
+ s.platform = Gem::Platform::RUBY
20
+ s.date = %q{2006-12-11}
21
+ s.summary = %q{A scheduling library for recurring events}
22
+ s.email = %q{jchris@mfdz.com}
23
+ s.homepage = %q{http://jchris.mfdz.com}
24
+ s.description = %q{Recurring allows you to define Schedules, which can tell you whether or not a given Time falls in the Schedule, as well as being able to return a list of times which match the Schedule within a given range.}
25
+ s.authors = ["Chris Anderson"]
26
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "lib/recurring.rb", "spec/date_language_spec.rb", "spec/schedule_spec.rb"]
27
+ s.add_development_dependency(%q<rspec>, [">= 0.7.4"])
28
+ s.has_rdoc = true
29
+ end
30
+
31
+ Rake::GemPackageTask.new specification do |pkg|
32
+ pkg.need_zip = true
33
+ pkg.need_tar = true
34
+ end
35
+
36
+ Rake::RDocTask.new(:docs) do |rd|
37
+ rd.main = "README.txt"
38
+ rd.options << '-d' if RUBY_PLATFORM !~ /win32/ and `which dot` =~ /\/dot/
39
+ rd.rdoc_dir = 'doc'
40
+ files = ["History.txt", "README.txt", "Rakefile", "lib/date_language.rb", "lib/recurring.rb", "lib/schedule.rb", "spec/date_language_spec.rb", "spec/schedule_spec.rb"]
41
+ rd.rdoc_files.push(*files)
42
+ title = "Recurring Documentation"
43
+ rd.options << "-t #{title}"
44
+ end
45
+
46
+ desc "Generate a gemspec file"
47
+ task :gemspec do
48
+ File.open("#{specification.name}.gemspec", 'w') do |f|
49
+ f.write specification.to_ruby
50
+ end
51
+ end
52
+
53
+
data/lib/recurring.rb ADDED
@@ -0,0 +1,3 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/schedule")
2
+ require File.expand_path(File.dirname(__FILE__) + "/date_language")
3
+
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ gem 'rspec'
3
+ require File.dirname(__FILE__) + "/../lib/date_language"
4
+ #require 'yaml'
5
+
6
+ context "Every two days from 2006/11/3" do
7
+ setup do
8
+ @rdl = Recurring::DateLanguage.tell do
9
+ every 2, :days, :anchor => Time.utc(2006,11,3)
10
+ times '4:45am 3pm'
11
+ end
12
+ end
13
+
14
+ specify "should intialize properly" do
15
+ @rdl.frequency.should == 2
16
+ end
17
+ # specify "should return an rdl" do
18
+ # @rdl.class.should == Recurring::DateLanguage
19
+ # end
20
+ # specify "should include the correct days at the times specified" do
21
+ # @rdl.should_include Time.utc(2006,11,3,4,45)
22
+ # @rdl.should_include Time.utc(2006,11,5,4,45)
23
+ # @rdl.should_include Time.utc(2006,11,19,3)
24
+ # end
25
+ # specify "should not include wrong times" do
26
+ # @rdl.should_not_include Time.utc(2006,11,3)
27
+ # end
28
+ end
29
+
30
+
31
+ context "Converting from RDL to Schedule" do
32
+ specify "should call the right things on mocks and stubs" do
33
+ end
34
+ end
@@ -0,0 +1,870 @@
1
+ require 'rubygems'
2
+ gem 'rspec'
3
+ require File.dirname(__FILE__) + "/../lib/recurring"
4
+ require 'yaml'
5
+
6
+ def results_should_be_included results, schedule
7
+ results.each do |t|
8
+ schedule.should include(t)
9
+ end
10
+ end
11
+
12
+ def should_find_in_range schedule, length, *range
13
+ result = schedule.find_in_range(range)
14
+ result.length.should == length
15
+ results_should_be_included result, schedule
16
+ result
17
+ end
18
+
19
+ describe "Initializing a Schedule" do
20
+
21
+ it "should accept the frequency, unit, and anchor params" do
22
+ rs = Recurring::Schedule.new :unit => 'days', :frequency => 2, :anchor => Time.utc(2006,8,11)
23
+ rs.unit.should == :days
24
+ rs.frequency.should == 2
25
+ rs.anchor.should == Time.utc(2006,8,11)
26
+ end
27
+
28
+ it "should check for valid units" do
29
+ lambda{@rs = Recurring::Schedule.new :unit => 'day', :times => '4:29am'}.should raise_error(ArgumentError)
30
+ end
31
+
32
+ it "should parse the time param" do
33
+ rs = Recurring::Schedule.new :unit => 'days', :times => '4:30pm 5pm 3:30:30'
34
+ rs.times.should == [{:hour => 16, :minute => 30, :second => 0}, {:hour => 17, :minute => 0, :second => 0}, {:hour => 3, :minute => 30, :second => 30}]
35
+ end
36
+
37
+ it "should not add 12 hours to '12pm'" do
38
+ rs = Recurring::Schedule.new :unit => 'days', :times => '12pm'
39
+ rs.times.should == [{:hour => 12, :minute => 0, :second => 0}]
40
+ end
41
+
42
+ it "should subtract 12 hours from '12am'" do
43
+ rs = Recurring::Schedule.new :unit => 'days', :times => '12am'
44
+ rs.times.should == [{:hour => 0, :minute => 0, :second => 0}]
45
+ end
46
+
47
+
48
+
49
+ it "should == graceful about a duplicate times string" do
50
+ rs = Recurring::Schedule.new :unit => 'days', :times => '4:30 4:30'
51
+ rs.times.should == [{:hour => 4, :minute => 30, :second => 0}]
52
+ end
53
+
54
+ it "should == graceful about a busted times string" do
55
+ rs = Recurring::Schedule.new :unit => 'days', :times => 'afs4 th'
56
+ rs.times.should == [{:hour => 0, :minute => 0, :second => 0}]
57
+ end
58
+
59
+ it "should == graceful about an empty times string" do
60
+ rs = Recurring::Schedule.new :unit => 'days', :times => ''
61
+ rs.times.should == [{:hour => 0, :minute => 0, :second => 0}]
62
+ end
63
+
64
+ it "should provide a sensible default time param" do
65
+ rs = Recurring::Schedule.new :unit => 'days'
66
+ rs.times.should == [{:hour => 0, :minute => 0, :second => 0}]
67
+ end
68
+
69
+ it "should flip out if the units are not provided" do
70
+ lambda{Recurring::Schedule.new :argument => 'no units, dogg'}.should raise_error(ArgumentError)
71
+ end
72
+
73
+ it "should accept weeks and days params" do
74
+ rs = Recurring::Schedule.new :unit => 'months', :weeks => [1,2], :weekdays => %w{monday wednesday}
75
+ rs.weeks.should == [1,2]
76
+ rs.weekdays.should == [1,3]
77
+ end
78
+
79
+ it "should flip out if weekdays aren't in the white list" do
80
+ lambda{Recurring::Schedule.new :unit => 'months', :weeks => [1,2], :weekdays => %w{garbage_day thanksgiving}}.should raise_error(ArgumentError)
81
+ end
82
+
83
+ it "should flip out if months aren't in the white list" do
84
+ lambda{Recurring::Schedule.new :unit => 'years', :months => %w{monsoon ramadan}, :weeks => [1,2], :weekdays => %w{mon}}.should raise_error(ArgumentError)
85
+ end
86
+
87
+ it "should accept months params" do
88
+ rs = Recurring::Schedule.new :unit => 'years', :months => 'feb', :monthdays => [4]
89
+ rs.months.should == [2]
90
+ end
91
+
92
+ it "should accept monthdays as strings" do
93
+ rs = Recurring::Schedule.new :unit => 'months', :monthdays => ['1','15']
94
+ rs.monthdays.should == [1,15]
95
+ end
96
+
97
+ it "should accept monthdays as integers" do
98
+ rs = Recurring::Schedule.new :unit => 'months', :monthdays => [1,15]
99
+ rs.monthdays.should == [1,15]
100
+ end
101
+
102
+ end
103
+
104
+ describe "A complex Schedule" do
105
+ setup do
106
+ @rs = Recurring::Schedule.new :unit => 'months', :frequency => 2, :anchor => Time.utc(2006,4,15,10,30), :monthdays => [3,7], :times => '5pm 4:45:12am'
107
+ end
108
+
109
+ it "should == marshallable" do
110
+ rm = Marshal.dump(@rs)
111
+ Marshal.load(rm).should == @rs
112
+ end
113
+
114
+ it "should == YAMLable" do
115
+ rm = YAML.dump(@rs)
116
+ YAML.load(rm).should == @rs
117
+ end
118
+
119
+ it "should == equal to a schedule with the same params" do
120
+ r2 = Recurring::Schedule.new :unit => 'months', :frequency => 2, :anchor => Time.utc(2006,4,15,10,30), :monthdays => [3,7], :times => '5pm 4:45:12am'
121
+ r2.should == @rs
122
+ end
123
+
124
+ it "should not == equal to a slightly different schedule" do
125
+ r2 = Recurring::Schedule.new :unit => 'months', :frequency => 2, :anchor => Time.utc(2006,4,15,10,30), :monthdays => [3,7], :times => '5pm 4:45:11am'
126
+ r2.should_not == @rs
127
+ end
128
+
129
+ end
130
+
131
+
132
+ #YEARS
133
+ describe "A basic yearly schedule" do
134
+ setup do
135
+ @rs = Recurring::Schedule.new :unit => 'years', :frequency => 1, :anchor => Time.utc(2008,3,6)
136
+ end
137
+
138
+ it "should include next year" do
139
+ @rs.should include(Time.utc(2009,3,6))
140
+ @rs.should include(Time.utc(2010,3,6))
141
+ end
142
+ it "should not include a random wrong time" do
143
+ @rs.should_not include(Time.utc(2008,4,6))
144
+ end
145
+ it "should find the right next" do
146
+ @rs.find_next(Time.utc(2008,3,6)).should == Time.utc(2008,3,6)
147
+ @rs.find_next(Time.utc(2008,3,7)).should == Time.utc(2009,3,6)
148
+ @rs.find_next(Time.utc(2008,3,6,1)).should == Time.utc(2009,3,6)
149
+ end
150
+ end
151
+
152
+ describe "A basic bi-yearly schedule" do
153
+ setup do
154
+ @rs = Recurring::Schedule.new :unit => 'years', :frequency => 2, :anchor => Time.utc(2008,3,6)
155
+ end
156
+
157
+ it "should include next year" do
158
+ @rs.should_not include(Time.utc(2009,3,6))
159
+ @rs.should include(Time.utc(2010,3,6))
160
+ end
161
+ end
162
+
163
+ describe "A yearly schedule with month and monthdays" do
164
+ setup do
165
+ @rs = Recurring::Schedule.new :unit => 'years', :months => 'feb', :monthdays => [4]
166
+ end
167
+
168
+ it "should include the day of the month in any year" do
169
+ @rs.should include(Time.utc(1980,2,4))
170
+ @rs.should include(Time.utc(1989,2,4))
171
+ end
172
+ it "should not include other days of the month in any year" do
173
+ @rs.should_not include(Time.utc(1989,4,4))
174
+ @rs.should_not include(Time.utc(1980,2,5))
175
+ end
176
+
177
+ it "should find 20 times in 20 years" do
178
+ should_find_in_range(@rs, 20, Time.utc(2006,12,12,1), Time.utc(2026,12,12,1,45))
179
+ end
180
+ end
181
+
182
+ describe "A yearly schedule with months and weekdays" do
183
+ setup do
184
+ @rs = Recurring::Schedule.new :unit => 'years', :months => 'feb', :weekdays => ['tuesday', 'weds']
185
+ end
186
+ it "should match every tuesday and wednesday in febraury" do
187
+ @rs.should include(Time.utc(2007,2,6))
188
+ @rs.should include(Time.utc(2007,2,7))
189
+ @rs.should include(Time.utc(2007,2,20))
190
+ @rs.should include(Time.utc(2007,2,21))
191
+ end
192
+ it "should not include other days of the week in feburary" do
193
+ @rs.should_not include(Time.utc(2007,2,8))
194
+ @rs.should_not include(Time.utc(2007,2,9))
195
+ @rs.should_not include(Time.utc(2007,2,23))
196
+ @rs.should_not include(Time.utc(2007,2,24))
197
+ end
198
+ it "should not include tuesday and wednesday outside of febraury" do
199
+ @rs.should_not include(Time.utc(2007,3,6))
200
+ @rs.should_not include(Time.utc(2007,3,7))
201
+ @rs.should_not include(Time.utc(2007,3,20))
202
+ @rs.should_not include(Time.utc(2007,3,21))
203
+ end
204
+ it "should find 20 times in 20 years" do
205
+ should_find_in_range(@rs, 161, Time.utc(2006,12,12,1), Time.utc(2026,12,12,1,45))
206
+ end
207
+ end
208
+
209
+ describe "A bi-yearly schedule with months, weeks, weekdays, and times" do
210
+ setup do
211
+ @rs = Recurring::Schedule.new :unit => 'years', :frequency => 2, :anchor => Time.utc(2006,6), :months => ['feb', 'may'], :weeks => [2], :weekdays => 'fri', :times => '5:15'
212
+ end
213
+
214
+ it "should include the correct days at the right times" do
215
+ @rs.should include(Time.utc(2006,2,10,5,15))
216
+ @rs.should include(Time.utc(2006,5,12,5,15))
217
+ @rs.should include(Time.utc(2008,2,8,5,15))
218
+ @rs.should include(Time.utc(2008,5,9,5,15))
219
+ end
220
+
221
+ it "should not include good times in bad years" do
222
+ @rs.should_not include(Time.utc(2007,2,9,5,15))
223
+ @rs.should_not include(Time.utc(2007,5,11,5,15))
224
+ end
225
+ end
226
+
227
+ #MONTHS
228
+
229
+ describe "A bi-monthly Schedule without more params" do
230
+
231
+ setup do
232
+ @rs = Recurring::Schedule.new :unit => 'months', :frequency => 2, :anchor => Time.utc(2006,4,15,10,30)
233
+ end
234
+
235
+ it "should include the anchor date" do
236
+ @rs.should include(Time.utc(2006,4,15,10,30))
237
+ end
238
+
239
+ it "should include dates offset by the frequency" do
240
+ @rs.should include(Time.utc(2006,6,15,10,30))
241
+ end
242
+
243
+ it "should not include the beginnings of days for which it includes points in the middle" do
244
+ @rs.should_not include(Time.utc(2006,6,15))
245
+ @rs.should_not include(Time.utc(2006,4,15))
246
+ end
247
+
248
+ it "should not include dates with wrong months" do
249
+ @rs.should_not include(Time.utc(2006,5,15,10,30))
250
+ end
251
+
252
+ it "should not include dates without matching time parts" do
253
+ @rs.should_not include(Time.utc(2006,4,16))
254
+ @rs.should_not include(Time.utc(2006,6,15,10,15))
255
+ end
256
+
257
+ it "should find that the start point is the next included date when the start point matches" do
258
+ included = Time.utc(2006,6,15,10,30)
259
+ @rs.find_next(included).should == included
260
+ end
261
+
262
+ it "should find the next date when the start point doesn't match" do
263
+ @rs.find_next(Time.utc(2006,6,15)).should == Time.utc(2006,6,15,10,30)
264
+ end
265
+
266
+ end
267
+
268
+ describe "A monthly schedule with monthday params" do
269
+ setup do
270
+ @rs = Recurring::Schedule.new :unit => 'months', :monthdays => [1,15]
271
+ # @rs.anchor = Time.utc(2006,6,18,12,30) #should react appropriately to the presence of a (no longer useless) anchor
272
+ end
273
+
274
+ it "should include the start of matching days" do
275
+ @rs.should include(Time.utc(2006,6,15))
276
+ @rs.should include(Time.utc(2006,7,1))
277
+ end
278
+
279
+ it "should not include the middle of matching days" do
280
+ @rs.should_not include(Time.utc(2006,6,15,14))
281
+ @rs.should_not include(Time.utc(2006,7,1,11,30))
282
+ @rs.should_not include(Time.utc(2006,7,1,0,0,30))
283
+ end
284
+
285
+ it "should not include the start of non-matching days" do
286
+ @rs.should_not include(Time.utc(2006,6,14))
287
+ @rs.should_not include(Time.utc(2006,7,2))
288
+ end
289
+
290
+ it "should not include times with no matching component" do
291
+ @rs.should_not include(Time.utc(2006,6,14,11,8))
292
+ @rs.should_not include(Time.utc(2006,7,2,5,30) )
293
+ end
294
+
295
+ it "should find the next date" do
296
+ @rs.find_next(Time.utc(2006,3,4)).should == Time.utc(2006,3,15)
297
+ @rs.find_next(Time.utc(2006,3,17)).should == Time.utc(2006,4,1)
298
+ end
299
+
300
+ end
301
+
302
+ describe "A bi-monthly Schedule with monthday params" do
303
+
304
+ setup do
305
+ @rs = Recurring::Schedule.new :unit => 'months', :frequency => 2, :anchor => Time.utc(2006,4,15,10,30), :monthdays => [10,18]
306
+ end
307
+
308
+ it "should include the beginnings of matching days" do
309
+ @rs.should include(Time.utc(2006,6,10))
310
+ @rs.should include(Time.utc(2006,8,18))
311
+ end
312
+
313
+ it "should not include the beginnings of non_matching days" do
314
+ @rs.should_not include(Time.utc(2006,6,11))
315
+ end
316
+
317
+ it "should not include the beginning of the anchor day" do
318
+ @rs.should_not include(Time.utc(2006,4,15))
319
+ end
320
+
321
+ it "should not include the anchor time" do
322
+ @rs.should_not include(Time.utc(2006,4,15,10,30))
323
+ end
324
+
325
+ it "should find the next date when the start point doesn't match" do
326
+ @rs.find_next(Time.utc(2006,6,15)).should == Time.utc(2006,6,18)
327
+ end
328
+
329
+ it "should find the next date" do
330
+ @rs.find_next(Time.utc(2006,5,4)).should == Time.utc(2006,6,10)
331
+ @rs.find_next(Time.utc(2006,6,11)).should == Time.utc(2006,6,18)
332
+ end
333
+ end
334
+
335
+ describe "A monthly schedule with week params" do
336
+ end
337
+
338
+ describe "A third-monthly schedule with week params" do
339
+
340
+ setup do
341
+ lambda{@rs = Recurring::Schedule.new :unit => 'months', :week => 1, :frequency => 3}.should raise_error(ArgumentError)
342
+ end
343
+
344
+ it "should walk up the stairs" do
345
+ end
346
+
347
+
348
+ end
349
+
350
+ describe "A monthly schedule with week params and weekday params" do
351
+
352
+ setup do
353
+ @rs = Recurring::Schedule.new :unit => 'months', :weeks => 1, :weekdays => :saturday
354
+ end
355
+
356
+ it "should include the beginnings of matching days" do
357
+ @rs.should include(Time.utc(2006,12,2))
358
+ end
359
+
360
+ it "should not include the matching days in off weeks" do
361
+ @rs.should_not include(Time.utc(2006,12,23))
362
+ @rs.should_not include(Time.utc(2006,12,9))
363
+ end
364
+
365
+ it "should have a next occurrence date no more than 38 days in the future" do
366
+ # August 4, 2009 is a Saturday. So is September 5. Calling next()
367
+ # in 0.5.2 would return Nov. 7, 2009 as the next occurrence.
368
+ @rs.find_next(Time.utc(2009,8,2)).should == Time.utc(2009,9,5)
369
+ end
370
+
371
+
372
+ end
373
+
374
+ describe "A monthly schedule with weekday params but no week params" do
375
+ end
376
+
377
+ describe "A six-monthly schedule with week, weekday, and times params" do
378
+ end
379
+
380
+ describe "A monthly schedule with negative week params and weekday params" do
381
+
382
+ setup do
383
+ @rs = Recurring::Schedule.new :unit => 'months', :weeks => -1,
384
+ :weekdays => :monday
385
+ end
386
+ it "should include the beginnings of matching days" do
387
+ @rs.should include(Time.utc(2006,12,25))
388
+ @rs.should include(Time.utc(2007,4,30))
389
+ end
390
+ it "should not include the matching days in off weeks" do
391
+ @rs.should_not include(Time.utc(2006,12,18))
392
+ @rs.should_not include(Time.utc(2006,12,11))
393
+ @rs.should_not include(Time.utc(2006,12,4))
394
+ end
395
+
396
+ end
397
+
398
+ #WEEKLY
399
+
400
+ describe "A bi-weekly schedule with weekdays and a midnight time" do
401
+ setup do
402
+ @rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => %w{sat sunday}, :times => '12am', :frequency => 2, :anchor => Time.utc(2001)
403
+ @danger = Time.utc(2006,12,17,18)
404
+ end
405
+
406
+ it "should include midnights of every other weekend" do
407
+ @rs.should include(Time.utc(2006,12,16))
408
+ @rs.should include(Time.utc(2006,12,10))
409
+ end
410
+
411
+ it "should not include other midnights" do
412
+ @rs.should_not include(Time.utc(2006,12,22))
413
+ @rs.should_not include(Time.utc(2006,12,25))
414
+ end
415
+
416
+ it "should find the previous time from a dangerous time" do
417
+ @rs.find_previous(@danger).should == Time.utc(2006,12,16)
418
+ end
419
+
420
+ end
421
+
422
+ describe "A bi-weekly schedule with weekdays and a noon time" do
423
+ setup do
424
+ @rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => %w{sat sunday}, :times => '12pm', :frequency => 2, :anchor => Time.utc(2001)
425
+ @danger = Time.utc(2006,12,17,18)
426
+ end
427
+
428
+ it "should include noons of every other weekend" do
429
+ @rs.should include(Time.utc(2006,12,10,12))
430
+ @rs.should include(Time.utc(2006,12,16,12))
431
+ end
432
+
433
+ it "should not include other midnights" do
434
+ @rs.should_not include(Time.utc(2006,12,22,12))
435
+ @rs.should_not include(Time.utc(2006,12,25,12))
436
+ end
437
+
438
+ it "should find the previous time from a dangerous time" do
439
+ @rs.find_previous(@danger).should == Time.utc(2006,12,16,12)
440
+ end
441
+ end
442
+
443
+ describe "A weekly schedule with weekday params" do
444
+
445
+ setup do
446
+ @rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => %w{sunday monday weds friday}
447
+ end
448
+
449
+ it "should include the beginnings of matching days" do
450
+ @rs.should include(Time.utc(2006,12,3))
451
+ @rs.should include(Time.utc(2006,12,6))
452
+ @rs.should include(Time.utc(2006,11,27))
453
+ end
454
+
455
+ it "should not include the middle of matching days" do
456
+ @rs.should_not include(Time.utc(2006,12,6,10,30))
457
+ @rs.should_not include(Time.utc(2006,11,27,0,30))
458
+ @rs.should_not include(Time.utc(2006,12,7))
459
+ end
460
+
461
+ it "should find the next date" do
462
+ @rs.find_next(Time.utc(2006,12,2)).should == Time.utc(2006,12,3)
463
+ @rs.find_next(Time.utc(2006,11,30)).should == Time.utc(2006,12,1)
464
+ end
465
+
466
+ end
467
+
468
+ describe "A Schedule with uppercase weekdays" do
469
+ setup do
470
+ @rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => %w{Friday}, :anchor => Time.now, :times => '12'
471
+ end
472
+
473
+ it "should include Friday's at noon" do
474
+ @rs.should include(Time.utc(2006,12,8,12))
475
+ end
476
+ end
477
+
478
+ describe "A weekly schedule with only an anchor" do
479
+
480
+ setup do
481
+ @rs = Recurring::Schedule.new :unit => 'weeks', :anchor => Time.utc(2006,12,6,17,30)
482
+ end
483
+
484
+ it "should include times that are offset by one week" do
485
+ @rs.should include(Time.utc(2006,12,20,17,30))
486
+ end
487
+
488
+ it "should not include times that are not offset by one week" do
489
+ @rs.should_not include(Time.utc(2006,12,19,17,30))
490
+ @rs.should_not include(Time.utc(2006,12,20))
491
+ @rs.should_not include(Time.utc(2006,5,6,17,30))
492
+ end
493
+
494
+ it "should find the next date" do
495
+ @rs.find_next(Time.utc(2006,5,4)).should == Time.utc(2006,5,10,17,30)
496
+ @rs.find_next(Time.utc(2006,6,11)).should == Time.utc(2006,6,14,17,30)
497
+ end
498
+
499
+ it "should find the previous date" do
500
+ @rs.find_previous(Time.utc(2006,5,14)).should == Time.utc(2006,5,10,17,30)
501
+ end
502
+ end
503
+
504
+ describe "A third-weekly schedule with weekday and times params" do
505
+
506
+ setup do
507
+ @rs = Recurring::Schedule.new :unit => 'weeks', :frequency => 3, :anchor => Time.utc(2006,12,1), :weekdays => %w{mon fri sat}, :times => '3pm'
508
+ end
509
+
510
+ it "should include the proper times on the right days of matching weeks" do
511
+ @rs.should include(Time.utc(2006,11,27,15))
512
+ @rs.should include(Time.utc(2006,12,1,15))
513
+ @rs.should include(Time.utc(2006,12,2,15))
514
+ @rs.should include(Time.utc(2006,12,18,15))
515
+ end
516
+
517
+ it "should not include the beginnings of matching days" do
518
+ @rs.should_not include(Time.utc(2006,12,1))
519
+ end
520
+
521
+ it "should not include the proper times on the right days of non-matching weeks" do
522
+ @rs.should_not include(Time.utc(2006,12,4,15))
523
+ end
524
+
525
+ it "should find the next date" do
526
+ @rs.find_next(Time.utc(2006,12,4)).should == Time.utc(2006,12,18,15)
527
+ @rs.find_next(Time.utc(2006,12,18)).should == Time.utc(2006,12,18,15)
528
+ end
529
+
530
+ it "should find the previous date" do
531
+ @rs.find_previous(Time.utc(2006,12,4)).should == Time.utc(2006,12,2,15)
532
+ @rs.find_previous(Time.utc(2006,12,18,20)).should == Time.utc(2006,12,18,15)
533
+ end
534
+
535
+ end
536
+
537
+ describe "Recurring.week_of_year" do
538
+
539
+ it "should return the same value for days in the same week" do
540
+ [[2006,12,1],
541
+ [2006,12,2],
542
+ [2006,11,28],
543
+ [2006,11,26]].collect do |args|
544
+ Time.utc *args
545
+ end.each do |t|
546
+ Recurring.week_of_year(t).should == 48
547
+ end
548
+
549
+ [[2006,12,7],
550
+ [2006,12,9],
551
+ [2006,12,3]].collect do |args|
552
+ Time.utc *args
553
+ end.each do |t|
554
+ Recurring.week_of_year(t).should == 49
555
+ end
556
+ end
557
+
558
+ end
559
+
560
+ describe "A weekly schedule with times params but no days params" do
561
+
562
+ it "should flip out hard" do
563
+ lambda{@rs = Recurring::Schedule.new :unit => 'weeks', :times => '4pm'}.should raise_error( ArgumentError)
564
+ end
565
+
566
+ end
567
+
568
+ #DAILY
569
+
570
+ describe "A daily schedule with no other params" do
571
+
572
+ setup do
573
+ @rs = Recurring::Schedule.new :unit => 'days'
574
+ end
575
+
576
+ it "should match the beginning of every day" do
577
+ @rs.should include(Time.utc(2006,11,5))
578
+ @rs.should include(Time.mktime(2006,11,5))
579
+ end
580
+
581
+ it "should not match the middle of any day" do
582
+ @rs.should_not include(Time.utc(2006,11,5,5))
583
+ @rs.should_not include(Time.utc(2006,11,5,0,0,22))
584
+ end
585
+
586
+ it "should find the next date" do
587
+ @rs.find_next(Time.utc(2006,5,4,2)).should == Time.utc(2006,5,5)
588
+ @rs.find_next(Time.utc(2006,6,13,5)).should == Time.utc(2006,6,14)
589
+ end
590
+
591
+ end
592
+
593
+ describe "A daily schedule with an anchor" do
594
+ setup do
595
+ @rs = Recurring::Schedule.new :unit => 'days', :anchor => Time.utc(2006,11,1,10,15,22)
596
+ end
597
+
598
+ it "should include daily mulitples of the anchor" do
599
+ @rs.should include(Time.utc(2006,11,7,10,15,22))
600
+ end
601
+
602
+ it "should not include other times in any day" do
603
+ @rs.should_not include(Time.utc(2006,11,7))
604
+ @rs.should_not include(Time.utc(2006,11,7,10,15,21))
605
+ end
606
+
607
+ it "should find the next date" do
608
+ @rs.find_next(Time.utc(2006,5,4,12)).should == Time.utc(2006,5,5,10,15,22)
609
+ @rs.find_next(Time.utc(2006,6,13,5)).should == Time.utc(2006,6,13,10,15,22)
610
+ end
611
+ end
612
+
613
+ describe "A fourth-daily schedule with only the unit and frequency != 1" do
614
+ it "should have an ArgumentError" do
615
+ lambda{@rs = Recurring::Schedule.new :unit => 'days', :frequency => 4}.should raise_error(ArgumentError)
616
+ end
617
+ end
618
+
619
+ describe "A daily schedule with a sub-second precise anchor" do
620
+ setup do
621
+ @rs = Recurring::Schedule.new :unit => 'days', :anchor => Time.utc(2006,11,27,0,0,30,45)
622
+ end
623
+ it "should include times equal up to second accuracy" do
624
+ @rs.should include(Time.utc(2006,11,27,0,0,30))
625
+ @rs.should include(Time.utc(2006,11,27,0,0,30,55))
626
+ end
627
+ it "should not include other times" do
628
+ @rs.should_not include(Time.utc(2006,11,27,0,0,31,45))
629
+ end
630
+ end
631
+
632
+ describe "A fourth-daily schedule with no other params" do
633
+
634
+ setup do
635
+ @rs = Recurring::Schedule.new :unit => 'days', :frequency => 4, :anchor => Time.utc(2006,11,1,9,30)
636
+ end
637
+
638
+ it "should check the anchor" do
639
+ @rs.send(:check_anchor?).should == true
640
+ end
641
+
642
+ it "should include the anchor" do
643
+ @rs.should include(Time.utc(2006,11,1,9,30))
644
+ end
645
+
646
+ it "should not include the beginning of the anchor day" do
647
+ @rs.should_not include(Time.utc(2006,11,1))
648
+ end
649
+
650
+ it "should include the time of the anchor, every four days" do
651
+ @rs.should include(Time.utc(2006,11,5,9,30))
652
+ @rs.should include(Time.utc(2006,10,28,9,30))
653
+ end
654
+
655
+ it "should not include the beginnings of matching days" do
656
+ @rs.should_not include(Time.utc(2006,11,5))
657
+ end
658
+ end
659
+
660
+ describe "A daily schedule with times params" do
661
+ end
662
+
663
+ describe "A third-daily schedule with times params" do
664
+ end
665
+
666
+ describe "A daily schedule with monthday params" do
667
+ end
668
+
669
+ #HOURLY
670
+
671
+ describe "An hourly schedule with no other params" do
672
+
673
+ setup do
674
+ @rs = Recurring::Schedule.new :unit => 'hours'
675
+ end
676
+
677
+ it "should include the top of every hour" do
678
+ @rs.should include(Time.utc(2006,3,4,5))
679
+ end
680
+
681
+ it "should not include times with non zero minutes or seconds" do
682
+ @rs.should_not include(Time.utc(2006,3,4,5,6))
683
+ @rs.should_not include(Time.utc(2006,3,4,5,0,6))
684
+ end
685
+
686
+ end
687
+
688
+ describe "An hourly schedule with an anchor" do
689
+ setup do
690
+ @rs = Recurring::Schedule.new :unit => 'hours', :anchor => Time.utc(2001,5,15,11,17)
691
+ end
692
+
693
+ it "should include any time with the same sub hour parts" do
694
+ @rs.should include(Time.utc(2006,5,15,14,17))
695
+ end
696
+
697
+ it "should include the anchor time" do
698
+ end
699
+
700
+ it "should not include any times with different sub hour parts" do
701
+ end
702
+
703
+ it "should find in range" do
704
+ @rs.find_in_range(Time.utc(2006), Time.utc(2007)).length.should == 24*365
705
+ end
706
+
707
+ end
708
+
709
+ describe "An bi-hourly schedule with time params" do
710
+
711
+ setup do
712
+ @rs = Recurring::Schedule.new :unit => 'hours', :frequency => 2, :times => '0:22 0:13:14', :anchor => Time.utc(2006)
713
+ end
714
+
715
+ it "should find 4 times in 4 hours" do
716
+ #should_find_in_range(@rs, 4, Time.utc(2006,12,12), Time.utc(2006,12,12,4) )
717
+ end
718
+
719
+ it "should include times every other hour with the valid minutes and seconds" do
720
+ @rs.should include(Time.utc(2006,1,1,0,22))
721
+ @rs.should include(Time.utc(2006,1,1,0,13,14))
722
+ @rs.should include(Time.utc(2006,1,1,2,22))
723
+ @rs.should include(Time.utc(2006,1,1,16,13,14))
724
+ end
725
+
726
+ it "should not include times with mismatched minutes or hours" do
727
+ @rs.should_not include(Time.utc(2006,12,12))
728
+ @rs.should_not include(Time.utc(2006,1,1,1,22))
729
+ @rs.should_not include(Time.utc(2006,1,1,3,13,14))
730
+ @rs.should_not include(Time.utc(2006,1,1,2,23))
731
+ @rs.should_not include(Time.utc(2006,1,1,16,13,24))
732
+ end
733
+
734
+ end
735
+
736
+ describe "An hourly schedule with times params" do
737
+
738
+ setup do
739
+ @rs = Recurring::Schedule.new :unit => 'hours', :times => '0:15 4:30 0:45:30'
740
+ end
741
+
742
+ it "should include matching times" do
743
+ @rs.should include(Time.utc(2001,11,11,11,15))
744
+ @rs.should include(Time.utc(2001,1,1,1,30))
745
+ @rs.should include(Time.utc(2009,12,14,3,45,30))
746
+ end
747
+
748
+ it "should not include non matching times" do
749
+ @rs.should_not include(Time.utc(2001,11,11,11,15,05))
750
+ @rs.should_not include(Time.utc(2001,1,1,1,30,1))
751
+ @rs.should_not include(Time.utc(2001,1,1,1,35))
752
+ @rs.should_not include(Time.utc(2009,12,14,3,45))
753
+ end
754
+
755
+ it "should find the next date" do
756
+ @rs.find_next(Time.utc(2006,5,4,12)).should == Time.utc(2006,5,4,12,15)
757
+ @rs.find_next(Time.utc(2006,6,13,5,31)).should == Time.utc(2006,6,13,5,45,30)
758
+ end
759
+
760
+ it "should find the previous minute that match" do
761
+ @rs.find_previous(Time.utc(2006,5,5,5,17)).should == Time.utc(2006,5,5,5,15)
762
+ end
763
+
764
+ end
765
+
766
+ describe "An eight-hourly schedule with times params" do
767
+ end
768
+
769
+ describe "An hourly schedule with monthday params" do
770
+
771
+ it "should ignore the monthday params" do
772
+ end
773
+
774
+ end
775
+
776
+ #MINUTELY
777
+
778
+ describe "Every 45 minutes from an anchor" do
779
+ setup do
780
+ @rs = Recurring::Schedule.new :unit => 'minutes', :frequency => 45, :anchor => Time.utc(2006, 12, 1, 10, 30)
781
+ end
782
+ it "should include 45 minute multiples of the anchor time" do
783
+ @rs.should include(Time.utc(2006, 12, 1, 11, 15))
784
+ @rs.should include(Time.utc(2006, 12, 1, 12, 00))
785
+ @rs.should include(Time.utc(2006, 12, 1, 9, 45))
786
+ end
787
+ end
788
+
789
+ describe "A 30 minutely schedule" do
790
+ setup do
791
+ @rs = Recurring::Schedule.new :unit => 'minutes', :frequency => 30, :anchor => Time.utc(2006,1,1,1,15)
792
+ end
793
+ it "should match the very next time after the start" do
794
+ @rs.find_in_range(Time.utc(2006,1,15,2), Time.utc(2006,1,16)).first.should == Time.utc(2006,1,15,2,15)
795
+ end
796
+ end
797
+
798
+ describe "A 5-minutely schedule with no other params" do
799
+
800
+ setup do
801
+ @rs = Recurring::Schedule.new :unit => 'minutes', :frequency => 5, :anchor => Time.utc(2006,9,1,10,30)
802
+ end
803
+
804
+ it "should include a five minute multiples of the anchor time" do
805
+ @rs.should include(Time.utc(2006,9,1,10,30))
806
+ @rs.should include(Time.utc(2006,9,1,10,35))
807
+ @rs.should include(Time.utc(2006,9,1,20,30))
808
+ end
809
+
810
+ it "should not include times with different seconds" do
811
+ @rs.should_not include(Time.utc(2006,9,1,10,30,30))
812
+ end
813
+
814
+ it "should find the next date" do
815
+ @rs.find_next(Time.utc(2006,5,4,12,1)).should == Time.utc(2006,5,4,12,5)
816
+ @rs.find_next(Time.utc(2006,6,13,5,31)).should == Time.utc(2006,6,13,5,35)
817
+ end
818
+
819
+ it "should ignore higher than second precision from the anchor" do
820
+ end
821
+
822
+ it "should find 7 times in a 30 minute range" do
823
+ should_find_in_range(@rs, 7, Time.utc(2006,12,12,0,45), Time.utc(2006,12,12,1,15))
824
+ @rs.find_in_range( Time.utc(2006,12,12,0,45)..Time.utc(2006,12,12,1,15) ).first.class.should == Time
825
+ end
826
+
827
+ it "should find 3 times in a 30 minute range with a limit of 3" do
828
+ results = @rs.find_in_range(Time.utc(2006,12,12,0,45), Time.utc(2006,12,12,1,15), :limit => 3)
829
+ results.length.should == 3
830
+ end
831
+
832
+ it "should find 3 times in a 30 minute range (with range args) with a limit of 3" do
833
+ results = @rs.find_in_range(Time.utc(2006,12,12,0,45)..Time.utc(2006,12,12,1,15), :limit => 3)
834
+ results.length.should == 3
835
+ end
836
+
837
+ it "should find in a range given as an object with first and last params" do
838
+ range = mock('range')
839
+ range.should_receive(:first).and_return(Time.utc(2006,12,12,0,45))
840
+ range.should_receive(:last).any_number_of_times.and_return(Time.utc(2006,12,12,1,15))
841
+ @rs.find_in_range(range).first.class.should == Time
842
+ end
843
+
844
+ it "should find in a range given as a Range" do
845
+ range = (Time.utc(2006,12,12,0,45)..Time.utc(2006,12,12,1,15))
846
+ @rs.find_in_range(range).first.class.should == Time
847
+ end
848
+
849
+ it "should find 10 times in a 45 minute range" do
850
+ should_find_in_range(@rs, 10, Time.utc(2006,12,12,1), Time.utc(2006,12,12,1,45))
851
+ @rs.find_in_range( Time.utc(2006,12,12,0,45), Time.utc(2006,12,12,1,15) ).first.class.should == Time
852
+ end
853
+ end
854
+
855
+ #SECONDLY
856
+
857
+
858
+ #ETC
859
+
860
+ describe "a daily schedule with a time 4:29am" do
861
+ setup do
862
+ @rs = Recurring::Schedule.new :unit => 'days', :times => '4:29am'
863
+ end
864
+ it "should include any day at the time specified" do
865
+ @rs.should include(Time.utc(2001,3,4,4,29))
866
+ end
867
+ it "should not include times other than 4:29am" do
868
+ @rs.should_not include(Time.utc(2004,5,17,1,39))
869
+ end
870
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ggoodale-recurring
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.3
5
+ platform: ruby
6
+ authors:
7
+ - Chris Anderson
8
+ - Grant Goodale
9
+ autorequire: recurring
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2006-12-11 00:00:00 -08:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 0.7.4
25
+ version:
26
+ description: Recurring allows you to define Schedules, which can tell you whether or not a given Time falls in the Schedule, as well as being able to return a list of times which match the Schedule within a given range.
27
+ email: jchris@mfdz.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - lib/recurring.rb
40
+ - spec/date_language_spec.rb
41
+ - spec/schedule_spec.rb
42
+ has_rdoc: false
43
+ homepage: http://jchris.mfdz.com
44
+ licenses:
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.5
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: A scheduling library for recurring events
69
+ test_files: []
70
+