fnando-recurrence 0.0.3 → 0.0.6

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 CHANGED
@@ -13,3 +13,24 @@
13
13
  * 1 major enhancement:
14
14
  * The recurrence now considers the starting date and its configurations
15
15
  * Added lots of specs
16
+
17
+ == 0.0.4 2008-09-30
18
+
19
+ * 1 major enhancement:
20
+ * Renamed items method to events
21
+ * Added each! method
22
+ * Added lots of specs
23
+
24
+ == 0.0.5 2008-09-30
25
+
26
+ * 1 major enhancement:
27
+ * Monthly interval now accepts symbols: monthly, bimonthly, quarterly,
28
+ semesterly
29
+
30
+ == 0.0.6 2009-01-06
31
+
32
+ * 1 major enhancement:
33
+ * Code refactoring
34
+ * Added next and next! methods
35
+ * Added more specs
36
+ * Yearly interval now accepts symbols: jan-dec and january-december
data/README.markdown CHANGED
@@ -40,35 +40,39 @@ USAGE:
40
40
  r = Recurrence.new(:every => :month, :on => 15)
41
41
  r = Recurrence.new(:every => :month, :on => 31)
42
42
  r = Recurrence.new(:every => :month, :on => 7, :interval => 2)
43
+ r = Recurrence.new(:every => :month, :on => 7, :interval => :monthly)
44
+ r = Recurrence.new(:every => :month, :on => 7, :interval => :bimonthly)
45
+ r = Recurrence.new(:every => :month, :on => 7, :interval => :quarterly)
46
+ r = Recurrence.new(:every => :month, :on => 7, :interval => :semesterly)
43
47
 
44
48
  # Yearly
45
49
  r = Recurrence.new(:every => :year, :on => [7, 4]) # => [month, day]
46
50
  r = Recurrence.new(:every => :year, :on => [10, 31], :interval => 3)
51
+ r = Recurrence.new(:every => :year, :on => [:jan, 31])
52
+ r = Recurrence.new(:every => :year, :on => [:january, 31])
47
53
 
48
54
  # Limit recurrence
49
55
  # :starts defaults to Date.today
50
56
  # :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
57
+ r = Recurrence.new(:every => :day, :starts => Date.today)
58
+ r = Recurrence.new(:every => :day, :until => '2010-01-31')
59
+ r = Recurrence.new(:every => :day, :starts => Date.today, :until => '2010-01-31')
59
60
 
60
61
  # 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
62
+ r.events.each {|date| puts date.to_s } # => Memoized array
63
+ r.events!.each {|date| puts date.to_s } # => reset items cache and re-execute it
64
+
65
+ # Iterating events
66
+ r.each { |date| puts date.to_s } # => Use items method
67
+ r.each! { |date| puts date.to_s } # => Use items! method
63
68
 
64
69
  # Check if a date is included
65
70
  r.include?(Date.today) # => true or false
66
71
  r.include?('2008-09-21')
67
-
68
- TODO
69
- ----
70
-
71
- * Write the specs
72
+
73
+ # Get next available date
74
+ r.next # => Keep the original date object
75
+ r.next! # => Change the internal date object to the next available date
72
76
 
73
77
  MAINTAINER
74
78
  ----------
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'rake'
2
2
 
3
- PKG_FILES = %w(init.rb Rakefile recurrence.gemspec History.txt License.txt README.markdown TODO.txt) +
3
+ PKG_FILES = %w(init.rb Rakefile recurrence.gemspec History.txt License.txt README.markdown) +
4
4
  Dir["lib/**/*"]
5
5
 
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = "recurrence"
8
- s.version = "0.0.3"
8
+ s.version = "0.0.6"
9
9
  s.summary = "A simples library that handles recurring events"
10
10
  s.authors = ["Nando Vieira"]
11
11
  s.email = ["fnando.vieira@gmail.com"]
@@ -15,7 +15,7 @@ spec = Gem::Specification.new do |s|
15
15
  s.files = PKG_FILES
16
16
 
17
17
  s.add_dependency "rubigen"
18
- s.add_dependency "activesupport"
18
+ s.add_dependency "activesupport", ">=2.1.1"
19
19
  end
