fnando-recurrence 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
+