fnando-recurrence 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt ADDED
@@ -0,0 +1,15 @@
1
+ == 0.0.1 2008-09-21
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+
6
+ == 0.0.2 2008-09-21
7
+
8
+ * 1 minor enhancement:
9
+ * Added `items` and `items!` methods; returns an array with all events
10
+
11
+ == 0.0.3 2008-09-22
12
+
13
+ * 1 major enhancement:
14
+ * The recurrence now considers the starting date and its configurations
15
+ * Added lots of specs
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Nando Vieira
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,100 @@
1
+ Recurrence
2
+ ==========
3
+
4
+ * [http://github.com/fnando/recurrence](http://github.com/fnando/recurrence)
5
+
6
+ DESCRIPTION:
7
+ ------------
8
+
9
+ A simples library that handles recurring events.
10
+
11
+
12
+ INSTALLATION:
13
+ -------------
14
+
15
+ Recurrence can be installed as Rails plugin or gem. To install it as gem, just
16
+ run the command
17
+
18
+ sudo gem install fnando-recurrence --source=http://gems.github.com
19
+
20
+ If you prefer it as a plugin, just run the command
21
+
22
+ script/plugin install git://github.com/fnando/recurrence.git
23
+
24
+ USAGE:
25
+ ------
26
+
27
+ require 'rubygems'
28
+ require 'recurrence'
29
+
30
+ # Daily
31
+ r = Recurrence.new(:every => :day)
32
+ r = Recurrence.new(:every => :day, :interval => 9)
33
+
34
+ # Weekly
35
+ r = Recurrence.new(:every => :week, :on => :friday)
36
+ r = Recurrence.new(:every => :week, :on => 5)
37
+ r = Recurrence.new(:every => :week, :on => :friday, :interval => 2)
38
+
39
+ # Monthly
40
+ r = Recurrence.new(:every => :month, :on => 15)
41
+ r = Recurrence.new(:every => :month, :on => 31)
42
+ r = Recurrence.new(:every => :month, :on => 7, :interval => 2)
43
+
44
+ # Yearly
45
+ r = Recurrence.new(:every => :year, :on => [7, 4]) # => [month, day]
46
+ r = Recurrence.new(:every => :year, :on => [10, 31], :interval => 3)
47
+
48
+ # Limit recurrence
49
+ # :starts defaults to Date.today
50
+ # :until defaults to 2037-12-31
51
+ r = Recurrence.new(:day, :starts => Date.today)
52
+ r = Recurrence.new(:day, :until => '2010-01-31')
53
+ r = Recurrence.new(:day, :starts => Date.today, :until => '2010-01-31')
54
+
55
+ # Iterating events
56
+ r.each do |date|
57
+ puts date.to_s
58
+ end
59
+
60
+ # Getting an array with all events
61
+ r.items.each {|date| puts date.to_s } # => Memoized array
62
+ r.items!.each {|date| puts date.to_s } # => reset items cache and re-execute it
63
+
64
+ # Check if a date is included
65
+ r.include?(Date.today) # => true or false
66
+ r.include?('2008-09-21')
67
+
68
+ TODO
69
+ ----
70
+
71
+ * Write the specs
72
+
73
+ MAINTAINER
74
+ ----------
75
+
76
+ * Nando Vieira ([http://simplesideias.com.br](http://simplesideias.com.br))
77
+
78
+ LICENSE:
79
+ --------
80
+
81
+ (The MIT License)
82
+
83
+ Permission is hereby granted, free of charge, to any person obtaining
84
+ a copy of this software and associated documentation files (the
85
+ 'Software'), to deal in the Software without restriction, including
86
+ without limitation the rights to use, copy, modify, merge, publish,
87
+ distribute, sublicense, and/or sell copies of the Software, and to
88
+ permit persons to whom the Software is furnished to do so, subject to
89
+ the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be
92
+ included in all copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
95
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
96
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
97
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
98
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
99
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
100
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,76 @@
1
+ require 'rake'
2
+
3
+ PKG_FILES = %w(init.rb Rakefile recurrence.gemspec History.txt License.txt README.markdown TODO.txt) +
4
+ Dir["lib/**/*"]
5
+
6
+ spec = Gem::Specification.new do |s|
7
+ s.name = "recurrence"
8
+ s.version = "0.0.3"
9
+ s.summary = "A simples library that handles recurring events"
10
+ s.authors = ["Nando Vieira"]
11
+ s.email = ["fnando.vieira@gmail.com"]
12
+ s.homepage = "http://github.com/fnando/recurrence"
13
+ s.description = ""
14
+ s.has_rdoc = false
15
+ s.files = PKG_FILES
16
+
17
+ s.add_dependency "rubigen"
18
+ s.add_dependency "activesupport"
19
+ end
20
+
21
+ namespace :gem do
22
+ # Thanks to the Merb project for this code.
23
+ desc "Update Github Gemspec"
24
+ task :update_gemspec do
25
+ skip_fields = %w(new_platform original_platform specification_version loaded required_ruby_version rubygems_version platform )
26
+
27
+ result = "# WARNING : RAKE AUTO-GENERATED FILE. DO NOT MANUALLY EDIT!\n"
28
+ result << "# RUN : 'rake gem:update_gemspec'\n\n"
29
+ result << "Gem::Specification.new do |s|\n"
30
+
31
+ spec.instance_variables.each do |ivar|
32
+ value = spec.instance_variable_get(ivar)
33
+ name = ivar.split("@").last
34
+ value = Time.now if name == "date"
35
+
36
+ next if skip_fields.include?(name) || value.nil? || value == "" || (value.respond_to?(:empty?) && value.empty?)
37
+ if name == "dependencies"
38
+ value.each do |d|
39
+ dep, *ver = d.to_s.split(" ")
40
+ result << " s.add_dependency #{dep.inspect}, #{ver.join(" ").inspect.gsub(/[()]/, "").gsub(", runtime", "")}\n"
41
+ end
42
+ else
43
+ case value
44
+ when Array
45
+ value = name != "files" ? value.inspect : value.inspect.split(",").join(",\n")
46
+ when FalseClass
47
+ when TrueClass
48
+ when Fixnum
49
+ when String
50
+ value = value.inspect
51
+ else
52
+ value = value.to_s.inspect
53
+ end
54
+ result << " s.#{name} = #{value}\n"
55
+ end
56
+ end
57
+
58
+ result << "end"
59
+ File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w"){|f| f << result}
60
+ end
61
+
62
+ desc "Build gem"
63
+ task :build => [:update_gemspec] do
64
+ system "gem build #{spec.instance_variable_get('@name')}.gemspec"
65
+ end
66
+
67
+ desc "Install gem"
68
+ task :install => [:update_gemspec, :build] do
69
+ system "sudo gem install #{spec.instance_variable_get('@name')}"
70
+ end
71
+ end
72
+
73
+ desc "Execute specs"
74
+ task :specs do
75
+ system "spec specs/recurrence_spec.rb -c -f s"
76
+ end
data/TODO.txt ADDED
File without changes
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require "recurrence"
data/lib/recurrence.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ require "date"
3
+ gem "activesupport", ">=2.1.1"
4
+ require "activesupport"
5
+ require File.dirname(__FILE__) + "/recurrence/base"
6
+ require File.dirname(__FILE__) + "/recurrence/event"
@@ -0,0 +1,93 @@
1
+ class Recurrence
2
+ FREQUENCY = %w(day week month year)
3
+ DAYS = %w(sunday monday tuesday wednesday thursday friday saturday)
4
+ INTERVALS = {
5
+ :monthly => 1,
6
+ :bimonthly => 2,
7
+ :quarterly => 3,
8
+ :semestral => 6
9
+ }
10
+
11
+ def initialize(options)
12
+ raise ArgumentError, ':every options is required' unless options.key?(:every)
13
+ raise ArgumentError, 'invalid :every option' unless FREQUENCY.include?(options[:every].to_s)
14
+ raise ArgumentError, 'interval should be greater than zero' if options.key?(:interval) && options[:interval].to_i == 0
15
+
16
+ @options = initialize_dates(options)
17
+ @options[:interval] ||= 1
18
+
19
+ case @options[:every].to_sym
20
+ when :day then
21
+ @event = Recurrence::Event.new(:day, @options)
22
+ when :week then
23
+ raise ArgumentError, 'invalid day' if !DAYS.include?(@options[:on].to_s) && !(0..6).include?(@options[:on])
24
+ @options.merge!(:on => DAYS.index(@options[:on].to_s)) if DAYS.include?(@options[:on].to_s)
25
+ @event = Recurrence::Event.new(:week, @options)
26
+ when :month then
27
+ raise ArgumentError, 'invalid day' unless (1..31).include?(@options[:on])
28
+ @event = Recurrence::Event.new(:month, @options)
29
+ when :year then
30
+ raise ArgumentError, 'invalid month' unless (1..12).include?(@options[:on].first)
31
+ raise ArgumentError, 'invalid day' unless (1..31).include?(@options[:on].last)
32
+ @event = Recurrence::Event.new(:year, @options)
33
+ end
34
+ end
35
+
36
+ def reset!
37
+ @event.reset!
38
+ end
39
+
40
+ def include?(required_date)
41
+ required_date = Date.parse(required_date) if required_date.is_a?(String)
42
+
43
+ if required_date < @options[:starts] || required_date > @options[:until]
44
+ false
45
+ else
46
+ each do |date|
47
+ return true if date == required_date
48
+ end
49
+ end
50
+
51
+ return false
52
+ end
53
+
54
+ def items
55
+ @items ||= begin
56
+ reset!
57
+ _items = []
58
+ each { |date| _items << date }
59
+ _items
60
+ end
61
+ end
62
+
63
+ def items!
64
+ @items = nil
65
+ items
66
+ end
67
+
68
+ def each(&block)
69
+ reset!
70
+
71
+ loop do
72
+ date = @event.find_next!
73
+
74
+ if date.nil?
75
+ break
76
+ else
77
+ yield date
78
+ end
79
+ end
80
+ end
81
+
82
+ private
83
+ def initialize_dates(options)
84
+ [:starts, :until].each do |name|
85
+ options[name] = Date.parse(options[name]) if options[name].is_a?(String)
86
+ end
87
+
88
+ options[:starts] ||= Date.today
89
+ options[:until] ||= Date.parse('2037-12-31')
90
+
91
+ options
92
+ end
93
+ end
@@ -0,0 +1,96 @@
1
+ class Recurrence::Event
2
+ def initialize(every, options={})
3
+ @every = every
4
+ @options = options
5
+ @started = false
6
+ reset!
7
+ end
8
+
9
+ def find_next
10
+ case @every
11
+ when :day
12
+ date = find_next_day
13
+ when :week
14
+ date = find_next_week
15
+ when :month
16
+ date = find_next_month
17
+ when :year
18
+ date = find_next_year
19
+ end
20
+
21
+ date = nil unless date && date.to_date <= @options[:until].to_date
22
+ date
23
+ end
24
+
25
+ def reset!
26
+ @date = @options[:starts]
27
+ end
28
+
29
+ def find_next!
30
+ @date = find_next
31
+ end
32
+
33
+ private
34
+ def started!
35
+ @started = true
36
+ end
37
+
38
+ def started?
39
+ @started == true
40
+ end
41
+
42
+ def find_next_day
43
+ if !started?
44
+ started!
45
+ date = @date
46
+ else
47
+ date = @date + @options[:interval].days
48
+ end
49
+
50
+ date.to_date
51
+ end
52
+
53
+ def find_next_week
54
+ if !started?
55
+ started!
56
+ date = @date
57
+
58
+ unless date.wday == @options[:on]
59
+ date = date.next until @options[:on] == date.wday
60
+ end
61
+ else @options[:interval]
62
+ date = @date + @options[:interval].weeks
63
+ end
64
+
65
+ date.to_date
66
+ end
67
+
68
+ def find_next_month
69
+ if !started?
70
+ started!
71
+ date = @date
72
+ else
73
+ date = @date.beginning_of_month + @options[:interval].months
74
+ end
75
+
76
+ day = [@options[:on], Time.days_in_month(date.month, date.year)].min
77
+ date = Date.new(date.year, date.month, day)
78
+ date.to_date
79
+ end
80
+
81
+ def find_next_year
82
+ if !started?
83
+ started!
84
+ date = @date
85
+ else
86
+ date = @date.beginning_of_month + @options[:interval].years
87
+ end
88
+
89
+ day = [Time.days_in_month(@options[:on].first, date.year), @options[:on].last].min
90
+ year = date.year
91
+
92
+ year += 1 if @options[:on].first < date.month
93
+
94
+ Date.new(year, @options[:on].first, day)
95
+ end
96
+ end
@@ -0,0 +1,29 @@
1
+ # WARNING : RAKE AUTO-GENERATED FILE. DO NOT MANUALLY EDIT!
2
+ # RUN : 'rake gem:update_gemspec'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.date = "Mon Sep 22 21:17:41 -0300 2008"
6
+ s.authors = ["Nando Vieira"]
7
+ s.required_rubygems_version = ">= 0"
8
+ s.version = "0.0.3"
9
+ s.files = ["init.rb",
10
+ "Rakefile",
11
+ "recurrence.gemspec",
12
+ "History.txt",
13
+ "License.txt",
14
+ "README.markdown",
15
+ "TODO.txt",
16
+ "lib/recurrence",
17
+ "lib/recurrence/base.rb",
18
+ "lib/recurrence/event.rb",
19
+ "lib/recurrence.rb"]
20
+ s.has_rdoc = false
21
+ s.email = ["fnando.vieira@gmail.com"]
22
+ s.name = "recurrence"
23
+ s.bindir = "bin"
24
+ s.homepage = "http://github.com/fnando/recurrence"
25
+ s.summary = "A simples library that handles recurring events"
26
+ s.add_dependency "rubigen", ">= 0"
27
+ s.add_dependency "activesupport", ">= 0"
28
+ s.require_paths = ["lib"]
29
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fnando-recurrence
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Nando Vieira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-09-22 17:17:41 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubigen
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: activesupport
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ description:
34
+ email:
35
+ - fnando.vieira@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - init.rb
44
+ - Rakefile
45
+ - recurrence.gemspec
46
+ - History.txt
47
+ - License.txt
48
+ - README.markdown
49
+ - TODO.txt
50
+ - lib/recurrence
51
+ - lib/recurrence/base.rb
52
+ - lib/recurrence/event.rb
53
+ - lib/recurrence.rb
54
+ has_rdoc: false
55
+ homepage: http://github.com/fnando/recurrence
56
+ post_install_message:
57
+ rdoc_options: []
58
+
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.2.0
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: A simples library that handles recurring events
80
+ test_files: []
81
+