20
20
 
21
21
  namespace :gem do
@@ -31,7 +31,7 @@ namespace :gem do
31
31
  spec.instance_variables.each do |ivar|
32
32
  value = spec.instance_variable_get(ivar)
33
33
  name = ivar.split("@").last
34
- value = Time.now if name == "date"
34
+ next if name == "date"
35
35
 
36
36
  next if skip_fields.include?(name) || value.nil? || value == "" || (value.respond_to?(:empty?) && value.empty?)
37
37
  if name == "dependencies"
@@ -71,6 +71,6 @@ namespace :gem do
71
71
  end
72
72
 
73
73
  desc "Execute specs"
74
- task :specs do
75
- system "spec specs/recurrence_spec.rb -c -f s"
74
+ task :spec do
75
+ system "spec spec/recurrence_spec.rb -c -f s"
76
76
  end
@@ -1,17 +1,41 @@
1
1
  class Recurrence
2
2
  FREQUENCY = %w(day week month year)
3
3
  DAYS = %w(sunday monday tuesday wednesday thursday friday saturday)
4
+ MONTHS = {
5
+ "jan" => 1, "january" => 1,
6
+ "feb" => 2, "february" => 2,
7
+ "mar" => 3, "march" => 3,
8
+ "apr" => 4, "april" => 4,
9
+ "may" => 5,
10
+ "jun" => 6, "june" => 6,
11
+ "jul" => 7, "july" => 7,
12
+ "aug" => 8, "august" => 8,
13
+ "sep" => 9, "september" => 9,
14
+ "oct" => 10, "october" => 10,
15
+ "nov" => 11, "november" => 11,
16
+ "dec" => 12, "december" => 12
17
+ }
18
+
4
19
  INTERVALS = {
5
20
  :monthly => 1,
6
21
  :bimonthly => 2,
7
22
  :quarterly => 3,
8
- :semestral => 6
23
+ :semesterly => 6
9
24
  }
10
25
 
26
+ attr_reader :event
27
+
11
28
  def initialize(options)
12
- raise ArgumentError, ':every options is required' unless options.key?(:every)
29
+ raise ArgumentError, ':every option is required' unless options.key?(:every)
13
30
  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
31
+
32
+ if options.key?(:interval)
33
+ if options[:every].to_sym == :month && options[:interval].is_a?(Symbol) && !INTERVALS.key?(options[:interval])
34
+ raise ArgumentError, 'interval symbol is not valid'
35
+ elsif options[:interval].to_i == 0
36
+ raise ArgumentError, 'interval should be greater than zero'
37
+ end
38
+ end
15
39
 
16
40
  @options = initialize_dates(options)
17
41
  @options[:interval] ||= 1
@@ -25,16 +49,19 @@ class Recurrence
25
49
  @event = Recurrence::Event.new(:week, @options)
26
50
  when :month then
27
51
  raise ArgumentError, 'invalid day' unless (1..31).include?(@options[:on])
52
+ options.merge!(:interval => INTERVALS[options[:interval]]) if options[:interval].is_a?(Symbol)
28
53
  @event = Recurrence::Event.new(:month, @options)
29
54
  when :year then
30
- raise ArgumentError, 'invalid month' unless (1..12).include?(@options[:on].first)
55
+ raise ArgumentError, 'invalid month' if !(1..12).include?(@options[:on].first) && !MONTHS.keys.include?(@options[:on].first)
31
56
  raise ArgumentError, 'invalid day' unless (1..31).include?(@options[:on].last)
57
+ @options.merge!(:on => [MONTHS[@options[:on].first.to_s], @options.last]) unless @options[:on].first.kind_of?(Numeric)
32
58
  @event = Recurrence::Event.new(:year, @options)
33
59
  end
34
60
  end
35
61
 
36
62
  def reset!
37
63
  @event.reset!
64
+ @events = nil
38
65
  end
39
66
 
40
67
  def include?(required_date)
@@ -51,31 +78,42 @@ class Recurrence
51
78
  return false
52
79
  end
53
80
 
