fnando-recurrence 0.0.3 → 0.0.6

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