recurring 0.3.2 → 0.3.10
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Rakefile +12 -13
- data/lib/recurring.rb +48 -14
- data/spec/recurring_spec.rb +79 -2
- metadata +2 -2
data/History.txt
CHANGED
data/Rakefile
CHANGED
@@ -25,7 +25,6 @@ Hoe.new('recurring', Recurring::VERSION) do |p|
|
|
25
25
|
p.description =<<-DESC
|
26
26
|
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
27
|
DESC
|
28
|
-
puts p.changes
|
29
28
|
end
|
30
29
|
|
31
30
|
# specification = Gem::Specification.new do |s|
|
@@ -52,17 +51,17 @@ end
|
|
52
51
|
# pkg.need_tar = true
|
53
52
|
# end
|
54
53
|
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
|
54
|
+
Rake::RDocTask.new(:docs) do |rd|
|
55
|
+
rd.main = "README.txt"
|
56
|
+
rd.options << '-d' if RUBY_PLATFORM !~ /win32/ and `which dot` =~ /\/dot/
|
57
|
+
rd.rdoc_dir = 'doc'
|
58
|
+
files = ["History.txt", "README.txt", "Rakefile", "lib/recurring.rb", "spec/recurring_spec.rb"]
|
59
|
+
rd.rdoc_files.push(*files)
|
60
|
+
|
61
|
+
title = "Recurring-#{VERSION} Documentation"
|
62
|
+
#title = "#{rubyforge_name}'s " + title if rubyforge_name != title
|
63
|
+
|
64
|
+
rd.options << "-t #{title}"
|
65
|
+
end
|
67
66
|
|
68
67
|
|
data/lib/recurring.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Recurring
|
2
|
-
VERSION = '0.3.
|
3
|
-
|
2
|
+
VERSION = '0.3.10'
|
4
3
|
class << self
|
4
|
+
|
5
5
|
# returns a number starting with 1
|
6
6
|
def week_in_month date
|
7
7
|
(((date.day - 1).to_f / 7.0) + 1).floor
|
@@ -45,8 +45,8 @@ module Recurring
|
|
45
45
|
|
46
46
|
attr_reader :unit, :frequency, :anchor, :months, :weeks, :monthdays, :weekdays, :times
|
47
47
|
|
48
|
-
#
|
49
|
-
# * valid
|
48
|
+
# Options hash has keys <tt>:unit, :frequency, :anchor, :weeks, :monthdays, :weekdays, :times</tt>
|
49
|
+
# * valid values for :unit are <tt>years, months, weeks, days, hours, minutes</tt>
|
50
50
|
# * :frequency defaults to 1
|
51
51
|
# * :anchor is required if the frequency is other than one
|
52
52
|
# * :weeks alongside :weekdays is used to specify the nth instance of a weekday in a month.
|
@@ -64,11 +64,19 @@ module Recurring
|
|
64
64
|
@frequency = options[:frequency] || 1
|
65
65
|
@anchor = options[:anchor]
|
66
66
|
@times = parse_times options[:times]
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
if options[:months]
|
68
|
+
@months = Array(options[:months]).collect{|d|d.to_s.downcase.to_sym}
|
69
|
+
raise ArgumentError, 'provide valid months' unless @months.all?{|m|ordinal_month(m)}
|
70
|
+
end
|
71
|
+
|
72
|
+
@weeks = Array(options[:weeks]).collect{|n|n.to_i} if options[:weeks]
|
73
|
+
if options[:weekdays]
|
74
|
+
@weekdays = Array(options[:weekdays]).collect{|d|d.to_s.downcase.to_sym}
|
75
|
+
raise ArgumentError, 'provide valid weekdays' unless @weekdays.all?{|w|ordinal_weekday(w)}
|
76
|
+
end
|
77
|
+
@monthdays = Array(options[:monthdays]).collect{|n|n.to_i} if options[:monthdays]
|
71
78
|
|
79
|
+
|
72
80
|
@anchor_multiple = options[:times].nil? && options[:weeks].nil? && options[:weekdays].nil? && options[:monthdays].nil?
|
73
81
|
end
|
74
82
|
|
@@ -100,6 +108,7 @@ module Recurring
|
|
100
108
|
def find_next date
|
101
109
|
loop do
|
102
110
|
return date if include?(date)
|
111
|
+
#puts "#{@resolution} : #{date}"
|
103
112
|
date = beginning_of_next @resolution, date
|
104
113
|
end
|
105
114
|
end
|
@@ -108,6 +117,7 @@ module Recurring
|
|
108
117
|
def find_previous date
|
109
118
|
loop do
|
110
119
|
return date if include?(date)
|
120
|
+
#puts "#{@resolution} : #{date}"
|
111
121
|
date = end_of_previous @resolution, date
|
112
122
|
end
|
113
123
|
end
|
@@ -153,7 +163,7 @@ module Recurring
|
|
153
163
|
when :week
|
154
164
|
to_sunday = date.wday
|
155
165
|
previous_week = (date - to_sunday*24*60*60)
|
156
|
-
Time.utc(previous_week.year, previous_week.month, previous_week.day)
|
166
|
+
Time.utc(previous_week.year, previous_week.month, previous_week.day) - 1
|
157
167
|
when :day
|
158
168
|
Time.utc(date.year, date.month, date.day) - 1
|
159
169
|
when :time
|
@@ -179,6 +189,10 @@ module Recurring
|
|
179
189
|
Time.utc(dayp.year, dayp.month, dayp.day)
|
180
190
|
when :time
|
181
191
|
next_time date
|
192
|
+
when :hour
|
193
|
+
date.hour < 23 ? Time.utc(date.year, date.month, date.day, date.hour+1) : beginning_of_next(:day, date)
|
194
|
+
when :sub_hour
|
195
|
+
next_sub_hour date
|
182
196
|
else
|
183
197
|
date + 1
|
184
198
|
end
|
@@ -221,6 +235,23 @@ module Recurring
|
|
221
235
|
end
|
222
236
|
end
|
223
237
|
|
238
|
+
def next_sub_hour date
|
239
|
+
me = {:minute => date.min, :second => date.sec, :me => true}
|
240
|
+
my_times = times + [me]
|
241
|
+
my_times += [{:minute => @anchor.min, :second => @anchor.sec}] if check_anchor?
|
242
|
+
my_times.sort! do |a,b|
|
243
|
+
v = a[:minute] <=> b[:minute]
|
244
|
+
v = a[:second] <=> b[:second] if v == 0
|
245
|
+
v
|
246
|
+
end
|
247
|
+
ntime = my_times[my_times.index(me)+1]
|
248
|
+
if ntime
|
249
|
+
Time.utc(date.year, date.month, date.day, date.hour, ntime[:minute], ntime[:second])
|
250
|
+
else
|
251
|
+
beginning_of_next :hour, date
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
224
255
|
def mismatch unit
|
225
256
|
@resolution = unit
|
226
257
|
false
|
@@ -246,9 +277,9 @@ module Recurring
|
|
246
277
|
end
|
247
278
|
|
248
279
|
def week_matches? date
|
249
|
-
|
280
|
+
if @unit == :weeks
|
250
281
|
return true if @frequency == 1
|
251
|
-
return (Recurring.week_of_year(date) - Recurring.week_of_year(@anchor)) % @frequency == 0
|
282
|
+
return ((Recurring.week_of_year(date) - Recurring.week_of_year(@anchor)) % @frequency) == 0
|
252
283
|
end
|
253
284
|
if @weeks
|
254
285
|
@weeks.include?(Recurring.week_in_month(date))
|
@@ -325,7 +356,8 @@ module Recurring
|
|
325
356
|
4 => [:thursday, :thurs],
|
326
357
|
5 => [:friday, :fri],
|
327
358
|
6 => [:saturday, :sat]}
|
328
|
-
lookup.select{|k,v| v.include?(symbol)}.first
|
359
|
+
pair = lookup.select{|k,v| v.include?(symbol)}.first
|
360
|
+
pair.first if pair
|
329
361
|
end
|
330
362
|
|
331
363
|
def ordinal_month symbol
|
@@ -341,7 +373,8 @@ module Recurring
|
|
341
373
|
10 => [:october, :oct],
|
342
374
|
11 => [:november, :nov],
|
343
375
|
12 => [:december, :dec]}
|
344
|
-
|
376
|
+
pair = lookup.select{|k,v| v.include?(symbol)}.first
|
377
|
+
pair.first if pair
|
345
378
|
end
|
346
379
|
|
347
380
|
def parse_times string
|
@@ -356,7 +389,8 @@ module Recurring
|
|
356
389
|
time[:hour], time[:minute], time[:second] = st.split(':').collect {|n| n.to_i}
|
357
390
|
time[:minute] ||= 0
|
358
391
|
time[:second] ||= 0
|
359
|
-
time[:hour] = time[:hour] + 12 if am_pm == 'pm'
|
392
|
+
time[:hour] = time[:hour] + 12 if am_pm == 'pm' && time[:hour] < 12
|
393
|
+
time[:hour] = 0 if am_pm == 'am' && time[:hour] == 12
|
360
394
|
time
|
361
395
|
end
|
362
396
|
#this is an implementation of Array#uniq required because Hash#eql? is not a synonym for Hash#==
|
data/spec/recurring_spec.rb
CHANGED
@@ -34,6 +34,18 @@ context "Initializing a Schedule" do
|
|
34
34
|
rs.times.should == [{:hour => 16, :minute => 30, :second => 0}, {:hour => 17, :minute => 0, :second => 0}, {:hour => 3, :minute => 30, :second => 30}]
|
35
35
|
end
|
36
36
|
|
37
|
+
specify "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
|
+
specify "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
|
+
|
37
49
|
specify "should be graceful about a duplicate times string" do
|
38
50
|
rs = Recurring::Schedule.new :unit => 'days', :times => '4:30 4:30'
|
39
51
|
rs.times.should == [{:hour => 4, :minute => 30, :second => 0}]
|
@@ -64,12 +76,25 @@ context "Initializing a Schedule" do
|
|
64
76
|
rs.weekdays.should == [:monday, :wednesday]
|
65
77
|
end
|
66
78
|
|
79
|
+
specify "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 ArgumentError
|
81
|
+
end
|
82
|
+
|
83
|
+
specify "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 ArgumentError
|
85
|
+
end
|
86
|
+
|
67
87
|
specify "should accept months params" do
|
68
88
|
rs = Recurring::Schedule.new :unit => 'years', :months => 'feb', :monthdays => [4]
|
69
89
|
rs.months.should == [:feb]
|
70
90
|
end
|
71
91
|
|
72
|
-
specify "should accept
|
92
|
+
specify "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
|
+
specify "should accept monthdays as integers" do
|
73
98
|
rs = Recurring::Schedule.new :unit => 'months', :monthdays => [1,15]
|
74
99
|
rs.monthdays.should == [1,15]
|
75
100
|
end
|
@@ -320,6 +345,49 @@ end
|
|
320
345
|
|
321
346
|
#WEEKLY
|
322
347
|
|
348
|
+
context "A bi-weekly schedule with weekdays and a midnight time" do
|
349
|
+
setup do
|
350
|
+
@rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => %w{sat sunday}, :times => '12am', :frequency => 2, :anchor => Time.utc(2001)
|
351
|
+
@danger = Time.utc(2006,12,17,18)
|
352
|
+
end
|
353
|
+
|
354
|
+
specify "should include midnights of every other weekend" do
|
355
|
+
@rs.should_include Time.utc(2006,12,16)
|
356
|
+
@rs.should_include Time.utc(2006,12,10)
|
357
|
+
end
|
358
|
+
|
359
|
+
specify "should not include other midnights" do
|
360
|
+
@rs.should_not_include Time.utc(2006,12,22)
|
361
|
+
@rs.should_not_include Time.utc(2006,12,25)
|
362
|
+
end
|
363
|
+
|
364
|
+
specify "should find the previous time from a dangerous time" do
|
365
|
+
@rs.find_previous(@danger).should == Time.utc(2006,12,16)
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
context "A bi-weekly schedule with weekdays and a noon time" do
|
371
|
+
setup do
|
372
|
+
@rs = Recurring::Schedule.new :unit => 'weeks', :weekdays => %w{sat sunday}, :times => '12pm', :frequency => 2, :anchor => Time.utc(2001)
|
373
|
+
@danger = Time.utc(2006,12,17,18)
|
374
|
+
end
|
375
|
+
|
376
|
+
specify "should include noons of every other weekend" do
|
377
|
+
@rs.should_include Time.utc(2006,12,10,12)
|
378
|
+
@rs.should_include Time.utc(2006,12,16,12)
|
379
|
+
end
|
380
|
+
|
381
|
+
specify "should not include other midnights" do
|
382
|
+
@rs.should_not_include Time.utc(2006,12,22,12)
|
383
|
+
@rs.should_not_include Time.utc(2006,12,25,12)
|
384
|
+
end
|
385
|
+
|
386
|
+
specify "should find the previous time from a dangerous time" do
|
387
|
+
@rs.find_previous(@danger).should == Time.utc(2006,12,16,12)
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
323
391
|
context "A weekly schedule with weekday params" do
|
324
392
|
|
325
393
|
setup do
|
@@ -406,6 +474,11 @@ context "A third-weekly schedule with weekday and times params" do
|
|
406
474
|
@rs.find_next(Time.utc(2006,12,4)).should == Time.utc(2006,12,18,15)
|
407
475
|
@rs.find_next(Time.utc(2006,12,18)).should == Time.utc(2006,12,18,15)
|
408
476
|
end
|
477
|
+
|
478
|
+
specify "should find the previous date" do
|
479
|
+
@rs.find_previous(Time.utc(2006,12,4)).should == Time.utc(2006,12,2,15)
|
480
|
+
@rs.find_previous(Time.utc(2006,12,18,20)).should == Time.utc(2006,12,18,15)
|
481
|
+
end
|
409
482
|
|
410
483
|
end
|
411
484
|
|
@@ -574,7 +647,11 @@ context "An hourly schedule with an anchor" do
|
|
574
647
|
|
575
648
|
specify "should not include any times with different sub hour parts" do
|
576
649
|
end
|
577
|
-
|
650
|
+
|
651
|
+
specify "should find in range" do
|
652
|
+
@rs.find_in_range(Time.utc(2006), Time.utc(2007)).length.should == 24*365
|
653
|
+
end
|
654
|
+
|
578
655
|
end
|
579
656
|
|
580
657
|
context "An bi-hourly schedule with time params" do
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: recurring
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.3.
|
7
|
-
date: 2006-12-
|
6
|
+
version: 0.3.10
|
7
|
+
date: 2006-12-18 00:00:00 -08:00
|
8
8
|
summary: A scheduling library for recurring events
|
9
9
|
require_paths:
|
10
10
|
- lib
|