54
- def items
55
- @items ||= begin
56
- reset!
57
- _items = []
58
- each { |date| _items << date }
59
- _items
60
- end
81
+ def next
82
+ @event.next
61
83
  end
62
84
 
63
- def items!
64
- @items = nil
65
- items
85
+ def next!
86
+ @event.next!
66
87
  end
67
88
 
68
- def each(&block)
69
- reset!
70
-
71
- loop do
72
- date = @event.find_next!
89
+ def events
90
+ @events ||= begin
91
+ _events = []
73
92
 
74
- if date.nil?
75
- break
76
- else
77
- yield date
93
+ loop do
94
+ date = @event.next!
95
+
96
+ break if date.nil?
97
+ _events << date
78
98
  end
99
+
100
+ _events
101
+ end
102
+ end
103
+
104
+ def events!
105
+ reset!
106
+ events
107
+ end
108
+
109
+ def each!(&block)
110
+ reset!
111
+ each(&block)
112
+ end
113
+
114
+ def each(&block)
115
+ events.each do |item|
116
+ yield item
79
117
  end
80
118
  end
81
119
 
@@ -1,96 +1,130 @@
1
1
  class Recurrence::Event
2
+ attr_accessor :date, :start_date, :options, :every
3
+
2
4
  def initialize(every, options={})
3
- @every = every
5
+ @every = every
4
6
  @options = options
5
- @started = false
6
- reset!
7
+ @current = nil
8
+ @date = options[:starts]
9
+ prepare!
10
+ end
11
+
12
+ def prepare!
13
+ self.next!
14
+ @start_date = @date
15
+ end
16
+
17
+ def next?
18
+ !!@next
7
19
  end
8
20
 
9
- def find_next
21
+ def next!
22
+ # just continue if date object is null or
23
+ # hasn't been initialized yet
24
+ return nil unless @date || !inited?
25
+
26
+ # return the date if is the first interaction after
27
+ # initializing object
28
+ if inited? && !next?
29
+ @next = true
30
+ return @date
31
+ end
32
+
10
33
  case @every
11
34
  when :day
12
- date = find_next_day
35
+ @date = next_day
13
36
  when :week
14
- date = find_next_week
37
+ @date = next_week
15
38
  when :month
16
- date = find_next_month
39
+ @date = next_month
17
40
  when :year
18
- date = find_next_year
41
+ @date = next_year
19
42
  end
20
43
 
21
- date = nil unless date && date.to_date <= @options[:until].to_date
22
- date
44
+ # if limit date has been reached just set the date
45
+ # object to nil
46
+ @date = nil unless @date.to_date <= @options[:until].to_date
47
+
48
+ @date
23
49
  end
24
50
 
25
- def reset!
26
- @date = @options[:starts]
51
+ def next
52
+ @date
27
53
  end
28
54
 
29
- def find_next!
30
- @date = find_next
55
+ def reset!
56
+ @date = @start_date
31
57
  end
32
58
 
33
59
  private
34
- def started!
35
- @started = true
36
- end
37
-
38
- def started?
39
- @started == true
60
+ def inited?
61
+ !!@start_date
40
62
  end
41
63
 
42
- def find_next_day
43
- if !started?
44
- started!
45
- date = @date
46
- else
47
- date = @date + @options[:interval].days
48
- end
64
+ def next_day
65
+ date = @date
66
+ date = date + @options[:interval].days if inited? || @options[:interval] > 1
49
67
 
50
68
  date.to_date
51
69
  end
52
70
 
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
71
+ def next_week
72
+ date = @date
73
+
74
+ if inited?
75
+ date = date + @options[:interval].weeks
76
+ elsif date.wday != @options[:on]
77
+ date = date.next until @options[:on] == date.wday && date > @options[:starts]
78
+ date = date + (@options[:interval] - 1).weeks
63
79
  end
64
80
 
65
81
  date.to_date
66
82
  end
67
83
 
68
- def find_next_month
69
- if !started?
70
- started!
71
- date = @date
84
+ def next_month
85
+ date = @date
86
+
87
+ if inited?
88
+ date = advance_to_month(date)
72
89
  else
