recurrence 0.1.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.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