recurrence 0.1.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/Gemfile +1 -4
- data/Gemfile.lock +33 -17
- data/History.txt +8 -1
- data/README.rdoc +124 -0
- data/Rakefile +6 -0
- data/lib/recurrence.rb +18 -0
- data/lib/recurrence/event.rb +1 -1
- data/lib/recurrence/event/base.rb +3 -3
- data/lib/recurrence/event/daily.rb +1 -1
- data/lib/recurrence/event/monthly.rb +8 -8
- data/lib/recurrence/event/weekly.rb +1 -1
- data/lib/recurrence/event/yearly.rb +3 -3
- data/lib/recurrence/namespace.rb +160 -32
- data/lib/recurrence/version.rb +3 -3
- data/recurrence.gemspec +2 -1
- data/spec/recurrence_spec.rb +179 -39
- data/spec/spec_helper.rb +1 -1
- metadata +19 -7
- data/README.markdown +0 -138
- data/init.rb +0 -2
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,26 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
recurrence (0.1.5)
|
5
|
+
activesupport (>= 3.0.0)
|
6
|
+
|
1
7
|
GEM
|
2
8
|
remote: http://rubygems.org/
|
3
9
|
specs:
|
4
|
-
activesupport (3.0.
|
10
|
+
activesupport (3.0.2)
|
11
|
+
archive-tar-minitar (0.5.2)
|
12
|
+
columnize (0.3.2)
|
5
13
|
diff-lcs (1.1.2)
|
6
|
-
|
7
|
-
|
8
|
-
rspec (2.
|
9
|
-
rspec-core (
|
10
|
-
rspec-expectations (
|
11
|
-
rspec-mocks (
|
12
|
-
rspec-core (2.
|
13
|
-
rspec-expectations (2.
|
14
|
-
diff-lcs (
|
15
|
-
rspec-mocks (2.
|
16
|
-
|
17
|
-
|
14
|
+
linecache19 (0.5.11)
|
15
|
+
ruby_core_source (>= 0.1.4)
|
16
|
+
rspec (2.1.0)
|
17
|
+
rspec-core (~> 2.1.0)
|
18
|
+
rspec-expectations (~> 2.1.0)
|
19
|
+
rspec-mocks (~> 2.1.0)
|
20
|
+
rspec-core (2.1.0)
|
21
|
+
rspec-expectations (2.1.0)
|
22
|
+
diff-lcs (~> 1.1.2)
|
23
|
+
rspec-mocks (2.1.0)
|
24
|
+
ruby-debug-base19 (0.11.24)
|
25
|
+
columnize (>= 0.3.1)
|
26
|
+
linecache19 (>= 0.5.11)
|
27
|
+
ruby_core_source (>= 0.1.4)
|
28
|
+
ruby-debug19 (0.11.6)
|
29
|
+
columnize (>= 0.3.1)
|
30
|
+
linecache19 (>= 0.5.11)
|
31
|
+
ruby-debug-base19 (>= 0.11.19)
|
32
|
+
ruby_core_source (0.1.4)
|
33
|
+
archive-tar-minitar (>= 0.5.2)
|
18
34
|
|
19
35
|
PLATFORMS
|
20
36
|
ruby
|
21
37
|
|
22
38
|
DEPENDENCIES
|
23
|
-
activesupport
|
24
|
-
|
25
|
-
|
26
|
-
|
39
|
+
activesupport (>= 3.0.0)
|
40
|
+
recurrence!
|
41
|
+
rspec (>= 2.0.0)
|
42
|
+
ruby-debug19
|
data/History.txt
CHANGED
@@ -64,4 +64,11 @@
|
|
64
64
|
== 0.1.5 2010-11-03
|
65
65
|
|
66
66
|
* Recurrence.default_starts_date is now configurable; pass in a String or block
|
67
|
-
* Add #options reader so we'll be able to use Recurrence with ActiveRecord.composed_of
|
67
|
+
* Add Recurrence#options reader so we'll be able to use Recurrence with ActiveRecord.composed_of
|
68
|
+
|
69
|
+
== 1.0.0 2010-11-16
|
70
|
+
|
71
|
+
* Recurrence#each returns an enumerator when no block is given
|
72
|
+
* Recurrence now includes Enumerable
|
73
|
+
* The public API is now documented
|
74
|
+
* Remove support for Rails plugin
|
data/README.rdoc
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
= Recurrence
|
2
|
+
|
3
|
+
A simple library to handle recurring events.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install recurrence
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
require "recurrence"
|
13
|
+
|
14
|
+
# Daily
|
15
|
+
r = Recurrence.new(:every => :day)
|
16
|
+
r = Recurrence.new(:every => :day, :interval => 9)
|
17
|
+
r = Recurrence.daily(options = {})
|
18
|
+
|
19
|
+
# Weekly
|
20
|
+
r = Recurrence.new(:every => :week, :on => 5)
|
21
|
+
r = Recurrence.new(:every => :week, :on => :monday)
|
22
|
+
r = Recurrence.new(:every => :week, :on => [:monday, :friday])
|
23
|
+
r = Recurrence.new(:every => :week, :on => [:monday, :wednesday, :friday])
|
24
|
+
r = Recurrence.new(:every => :week, :on => :friday, :interval => 2)
|
25
|
+
r = Recurrence.weekly(:on => :thursday)
|
26
|
+
|
27
|
+
# Monthly by month day
|
28
|
+
r = Recurrence.new(:every => :month, :on => 15)
|
29
|
+
r = Recurrence.new(:every => :month, :on => 31)
|
30
|
+
r = Recurrence.new(:every => :month, :on => 7, :interval => 2)
|
31
|
+
r = Recurrence.new(:every => :month, :on => 7, :interval => :monthly)
|
32
|
+
r = Recurrence.new(:every => :month, :on => 7, :interval => :bimonthly)
|
33
|
+
r = Recurrence.monthly(:on => 31)
|
34
|
+
|
35
|
+
# Monthly by week day
|
36
|
+
r = Recurrence.new(:every => :month, :on => :first, :weekday => :sunday)
|
37
|
+
r = Recurrence.new(:every => :month, :on => :third, :weekday => :monday)
|
38
|
+
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday)
|
39
|
+
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday, :interval => 2)
|
40
|
+
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday, :interval => :quarterly)
|
41
|
+
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday, :interval => :semesterly)
|
42
|
+
|
43
|
+
# Yearly
|
44
|
+
r = Recurrence.new(:every => :year, :on => [7, 4]) # => [month, day]
|
45
|
+
r = Recurrence.new(:every => :year, :on => [10, 31], :interval => 3)
|
46
|
+
r = Recurrence.new(:every => :year, :on => [:jan, 31])
|
47
|
+
r = Recurrence.new(:every => :year, :on => [:january, 31])
|
48
|
+
r = Recurrence.yearly(:on => [:january, 31])
|
49
|
+
|
50
|
+
# Limit recurrence
|
51
|
+
# :starts defaults to Date.today
|
52
|
+
# :until defaults to 2037-12-31
|
53
|
+
r = Recurrence.new(:every => :day, :starts => Date.today)
|
54
|
+
r = Recurrence.new(:every => :day, :until => '2010-01-31')
|
55
|
+
r = Recurrence.new(:every => :day, :starts => Date.today, :until => '2010-01-31')
|
56
|
+
|
57
|
+
# Getting an array with all events
|
58
|
+
r.events.each {|date| puts date.to_s } # => Memoized array
|
59
|
+
r.events!.each {|date| puts date.to_s } # => reset items cache and re-execute it
|
60
|
+
r.events(:starts => '2009-01-01').each {|date| puts date.to_s }
|
61
|
+
r.events(:until => '2009-01-10').each {|date| puts date.to_s }
|
62
|
+
r.events(:starts => '2009-01-05', :until => '2009-01-10').each {|date| puts date.to_s }
|
63
|
+
|
64
|
+
# Iterating events
|
65
|
+
r.each { |date| puts date.to_s } # => Use items method
|
66
|
+
r.each! { |date| puts date.to_s } # => Use items! method
|
67
|
+
|
68
|
+
# Check if a date is included
|
69
|
+
r.include?(Date.today) # => true or false
|
70
|
+
r.include?('2008-09-21')
|
71
|
+
|
72
|
+
# Get next available date
|
73
|
+
r.next # => Keep the original date object
|
74
|
+
r.next! # => Change the internal date object to the next available date
|
75
|
+
|
76
|
+
== Troubleshooting
|
77
|
+
|
78
|
+
If you're having problems because already have a class/module called Recurrence that is conflicting with this gem, you can require the namespace and create a class that inherits from <tt>SimplesIdeias::Recurrence</tt>.
|
79
|
+
|
80
|
+
require "recurrence/namespace"
|
81
|
+
|
82
|
+
class RecurrentEvent < SimplesIdeias::Recurrence
|
83
|
+
end
|
84
|
+
|
85
|
+
r = RecurrentEvent.new(:every => :day)
|
86
|
+
|
87
|
+
If you're using Rails/Bundler or something like that, remember to override the <tt>:require</tt> option.
|
88
|
+
|
89
|
+
# Gemfile
|
90
|
+
source :rubygems
|
91
|
+
|
92
|
+
gem "recurrence", :require => "recurrence/namespace"
|
93
|
+
|
94
|
+
== Maintainer
|
95
|
+
|
96
|
+
* Nando Vieira (http://nandovieira.com.br)
|
97
|
+
|
98
|
+
== Contributors
|
99
|
+
|
100
|
+
* José Valim (http://plataformatec.com.br)
|
101
|
+
* Maxim Chernyak (http://mediumexposure.com)
|
102
|
+
|
103
|
+
== License
|
104
|
+
|
105
|
+
(The MIT License)
|
106
|
+
|
107
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
108
|
+
a copy of this software and associated documentation files (the
|
109
|
+
'Software'), to deal in the Software without restriction, including
|
110
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
111
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
112
|
+
permit persons to whom the Software is furnished to do so, subject to
|
113
|
+
the following conditions:
|
114
|
+
|
115
|
+
The above copyright notice and this permission notice shall be
|
116
|
+
included in all copies or substantial portions of the Software.
|
117
|
+
|
118
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
119
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
120
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
121
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
122
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
123
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
124
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -3,3 +3,9 @@ Bundler::GemHelper.install_tasks
|
|
3
3
|
|
4
4
|
require "rspec/core/rake_task"
|
5
5
|
RSpec::Core::RakeTask.new
|
6
|
+
|
7
|
+
require "rake/rdoctask"
|
8
|
+
Rake::RDocTask.new do |rd|
|
9
|
+
rd.main = "README.rdoc"
|
10
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb", "History.txt", "License.txt")
|
11
|
+
end
|
data/lib/recurrence.rb
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
require "recurrence/namespace"
|
2
2
|
|
3
|
+
# The default namespace. If you already have Recurrence constant set on your codebase,
|
4
|
+
# you can inherit from SimplesIdeias::Recurrence and have your own namespace.
|
5
|
+
#
|
6
|
+
# require "recurrence/namespace"
|
7
|
+
#
|
8
|
+
# class RecurrentEvent < SimplesIdeias::Recurrence
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# r = RecurrentEvent.new(:every => :day)
|
12
|
+
#
|
13
|
+
# Remember require <tt>recurrence/namespace</tt> instead of just <tt>recurrence</tt>.
|
14
|
+
# If you’re using Rails/Bundler or something like that, remember to override the
|
15
|
+
# <tt>:require</tt> option.
|
16
|
+
#
|
17
|
+
# # Gemfile
|
18
|
+
# source :rubygems
|
19
|
+
# gem "recurrence", :require => "recurrence/namespace"
|
20
|
+
#
|
3
21
|
class Recurrence < SimplesIdeias::Recurrence
|
4
22
|
end
|
data/lib/recurrence/event.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module SimplesIdeias
|
2
2
|
class Recurrence
|
3
|
-
module Event
|
3
|
+
module Event # :nodoc: all
|
4
4
|
class Base
|
5
5
|
CARDINALS = %w(first second third fourth fifth)
|
6
6
|
DAYS = %w(sunday monday tuesday wednesday thursday friday saturday)
|
@@ -8,7 +8,7 @@ module SimplesIdeias
|
|
8
8
|
attr_accessor :start_date
|
9
9
|
|
10
10
|
def initialize(options={})
|
11
|
-
every, options = nil, every if every.
|
11
|
+
every, options = nil, every if every.kind_of?(Hash)
|
12
12
|
|
13
13
|
@options = options
|
14
14
|
@date = options[:starts]
|
@@ -59,7 +59,7 @@ module SimplesIdeias
|
|
59
59
|
|
60
60
|
# Common validation for inherited classes.
|
61
61
|
#
|
62
|
-
def valid_month_day?(day)
|
62
|
+
def valid_month_day?(day)
|
63
63
|
raise ArgumentError, "invalid day #{day}" unless (1..31).include?(day)
|
64
64
|
end
|
65
65
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module SimplesIdeias
|
2
2
|
class Recurrence
|
3
3
|
module Event
|
4
|
-
class Monthly < Base
|
4
|
+
class Monthly < Base # :nodoc: all
|
5
5
|
INTERVALS = {
|
6
|
-
:monthly
|
7
|
-
:bimonthly
|
8
|
-
:quarterly
|
6
|
+
:monthly => 1,
|
7
|
+
:bimonthly => 2,
|
8
|
+
:quarterly => 3,
|
9
9
|
:semesterly => 6
|
10
10
|
}
|
11
11
|
|
@@ -28,7 +28,7 @@ module SimplesIdeias
|
|
28
28
|
valid_month_day?(@options[:on])
|
29
29
|
end
|
30
30
|
|
31
|
-
if @options[:interval].
|
31
|
+
if @options[:interval].kind_of?(Symbol)
|
32
32
|
valid_interval?(@options[:interval])
|
33
33
|
@options[:interval] = INTERVALS[@options[:interval]]
|
34
34
|
end
|
@@ -88,15 +88,15 @@ module SimplesIdeias
|
|
88
88
|
end
|
89
89
|
|
90
90
|
private
|
91
|
-
def valid_cardinal?(cardinal)
|
91
|
+
def valid_cardinal?(cardinal)
|
92
92
|
raise ArgumentError, "invalid cardinal #{cardinal}" unless CARDINALS.include?(cardinal.to_s)
|
93
93
|
end
|
94
94
|
|
95
|
-
def valid_interval?(interval)
|
95
|
+
def valid_interval?(interval)
|
96
96
|
raise ArgumentError, "invalid cardinal #{interval}" unless INTERVALS.key?(interval)
|
97
97
|
end
|
98
98
|
|
99
|
-
def valid_week?(week)
|
99
|
+
def valid_week?(week)
|
100
100
|
raise ArgumentError, "invalid week #{week}" unless (1..5).include?(week)
|
101
101
|
end
|
102
102
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module SimplesIdeias
|
2
2
|
class Recurrence
|
3
3
|
module Event
|
4
|
-
class Yearly < Base
|
4
|
+
class Yearly < Base # :nodoc: all
|
5
5
|
MONTHS = {
|
6
6
|
"jan" => 1, "january" => 1,
|
7
7
|
"feb" => 2, "february" => 2,
|
@@ -48,11 +48,11 @@ module SimplesIdeias
|
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
|
-
def valid_month?(month)
|
51
|
+
def valid_month?(month)
|
52
52
|
raise ArgumentError, "invalid month #{month}" unless (1..12).include?(month)
|
53
53
|
end
|
54
54
|
|
55
|
-
def valid_month_name?(month)
|
55
|
+
def valid_month_name?(month)
|
56
56
|
raise ArgumentError, "invalid month #{month}" unless MONTHS.keys.include?(month.to_s)
|
57
57
|
end
|
58
58
|
end
|
data/lib/recurrence/namespace.rb
CHANGED
@@ -1,94 +1,167 @@
|
|
1
1
|
require "date"
|
2
2
|
require "active_support/all"
|
3
|
+
require "enumerator"
|
3
4
|
|
4
5
|
module SimplesIdeias
|
5
6
|
class Recurrence
|
6
|
-
autoload :Event,
|
7
|
-
autoload :Version,
|
7
|
+
autoload :Event, "recurrence/event"
|
8
|
+
autoload :Version, "recurrence/version"
|
8
9
|
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
# This is the available frequency options accepted by
|
13
|
+
# <tt>:every</tt> option.
|
9
14
|
FREQUENCY = %w(day week month year)
|
10
15
|
|
11
16
|
attr_reader :event, :options
|
12
17
|
|
18
|
+
# Return the default starting date.
|
19
|
+
#
|
20
|
+
# Recurrence.default_starts_date
|
21
|
+
# #=> <Date>
|
22
|
+
#
|
13
23
|
def self.default_starts_date
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
24
|
+
case @default_starts_date
|
25
|
+
when String
|
26
|
+
eval(@default_starts_date)
|
27
|
+
when Proc
|
28
|
+
@default_starts_date.call
|
20
29
|
else
|
21
30
|
Date.today
|
22
31
|
end
|
23
32
|
end
|
24
33
|
|
34
|
+
# Set the default starting date globally.
|
35
|
+
# Can be a proc or a string.
|
36
|
+
#
|
37
|
+
# Recurrence.default_starts_date = proc { Date.today }
|
38
|
+
# Recurrence.default_starts_date = "Date.today"
|
39
|
+
#
|
25
40
|
def self.default_starts_date=(date)
|
26
|
-
unless date.respond_to?(:call) || date.
|
41
|
+
unless date.respond_to?(:call) || date.kind_of?(String) || date == nil
|
27
42
|
raise ArgumentError, 'default_starts_date must be a proc or an evaluatable string such as "Date.current"'
|
28
43
|
end
|
29
44
|
|
30
45
|
@default_starts_date = date
|
31
46
|
end
|
32
47
|
|
48
|
+
# Return the default ending date. Defaults to 2037-12-31.
|
49
|
+
#
|
50
|
+
# Recurrence.default_until_date
|
51
|
+
#
|
33
52
|
def self.default_until_date
|
34
53
|
@default_until_date ||= Date.new(2037, 12, 31)
|
35
54
|
end
|
36
55
|
|
56
|
+
# Set the default ending date globally.
|
57
|
+
# Can be a date or a string recognized by Date#parse.
|
58
|
+
#
|
59
|
+
# Recurrence.default_until_date = "2012-12-31"
|
60
|
+
# Recurrence.default_until_date = Date.tomorrow
|
61
|
+
#
|
37
62
|
def self.default_until_date=(date)
|
38
|
-
@default_until_date =
|
39
|
-
Date.parse(date)
|
40
|
-
else
|
41
|
-
date
|
42
|
-
end
|
63
|
+
@default_until_date = as_date(date)
|
43
64
|
end
|
44
65
|
|
66
|
+
# Create a daily recurrence.
|
67
|
+
#
|
68
|
+
# Recurrence.daily
|
69
|
+
# Recurrence.daily(:interval => 2) #=> every 2 days
|
70
|
+
# Recurrence.daily(:starts => 3.days.from_now)
|
71
|
+
# Recurrence.daily(:until => 10.days.from_now)
|
72
|
+
#
|
45
73
|
def self.daily(options = {})
|
46
74
|
options[:every] = :day
|
47
75
|
new(options)
|
48
76
|
end
|
49
77
|
|
78
|
+
# Create a weekly recurrence.
|
79
|
+
#
|
80
|
+
# Recurrence.weekly(:on => 5) #=> 0 = sunday, 1 = monday, ...
|
81
|
+
# Recurrence.weekly(:on => :saturday)
|
82
|
+
# Recurrence.weekly(:on => [sunday, :saturday])
|
83
|
+
# Recurrence.weekly(:on => :saturday, :interval => 2)
|
84
|
+
#
|
50
85
|
def self.weekly(options = {})
|
51
86
|
options[:every] = :week
|
52
87
|
new(options)
|
53
88
|
end
|
54
89
|
|
90
|
+
# Create a monthly recurrence.
|
91
|
+
#
|
92
|
+
# Recurrence.monthly(:on => 15) #=> every 15th day
|
93
|
+
# Recurrence.monthly(:on => :first, :weekday => :sunday)
|
94
|
+
# Recurrence.monthly(:on => :second, :weekday => :sunday)
|
95
|
+
# Recurrence.monthly(:on => :third, :weekday => :sunday)
|
96
|
+
# Recurrence.monthly(:on => :fourth, :weekday => :sunday)
|
97
|
+
# Recurrence.monthly(:on => :fifth, :weekday => :sunday)
|
98
|
+
# Recurrence.monthly(:on => :last, :weekday => :sunday)
|
99
|
+
# Recurrence.monthly(:on => 15, :interval => 2)
|
100
|
+
# Recurrence.monthly(:on => 15, :interval => :monthly)
|
101
|
+
# Recurrence.monthly(:on => 15, :interval => :bimonthly)
|
102
|
+
# Recurrence.monthly(:on => 15, :interval => :quarterly)
|
103
|
+
# Recurrence.monthly(:on => 15, :interval => :semesterly)
|
104
|
+
#
|
55
105
|
def self.monthly(options = {})
|
56
106
|
options[:every] = :month
|
57
107
|
new(options)
|
58
108
|
end
|
59
109
|
|
110
|
+
# Create a yearly recurrence.
|
111
|
+
#
|
112
|
+
# Recurrence.yearly(:on => [7, 14]) #=> every Jul 14
|
113
|
+
# Recurrence.yearly(:on => [7, 14], :interval => 2) #=> every 2 years on Jul 14
|
114
|
+
# Recurrence.yearly(:on => [:jan, 14], :interval => 2)
|
115
|
+
# Recurrence.yearly(:on => [:january, 14], :interval => 2)
|
116
|
+
#
|
60
117
|
def self.yearly(options = {})
|
61
118
|
options[:every] = :year
|
62
119
|
new(options)
|
63
120
|
end
|
64
121
|
|
122
|
+
# Initialize a recurrence object. All options from shortcut methods
|
123
|
+
# (Recurrence.daily, Recurrence.monthly, and so on) and requires the <tt>:every</tt> option to
|
124
|
+
# be one of these options: <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt>, or <tt>:year</tt>.
|
125
|
+
#
|
126
|
+
# Recurrence.new(:every => :day)
|
127
|
+
# Recurrence.new(:every => :week, :on => :sunday)
|
128
|
+
# Recurrence.new(:every => :month, :on => 14)
|
129
|
+
# Recurrence.new(:every => :year, :on => [:jan, 14])
|
130
|
+
#
|
65
131
|
def initialize(options)
|
66
132
|
raise ArgumentError, ":every option is required" unless options.key?(:every)
|
67
133
|
raise ArgumentError, "invalid :every option" unless FREQUENCY.include?(options[:every].to_s)
|
68
134
|
|
69
|
-
@options = options
|
70
|
-
@normalized_options = initialize_dates(options)
|
135
|
+
@options = options
|
136
|
+
@normalized_options = initialize_dates(options.dup)
|
71
137
|
@normalized_options[:interval] ||= 1
|
72
138
|
|
73
139
|
@event = case @normalized_options[:every].to_sym
|
74
140
|
when :day
|
75
|
-
|
141
|
+
Event::Daily.new(@normalized_options)
|
76
142
|
when :week
|
77
|
-
|
143
|
+
Event::Weekly.new(@normalized_options)
|
78
144
|
when :month
|
79
|
-
|
145
|
+
Event::Monthly.new(@normalized_options)
|
80
146
|
when :year
|
81
|
-
|
147
|
+
Event::Yearly.new(@normalized_options)
|
82
148
|
end
|
83
149
|
end
|
84
150
|
|
151
|
+
# Reset the recurrence cache, returning to the first available date.
|
85
152
|
def reset!
|
86
153
|
@event.reset!
|
87
154
|
@events = nil
|
88
155
|
end
|
89
156
|
|
157
|
+
# Check if a given date can be retrieve from the current recurrence options.
|
158
|
+
#
|
159
|
+
# r = Recurrence.weekly(:on => :sunday)
|
160
|
+
# r.include?("2010-11-16")
|
161
|
+
# #=> false, because "2010-11-16" is monday
|
162
|
+
#
|
90
163
|
def include?(required_date)
|
91
|
-
required_date =
|
164
|
+
required_date = as_date(required_date)
|
92
165
|
|
93
166
|
if required_date < @normalized_options[:starts] || required_date > @normalized_options[:until]
|
94
167
|
false
|
@@ -98,20 +171,48 @@ module SimplesIdeias
|
|
98
171
|
end
|
99
172
|
end
|
100
173
|
|
101
|
-
|
174
|
+
false
|
102
175
|
end
|
103
176
|
|
177
|
+
# Return the next date in recurrence, without changing the internal date object.
|
178
|
+
#
|
179
|
+
# r = Recurrence.weekly(:on => :sunday, :starts => "2010-11-15")
|
180
|
+
# r.next #=> Sun, 21 Nov 2010
|
181
|
+
# r.next #=> Sun, 21 Nov 2010
|
182
|
+
#
|
104
183
|
def next
|
105
184
|
@event.next
|
106
185
|
end
|
107
186
|
|
187
|
+
# Return the next date in recurrence, and changes the internal date object.
|
188
|
+
#
|
189
|
+
# r = Recurrence.weekly(:on => :sunday, :starts => "2010-11-15")
|
190
|
+
# r.next! #=> Sun, 21 Nov 2010
|
191
|
+
# r.next! #=> Sun, 28 Nov 2010
|
192
|
+
#
|
108
193
|
def next!
|
109
194
|
@event.next!
|
110
195
|
end
|
111
196
|
|
197
|
+
# Return an array with all dates within a given recurrence, caching the result.
|
198
|
+
#
|
199
|
+
# r = Recurrence.daily(:starts => "2010-11-15", :until => "2010-11-20")
|
200
|
+
# r.events
|
201
|
+
#
|
202
|
+
# The return will be
|
203
|
+
#
|
204
|
+
# [
|
205
|
+
# [0] Mon, 15 Nov 2010,
|
206
|
+
# [1] Tue, 16 Nov 2010,
|
207
|
+
# [2] Wed, 17 Nov 2010,
|
208
|
+
# [3] Thu, 18 Nov 2010,
|
209
|
+
# [4] Fri, 19 Nov 2010,
|
210
|
+
# [5] Sat, 20 Nov 2010
|
211
|
+
# ]
|
212
|
+
#
|
112
213
|
def events(options={})
|
113
|
-
options[:starts] =
|
114
|
-
options[:until] =
|
214
|
+
options[:starts] = as_date(options[:starts])
|
215
|
+
options[:until] = as_date(options[:until])
|
115
216
|
|
116
217
|
reset! if options[:starts] || options[:until]
|
117
218
|
|
@@ -134,26 +235,44 @@ module SimplesIdeias
|
|
134
235
|
end
|
135
236
|
end
|
136
237
|
|
238
|
+
# Works like SimplesIdeias::Recurrence::Namespace#events, but removes the cache first.
|
137
239
|
def events!(options={})
|
138
240
|
reset!
|
139
241
|
events(options)
|
140
242
|
end
|
141
243
|
|
244
|
+
# Iterate in all events between <tt>:starts</tt> and <tt>:until</tt> options.
|
245
|
+
#
|
246
|
+
# r = Recurrence.daily(:starts => "2010-11-15", :until => "2010-11-17")
|
247
|
+
# r.each do |date|
|
248
|
+
# puts date
|
249
|
+
# end
|
250
|
+
#
|
251
|
+
# This will print
|
252
|
+
#
|
253
|
+
# Sun, 15 Nov 2010
|
254
|
+
# Sun, 16 Nov 2010
|
255
|
+
# Sun, 17 Nov 2010
|
256
|
+
#
|
257
|
+
# When called without a block, it will return a Enumerator.
|
258
|
+
#
|
259
|
+
# r.each
|
260
|
+
# #=> #<Enumerator: [Mon, 15 Nov 2010, Tue, 16 Nov 2010, Wed, 17 Nov 2010]:each>
|
261
|
+
#
|
262
|
+
def each(&block)
|
263
|
+
events.each(&block)
|
264
|
+
end
|
265
|
+
|
266
|
+
# Works like SimplesIdeias::Recurrence::Namespace#each, but removes the cache first.
|
142
267
|
def each!(&block)
|
143
268
|
reset!
|
144
269
|
each(&block)
|
145
270
|
end
|
146
271
|
|
147
|
-
def each(&block)
|
148
|
-
events.each do |item|
|
149
|
-
yield item
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
272
|
private
|
154
|
-
def initialize_dates(options)
|
273
|
+
def initialize_dates(options) # :nodoc:
|
155
274
|
[:starts, :until].each do |name|
|
156
|
-
options[name] =
|
275
|
+
options[name] = as_date(options[name])
|
157
276
|
end
|
158
277
|
|
159
278
|
options[:starts] ||= self.class.default_starts_date
|
@@ -161,5 +280,14 @@ module SimplesIdeias
|
|
161
280
|
|
162
281
|
options
|
163
282
|
end
|
283
|
+
|
284
|
+
def as_date(date) # :nodoc:
|
285
|
+
case date
|
286
|
+
when String
|
287
|
+
Date.parse(date)
|
288
|
+
else
|
289
|
+
date
|
290
|
+
end
|
291
|
+
end
|
164
292
|
end
|
165
293
|
end
|
data/lib/recurrence/version.rb
CHANGED
data/recurrence.gemspec
CHANGED
data/spec/recurrence_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Recurrence do
|
4
4
|
it "should require :every option" do
|
5
5
|
expect { recurrence({}) }.to raise_error(ArgumentError)
|
6
6
|
end
|
@@ -13,58 +13,76 @@ describe "recurrence" do
|
|
13
13
|
expect { recurrence(:every => :day, :interval => 0) }.to raise_error(ArgumentError)
|
14
14
|
end
|
15
15
|
|
16
|
+
it "should return an enumerator when Recurrence#each is called without a block" do
|
17
|
+
recurrence(:every => :day).each.should be_instance_of(Enumerator)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return an enumerator when Recurrence#each! is called without a block" do
|
21
|
+
recurrence(:every => :day).each!.should be_instance_of(Enumerator)
|
22
|
+
end
|
23
|
+
|
16
24
|
Recurrence::Event::Monthly::INTERVALS.each do |interval|
|
17
25
|
it "should accept valid :interval symbol for monthly recurrence (#{interval[0]})" do
|
18
|
-
expect {
|
26
|
+
expect {
|
27
|
+
recurrence(:every => :month, :on => 10, :interval => interval[0])
|
28
|
+
}.to_not raise_error(ArgumentError)
|
19
29
|
end
|
20
30
|
end
|
21
31
|
|
22
32
|
Recurrence::Event::Yearly::MONTHS.each do |month_name, month_number|
|
23
33
|
it "should accept month as symbol for yearly recurrence (#{month_name})" do
|
24
|
-
expect {
|
34
|
+
expect {
|
35
|
+
recurrence(:every => :year, :on => [month_name, 10])
|
36
|
+
}.to_not raise_error(ArgumentError)
|
25
37
|
end
|
26
38
|
end
|
27
39
|
|
28
40
|
it "should require month to be a valid symbol for yearly recurrence" do
|
29
|
-
expect {
|
41
|
+
expect {
|
42
|
+
recurrence(:every => :year, :on => [:invalid, 10])
|
43
|
+
}.to raise_error(ArgumentError)
|
30
44
|
end
|
31
45
|
|
32
46
|
it "should require :interval to be a valid symbol for monthly recurrence" do
|
33
|
-
expect {
|
47
|
+
expect {
|
48
|
+
recurrence(:every => :month, :on => 10, :interval => :invalid)
|
49
|
+
}.to raise_error(ArgumentError)
|
34
50
|
end
|
35
51
|
|
36
|
-
describe
|
37
|
-
it
|
52
|
+
describe ".default_starts_date" do
|
53
|
+
it "should return Date.today by default" do
|
38
54
|
Recurrence.default_starts_date.should == Date.today
|
39
55
|
end
|
40
56
|
|
41
|
-
it
|
42
|
-
expect {
|
57
|
+
it "should require only strings and procs" do
|
58
|
+
expect {
|
59
|
+
Recurrence.default_starts_date = Date.tomorrow
|
60
|
+
}.to raise_error(ArgumentError)
|
43
61
|
end
|
44
62
|
|
45
|
-
context
|
46
|
-
before { Recurrence.default_starts_date =
|
63
|
+
context "when .default_starts_date is reassigned to 'Date.tomorrow' string" do
|
64
|
+
before { Recurrence.default_starts_date = "Date.tomorrow" }
|
47
65
|
after { Recurrence.default_starts_date = nil }
|
48
66
|
|
49
|
-
it
|
67
|
+
it "should return Date.tomorrow" do
|
50
68
|
Recurrence.default_starts_date.should == Date.tomorrow
|
51
69
|
end
|
52
70
|
|
53
|
-
it
|
71
|
+
it "should have effect on generated events" do
|
54
72
|
r = Recurrence.new(:every => :day, :until => 3.days.from_now.to_date)
|
55
73
|
r.events.first.should == Date.tomorrow
|
56
74
|
end
|
57
75
|
end
|
58
76
|
|
59
|
-
context
|
77
|
+
context "when .default_starts_date is reassigned to lambda { Date.tomorrow } proc" do
|
60
78
|
before { Recurrence.default_starts_date = lambda { Date.tomorrow } }
|
61
79
|
after { Recurrence.default_starts_date = nil }
|
62
80
|
|
63
|
-
it
|
81
|
+
it "should return Date.tomorrow" do
|
64
82
|
Recurrence.default_starts_date.should == Date.tomorrow
|
65
83
|
end
|
66
84
|
|
67
|
-
it
|
85
|
+
it "should have effect on generated events" do
|
68
86
|
r = Recurrence.new(:every => :day, :until => 3.days.from_now.to_date)
|
69
87
|
r.events.first.should == Date.tomorrow
|
70
88
|
end
|
@@ -106,7 +124,12 @@ describe "recurrence" do
|
|
106
124
|
end
|
107
125
|
|
108
126
|
it "should have a lacking day if the interval does not match the last day" do
|
109
|
-
@recurrence = recurrence(
|
127
|
+
@recurrence = recurrence(
|
128
|
+
:every => :day,
|
129
|
+
:starts => "2008-03-19",
|
130
|
+
:until => "2008-04-25",
|
131
|
+
:interval => 2
|
132
|
+
)
|
110
133
|
@recurrence.events[-1].to_s.should == "2008-04-24"
|
111
134
|
end
|
112
135
|
end
|
@@ -140,7 +163,12 @@ describe "recurrence" do
|
|
140
163
|
starts = Date.parse("2008-02-29")
|
141
164
|
ends = Date.parse("2008-03-14")
|
142
165
|
|
143
|
-
@recurrence = recurrence(
|
166
|
+
@recurrence = recurrence(
|
167
|
+
:every => :week,
|
168
|
+
:on => :friday,
|
169
|
+
:starts => starts,
|
170
|
+
:until => ends.to_date
|
171
|
+
)
|
144
172
|
@recurrence.events[0].to_s.should == "2008-02-29"
|
145
173
|
@recurrence.events[1].to_s.should == "2008-03-07"
|
146
174
|
@recurrence.events[-1].to_s.should == ends.to_s
|
@@ -148,7 +176,13 @@ describe "recurrence" do
|
|
148
176
|
|
149
177
|
it "should use interval" do
|
150
178
|
starts = Date.parse("2008-09-21")
|
151
|
-
@recurrence = recurrence(
|
179
|
+
@recurrence = recurrence(
|
180
|
+
:every => :week,
|
181
|
+
:on => starts.wday,
|
182
|
+
:interval => 2,
|
183
|
+
:starts => starts,
|
184
|
+
:until => "2009-01-01"
|
185
|
+
)
|
152
186
|
@recurrence.events[0].to_s.should == "2008-09-21"
|
153
187
|
@recurrence.events[1].to_s.should == "2008-10-05"
|
154
188
|
@recurrence.events[2].to_s.should == "2008-10-19"
|
@@ -160,7 +194,13 @@ describe "recurrence" do
|
|
160
194
|
|
161
195
|
it "should occur several times per week" do
|
162
196
|
starts = Date.parse("2008-09-21") #=> sunday
|
163
|
-
@recurrence = recurrence(
|
197
|
+
@recurrence = recurrence(
|
198
|
+
:every => :week,
|
199
|
+
:on => [:saturday, :sunday],
|
200
|
+
:interval => 2,
|
201
|
+
:starts => starts,
|
202
|
+
:until => "2009-01-01"
|
203
|
+
)
|
164
204
|
@recurrence.events[0].to_s.should == "2008-09-21"
|
165
205
|
@recurrence.events[1].to_s.should == "2008-09-27"
|
166
206
|
@recurrence.events[2].to_s.should == "2008-10-05"
|
@@ -171,7 +211,12 @@ describe "recurrence" do
|
|
171
211
|
@recurrence.events[7].to_s.should == "2008-11-08"
|
172
212
|
|
173
213
|
starts = Date.parse("2008-09-21") #=> sunday
|
174
|
-
@recurrence = recurrence(
|
214
|
+
@recurrence = recurrence(
|
215
|
+
:every => :week,
|
216
|
+
:on => [:monday, :wednesday, :friday],
|
217
|
+
:starts => starts,
|
218
|
+
:until => "2009-01-01"
|
219
|
+
)
|
175
220
|
@recurrence.events[0].to_s.should == "2008-09-22"
|
176
221
|
@recurrence.events[1].to_s.should == "2008-09-24"
|
177
222
|
@recurrence.events[2].to_s.should == "2008-09-26"
|
@@ -182,7 +227,12 @@ describe "recurrence" do
|
|
182
227
|
|
183
228
|
it "should run until next available saturday" do
|
184
229
|
starts = Date.parse("2008-09-21") # => sunday
|
185
|
-
@recurrence = recurrence(
|
230
|
+
@recurrence = recurrence(
|
231
|
+
:every => :week,
|
232
|
+
:on => :saturday,
|
233
|
+
:starts => starts,
|
234
|
+
:until => "2009-01-01"
|
235
|
+
)
|
186
236
|
@recurrence.events[0].to_s.should == "2008-09-27"
|
187
237
|
end
|
188
238
|
end
|
@@ -211,7 +261,12 @@ describe "recurrence" do
|
|
211
261
|
starts = Date.parse("2008-06-07")
|
212
262
|
ends = Date.parse("2008-11-07")
|
213
263
|
|
214
|
-
@recurrence = recurrence(
|
264
|
+
@recurrence = recurrence(
|
265
|
+
:every => :month,
|
266
|
+
:on => starts.day,
|
267
|
+
:starts => starts,
|
268
|
+
:until => ends
|
269
|
+
)
|
215
270
|
@recurrence.events[0].to_s.should == "2008-06-07"
|
216
271
|
@recurrence.events[-1].to_s.should == "2008-11-07"
|
217
272
|
end
|
@@ -219,13 +274,24 @@ describe "recurrence" do
|
|
219
274
|
it "should run until next available 27th" do
|
220
275
|
starts = Date.parse("2008-09-28")
|
221
276
|
|
222
|
-
@recurrence = recurrence(
|
277
|
+
@recurrence = recurrence(
|
278
|
+
:every => :month,
|
279
|
+
:on => 27,
|
280
|
+
:starts => starts,
|
281
|
+
:until => "2009-01-01"
|
282
|
+
)
|
223
283
|
@recurrence.events[0].to_s.should == "2008-10-27"
|
224
284
|
end
|
225
285
|
|
226
286
|
it "should use interval" do
|
227
287
|
starts = Date.parse("2008-01-31")
|
228
|
-
@recurrence = recurrence(
|
288
|
+
@recurrence = recurrence(
|
289
|
+
:every => :month,
|
290
|
+
:on => 31,
|
291
|
+
:interval => 2,
|
292
|
+
:starts => starts,
|
293
|
+
:until => "2010-01-01"
|
294
|
+
)
|
229
295
|
@recurrence.events[0].to_s.should == "2008-01-31"
|
230
296
|
@recurrence.events[1].to_s.should == "2008-03-31"
|
231
297
|
@recurrence.events[2].to_s.should == "2008-05-31"
|
@@ -235,7 +301,13 @@ describe "recurrence" do
|
|
235
301
|
@recurrence.events[6].to_s.should == "2009-01-31"
|
236
302
|
|
237
303
|
starts = Date.parse("2008-01-31")
|
238
|
-
@recurrence = recurrence(
|
304
|
+
@recurrence = recurrence(
|
305
|
+
:every => :month,
|
306
|
+
:on => 29,
|
307
|
+
:interval => 3,
|
308
|
+
:starts => starts,
|
309
|
+
:until => "2010-01-01"
|
310
|
+
)
|
239
311
|
@recurrence.events[0].to_s.should == "2008-04-29"
|
240
312
|
@recurrence.events[1].to_s.should == "2008-07-29"
|
241
313
|
@recurrence.events[2].to_s.should == "2008-10-29"
|
@@ -244,7 +316,13 @@ describe "recurrence" do
|
|
244
316
|
@recurrence.events[5].to_s.should == "2009-07-29"
|
245
317
|
|
246
318
|
starts = Date.parse("2008-02-29")
|
247
|
-
@recurrence = recurrence(
|
319
|
+
@recurrence = recurrence(
|
320
|
+
:every => :month,
|
321
|
+
:on => 31,
|
322
|
+
:interval => 4,
|
323
|
+
:starts => starts,
|
324
|
+
:until => "2010-01-01"
|
325
|
+
)
|
248
326
|
@recurrence.events[0].to_s.should == "2008-02-29"
|
249
327
|
@recurrence.events[1].to_s.should == "2008-06-30"
|
250
328
|
@recurrence.events[2].to_s.should == "2008-10-31"
|
@@ -261,14 +339,24 @@ describe "recurrence" do
|
|
261
339
|
it "should repeat until 8 months from now" do
|
262
340
|
date = 8.months.from_now
|
263
341
|
week = (date.day - 1) / 7 + 1
|
264
|
-
@recurrence = recurrence(
|
342
|
+
@recurrence = recurrence(
|
343
|
+
:every => :month,
|
344
|
+
:on => week,
|
345
|
+
:weekday => date.wday,
|
346
|
+
:until => date.to_date
|
347
|
+
)
|
265
348
|
@recurrence.events[-1].should == date.to_date
|
266
349
|
end
|
267
350
|
|
268
351
|
it "should start 9 months ago" do
|
269
352
|
date = 9.months.ago
|
270
353
|
week = (date.day - 1) / 7 + 1
|
271
|
-
@recurrence = recurrence(
|
354
|
+
@recurrence = recurrence(
|
355
|
+
:every => :month,
|
356
|
+
:on => week,
|
357
|
+
:weekday => date.wday,
|
358
|
+
:starts => date.to_date
|
359
|
+
)
|
272
360
|
@recurrence.events[0].should == date.to_date
|
273
361
|
end
|
274
362
|
|
@@ -276,7 +364,13 @@ describe "recurrence" do
|
|
276
364
|
starts = Date.parse("2008-06-07")
|
277
365
|
ends = Date.parse("2008-11-01")
|
278
366
|
|
279
|
-
@recurrence = recurrence(
|
367
|
+
@recurrence = recurrence(
|
368
|
+
:every => :month,
|
369
|
+
:on => :first,
|
370
|
+
:weekday => :saturday,
|
371
|
+
:starts => starts,
|
372
|
+
:until => ends
|
373
|
+
)
|
280
374
|
@recurrence.events[0].to_s.should == "2008-06-07"
|
281
375
|
@recurrence.events[-1].to_s.should == "2008-11-01"
|
282
376
|
end
|
@@ -285,14 +379,27 @@ describe "recurrence" do
|
|
285
379
|
starts = Date.parse("2008-06-29")
|
286
380
|
ends = Date.parse("2008-11-30")
|
287
381
|
|
288
|
-
@recurrence = recurrence(
|
382
|
+
@recurrence = recurrence(
|
383
|
+
:every => :month,
|
384
|
+
:on => :last,
|
385
|
+
:weekday => :sunday,
|
386
|
+
:starts => starts,
|
387
|
+
:until => ends
|
388
|
+
)
|
289
389
|
@recurrence.events[0].to_s.should == "2008-06-29"
|
290
390
|
@recurrence.events[-1].to_s.should == "2008-11-30"
|
291
391
|
end
|
292
392
|
|
293
393
|
it "should use interval" do
|
294
394
|
starts = Date.parse("2009-01-01")
|
295
|
-
@recurrence = recurrence(
|
395
|
+
@recurrence = recurrence(
|
396
|
+
:every => :month,
|
397
|
+
:on => :third,
|
398
|
+
:weekday => :sunday,
|
399
|
+
:interval => 2,
|
400
|
+
:starts => starts,
|
401
|
+
:until => "2010-02-01"
|
402
|
+
)
|
296
403
|
@recurrence.events[0].to_s.should == "2009-01-18"
|
297
404
|
@recurrence.events[1].to_s.should == "2009-03-15"
|
298
405
|
@recurrence.events[2].to_s.should == "2009-05-17"
|
@@ -317,19 +424,34 @@ describe "recurrence" do
|
|
317
424
|
end
|
318
425
|
|
319
426
|
it "should accept monthly symbol" do
|
320
|
-
@recurrence = recurrence(
|
427
|
+
@recurrence = recurrence(
|
428
|
+
:every => :month,
|
429
|
+
:on => 10,
|
430
|
+
:starts => @starts,
|
431
|
+
:interval => :monthly
|
432
|
+
)
|
321
433
|
@recurrence.events[0].to_s.should == "2008-09-10"
|
322
434
|
@recurrence.events[1].to_s.should == "2008-10-10"
|
323
435
|
end
|
324
436
|
|
325
437
|
it "should accept bimonthly symbol" do
|
326
|
-
@recurrence = recurrence(
|
438
|
+
@recurrence = recurrence(
|
439
|
+
:every => :month,
|
440
|
+
:on => 10,
|
441
|
+
:starts => @starts,
|
442
|
+
:interval => :bimonthly
|
443
|
+
)
|
327
444
|
@recurrence.events[0].to_s.should == "2008-09-10"
|
328
445
|
@recurrence.events[1].to_s.should == "2008-11-10"
|
329
446
|
end
|
330
447
|
|
331
448
|
it "should accept quarterly symbol" do
|
332
|
-
@recurrence = recurrence(
|
449
|
+
@recurrence = recurrence(
|
450
|
+
:every => :month,
|
451
|
+
:on => 10,
|
452
|
+
:starts => @starts,
|
453
|
+
:interval => :quarterly
|
454
|
+
)
|
333
455
|
@recurrence.events[0].to_s.should == "2008-09-10"
|
334
456
|
@recurrence.events[1].to_s.should == "2008-12-10"
|
335
457
|
end
|
@@ -350,13 +472,21 @@ describe "recurrence" do
|
|
350
472
|
|
351
473
|
it "should repeat until 7 years from now" do
|
352
474
|
date = 7.years.from_now
|
353
|
-
@recurrence = recurrence(
|
475
|
+
@recurrence = recurrence(
|
476
|
+
:every => :year,
|
477
|
+
:on => [date.month, date.day],
|
478
|
+
:until => date.to_date
|
479
|
+
)
|
354
480
|
@recurrence.events[-1].should == date.to_date
|
355
481
|
end
|
356
482
|
|
357
483
|
it "should start 2 years ago" do
|
358
484
|
date = 2.years.ago
|
359
|
-
@recurrence = recurrence(
|
485
|
+
@recurrence = recurrence(
|
486
|
+
:every => :year,
|
487
|
+
:on => [date.month, date.day],
|
488
|
+
:starts => date.to_date
|
489
|
+
)
|
360
490
|
@recurrence.events[0].should == date.to_date
|
361
491
|
end
|
362
492
|
|
@@ -364,7 +494,12 @@ describe "recurrence" do
|
|
364
494
|
starts = Date.parse("2003-06-07")
|
365
495
|
ends = Date.parse("2018-06-07")
|
366
496
|
|
367
|
-
@recurrence = recurrence(
|
497
|
+
@recurrence = recurrence(
|
498
|
+
:every => :year,
|
499
|
+
:on => [starts.month, starts.day],
|
500
|
+
:starts => starts,
|
501
|
+
:until => ends
|
502
|
+
)
|
368
503
|
@recurrence.events[0].to_s.should == "2003-06-07"
|
369
504
|
@recurrence.events[-1].to_s.should == "2018-06-07"
|
370
505
|
end
|
@@ -372,7 +507,12 @@ describe "recurrence" do
|
|
372
507
|
it "should use interval" do
|
373
508
|
starts = Date.parse("2008-09-21")
|
374
509
|
|
375
|
-
@recurrence = recurrence(
|
510
|
+
@recurrence = recurrence(
|
511
|
+
:every => :year,
|
512
|
+
:on => [starts.month, starts.day],
|
513
|
+
:interval => 2,
|
514
|
+
:starts => starts
|
515
|
+
)
|
376
516
|
@recurrence.events[0].to_s.should == "2008-09-21"
|
377
517
|
@recurrence.events[1].to_s.should == "2010-09-21"
|
378
518
|
@recurrence.events[2].to_s.should == "2012-09-21"
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -3,10 +3,10 @@ name: recurrence
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
- 0
|
7
6
|
- 1
|
8
|
-
-
|
9
|
-
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nando Vieira
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-11-
|
17
|
+
date: 2010-11-16 00:00:00 -02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
type: :runtime
|
32
32
|
version_requirements: *id001
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name: rspec
|
34
|
+
name: rspec
|
35
35
|
prerelease: false
|
36
36
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
37
|
none: false
|
@@ -45,6 +45,19 @@ dependencies:
|
|
45
45
|
version: 2.0.0
|
46
46
|
type: :development
|
47
47
|
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: ruby-debug19
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
type: :development
|
60
|
+
version_requirements: *id003
|
48
61
|
description: A simple library to handle recurring events
|
49
62
|
email:
|
50
63
|
- fnando.vieira@gmail.com
|
@@ -62,9 +75,8 @@ files:
|
|
62
75
|
- Gemfile.lock
|
63
76
|
- History.txt
|
64
77
|
- License.txt
|
65
|
-
- README.
|
78
|
+
- README.rdoc
|
66
79
|
- Rakefile
|
67
|
-
- init.rb
|
68
80
|
- lib/recurrence.rb
|
69
81
|
- lib/recurrence/event.rb
|
70
82
|
- lib/recurrence/event/base.rb
|
data/README.markdown
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
Recurrence
|
2
|
-
==========
|
3
|
-
|
4
|
-
* [http://github.com/fnando/recurrence](http://github.com/fnando/recurrence)
|
5
|
-
|
6
|
-
DESCRIPTION:
|
7
|
-
------------
|
8
|
-
|
9
|
-
A simple library to handle recurring events.
|
10
|
-
|
11
|
-
|
12
|
-
INSTALLATION:
|
13
|
-
-------------
|
14
|
-
|
15
|
-
Recurrence can be installed by running
|
16
|
-
|
17
|
-
gem install recurrence
|
18
|
-
|
19
|
-
USAGE:
|
20
|
-
------
|
21
|
-
|
22
|
-
require 'rubygems'
|
23
|
-
require 'recurrence'
|
24
|
-
|
25
|
-
# Daily
|
26
|
-
r = Recurrence.new(:every => :day)
|
27
|
-
r = Recurrence.new(:every => :day, :interval => 9)
|
28
|
-
r = Recurrence.daily(options = {})
|
29
|
-
|
30
|
-
# Weekly
|
31
|
-
r = Recurrence.new(:every => :week, :on => 5)
|
32
|
-
r = Recurrence.new(:every => :week, :on => :monday)
|
33
|
-
r = Recurrence.new(:every => :week, :on => [:monday, :friday])
|
34
|
-
r = Recurrence.new(:every => :week, :on => [:monday, :wednesday, :friday])
|
35
|
-
r = Recurrence.new(:every => :week, :on => :friday, :interval => 2)
|
36
|
-
r = Recurrence.weekly(:on => :thursday)
|
37
|
-
|
38
|
-
# Monthly by month day
|
39
|
-
r = Recurrence.new(:every => :month, :on => 15)
|
40
|
-
r = Recurrence.new(:every => :month, :on => 31)
|
41
|
-
r = Recurrence.new(:every => :month, :on => 7, :interval => 2)
|
42
|
-
r = Recurrence.new(:every => :month, :on => 7, :interval => :monthly)
|
43
|
-
r = Recurrence.new(:every => :month, :on => 7, :interval => :bimonthly)
|
44
|
-
r = Recurrence.monthly(:on => 31)
|
45
|
-
|
46
|
-
# Monthly by week day
|
47
|
-
r = Recurrence.new(:every => :month, :on => :first, :weekday => :sunday)
|
48
|
-
r = Recurrence.new(:every => :month, :on => :third, :weekday => :monday)
|
49
|
-
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday)
|
50
|
-
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday, :interval => 2)
|
51
|
-
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday, :interval => :quarterly)
|
52
|
-
r = Recurrence.new(:every => :month, :on => :last, :weekday => :friday, :interval => :semesterly)
|
53
|
-
|
54
|
-
# Yearly
|
55
|
-
r = Recurrence.new(:every => :year, :on => [7, 4]) # => [month, day]
|
56
|
-
r = Recurrence.new(:every => :year, :on => [10, 31], :interval => 3)
|
57
|
-
r = Recurrence.new(:every => :year, :on => [:jan, 31])
|
58
|
-
r = Recurrence.new(:every => :year, :on => [:january, 31])
|
59
|
-
r = Recurrence.yearly(:on => [:january, 31])
|
60
|
-
|
61
|
-
# Limit recurrence
|
62
|
-
# :starts defaults to Date.today
|
63
|
-
# :until defaults to 2037-12-31
|
64
|
-
r = Recurrence.new(:every => :day, :starts => Date.today)
|
65
|
-
r = Recurrence.new(:every => :day, :until => '2010-01-31')
|
66
|
-
r = Recurrence.new(:every => :day, :starts => Date.today, :until => '2010-01-31')
|
67
|
-
|
68
|
-
# Getting an array with all events
|
69
|
-
r.events.each {|date| puts date.to_s } # => Memoized array
|
70
|
-
r.events!.each {|date| puts date.to_s } # => reset items cache and re-execute it
|
71
|
-
r.events(:starts => '2009-01-01').each {|date| puts date.to_s }
|
72
|
-
r.events(:until => '2009-01-10').each {|date| puts date.to_s }
|
73
|
-
r.events(:starts => '2009-01-05', :until => '2009-01-10').each {|date| puts date.to_s }
|
74
|
-
|
75
|
-
# Iterating events
|
76
|
-
r.each { |date| puts date.to_s } # => Use items method
|
77
|
-
r.each! { |date| puts date.to_s } # => Use items! method
|
78
|
-
|
79
|
-
# Check if a date is included
|
80
|
-
r.include?(Date.today) # => true or false
|
81
|
-
r.include?('2008-09-21')
|
82
|
-
|
83
|
-
# Get next available date
|
84
|
-
r.next # => Keep the original date object
|
85
|
-
r.next! # => Change the internal date object to the next available date
|
86
|
-
|
87
|
-
TROUBLESHOOTING
|
88
|
-
---------------
|
89
|
-
|
90
|
-
If you're having problems because already have a class/module called Recurrence that is conflicting with this gem, you can require the namespace and create a class that inherits from `SimplesIdeias::Recurrence`.
|
91
|
-
|
92
|
-
require "recurrence/namespace"
|
93
|
-
|
94
|
-
class RecurrentEvent < SimplesIdeias::Recurrence
|
95
|
-
end
|
96
|
-
|
97
|
-
r = RecurrentEvent.new(:every => :day)
|
98
|
-
|
99
|
-
If you're using Rails/Bundler or something like that, remember to override the `:require` option.
|
100
|
-
|
101
|
-
# Gemfile
|
102
|
-
source :rubygems
|
103
|
-
|
104
|
-
gem "recurrence", :require => "recurrence/namespace"
|
105
|
-
|
106
|
-
MAINTAINER
|
107
|
-
----------
|
108
|
-
|
109
|
-
* Nando Vieira (<http://simplesideias.com.br/>)
|
110
|
-
|
111
|
-
CONTRIBUTORS
|
112
|
-
------------
|
113
|
-
|
114
|
-
* José Valim (<http://josevalim.blogspot.com/>)
|
115
|
-
|
116
|
-
LICENSE:
|
117
|
-
--------
|
118
|
-
|
119
|
-
(The MIT License)
|
120
|
-
|
121
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
122
|
-
a copy of this software and associated documentation files (the
|
123
|
-
'Software'), to deal in the Software without restriction, including
|
124
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
125
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
126
|
-
permit persons to whom the Software is furnished to do so, subject to
|
127
|
-
the following conditions:
|
128
|
-
|
129
|
-
The above copyright notice and this permission notice shall be
|
130
|
-
included in all copies or substantial portions of the Software.
|
131
|
-
|
132
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
133
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
134
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
135
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
136
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
137
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
138
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/init.rb
DELETED