73
- date = @date.beginning_of_month + @options[:interval].months
90
+ day = [options[:on], Time.days_in_month(date.month, date.year)].min
91
+ date = Date.new(date.year, date.month, day)
92
+ date = advance_to_month(date) if @date.day > day
74
93
  end
75
-
76
- day = [@options[:on], Time.days_in_month(date.month, date.year)].min
77
- date = Date.new(date.year, date.month, day)
94
+
78
95
  date.to_date
79
96
  end
80
97
 
81
- def find_next_year
82
- if !started?
83
- started!
84
- date = @date
98
+ def advance_to_month(date)
99
+ date = date.beginning_of_month + @options[:interval].months
100
+ day = [options[:on], Time.days_in_month(date.month, date.year)].min
101
+
102
+ if date.day != day && date.day < day
103
+ date = date.to_date.next until date.day == day
104
+ end
105
+
106
+ date
107
+ end
108
+
109
+ def next_year
110
+ date = @date
111
+
112
+ if inited?
113
+ date = advance_to_year(date)
85
114
  else
86
- date = @date.beginning_of_month + @options[:interval].years
115
+ day = [options[:on].last, Time.days_in_month(options[:on].first, date.year)].min
116
+ date = Date.new(date.year, options[:on].first, day)
117
+ date = advance_to_year(date) if @date.month > date.month || @options[:on].last < @date.day
87
118
  end
88
119
 
120
+ date.to_date
121
+ end
122
+
123
+ def advance_to_year(date)
124
+ date = date.beginning_of_month + @options[:interval].years
89
125
  day = [Time.days_in_month(@options[:on].first, date.year), @options[:on].last].min
90
126
  year = date.year
91
-
92
- year += 1 if @options[:on].first < date.month
93
-
94
- Date.new(year, @options[:on].first, day)
127
+
128
+ date = Date.new(year, @options[:on].first, day)
95
129
  end
96
- end
130
+ end
data/recurrence.gemspec CHANGED
@@ -2,28 +2,26 @@
2
2
  # RUN : 'rake gem:update_gemspec'
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.date = "Mon Sep 22 21:17:41 -0300 2008"
6
5
  s.authors = ["Nando Vieira"]
6
+ s.require_paths = ["lib"]
7
7
  s.required_rubygems_version = ">= 0"
8
- s.version = "0.0.3"
8
+ s.has_rdoc = false
9
9
  s.files = ["init.rb",
10
10
  "Rakefile",
11
11
  "recurrence.gemspec",
12
12
  "History.txt",
13
13
  "License.txt",
14
14
  "README.markdown",
15
- "TODO.txt",
16
15
  "lib/recurrence",
17
16
  "lib/recurrence/base.rb",
18
17
  "lib/recurrence/event.rb",
19
18
  "lib/recurrence.rb"]
20
- s.has_rdoc = false
21
19
  s.email = ["fnando.vieira@gmail.com"]
22
- s.name = "recurrence"
23
- s.bindir = "bin"
20
+ s.version = "0.0.6"
24
21
  s.homepage = "http://github.com/fnando/recurrence"
22
+ s.name = "recurrence"
25
23
  s.summary = "A simples library that handles recurring events"
26
24
  s.add_dependency "rubigen", ">= 0"
27
- s.add_dependency "activesupport", ">= 0"
28
- s.require_paths = ["lib"]
25
+ s.add_dependency "activesupport", ">= 2.1.1"
26
+ s.bindir = "bin"
29
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fnando-recurrence
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-22 17:17:41 -07:00
12
+ date: 2008-12-22 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -28,7 +28,7 @@ dependencies:
28
28
  requirements:
29
29
  - - ">="
30
30
  - !ruby/object:Gem::Version
31
- version: "0"
31
+ version: 2.1.1
32
32
  version:
33
33
  description:
34
34
  email:
@@ -46,7 +46,6 @@ files:
46
46
  - History.txt
47
47
  - License.txt
48
48
  - README.markdown
49
- - TODO.txt
50
49
  - lib/recurrence
51
50
  - lib/recurrence/base.rb
52
51
  - lib/recurrence/event.rb
data/TODO.txt DELETED
File without changes