Permalink
Browse files

Moved inner classes inside RecurrenceRule to separate files

  • Loading branch information...
1 parent 16df4b4 commit 046e17936678e58bf5b988e85c9a03025489f697 @rubyredrick committed Feb 24, 2009
@@ -1,249 +1,11 @@
-require 'rubygems'
+Dir[File.dirname(__FILE__) + "/recurrence_rule/*.rb"].sort.each do |path|
+ require path
+end
+
module RiCal
class PropertyValue
class RecurrenceRule < PropertyValue
- class Enumerator
- attr_accessor :start_time, :duration, :next_time, :recurrence_rule
- attr_reader :reset_second, :reset_minute, :reset_hour, :reset_day, :reset_month
- def initialize(recurrence_rule, component, setpos_list)
- self.recurrence_rule = recurrence_rule
- self.start_time = component.default_start_time
- self.duration = component.default_duration
- self.next_time = recurrence_rule.adjust_start(self.start_time)
- @count = 0
- @setpos_list = setpos_list
- @setpos = 1
- @reset_second = recurrence_rule.reset_second || start_time.sec
- @reset_minute = recurrence_rule.reset_minute || start_time.min
- @reset_hour = recurrence_rule.reset_hour || start_time.hour
- @reset_day = recurrence_rule.reset_day || start_time.day
- @reset_month = recurrence_rule.reset_month || start_time.month
- @next_occurrence_count = 0
- end
-
- def result_hash(date_time_value)
- {:start => date_time_value, :end => nil}
- end
-
- def result_passes_setpos_filter?(result)
- result_setpos = @setpos
- if recurrence_rule.in_same_set?(result, next_time)
- @setpos += 1
- else
- @setpos = 1
- end
- if (result == start_time) || (result > start_time && @setpos_list.include?(result_setpos))
- return true
- else
- return false
- end
- end
-
- def result_passes_filters?(result)
- if @setpos_list
- result_passes_setpos_filter?(result)
- else
- result >= start_time
- end
- end
-
- def next_occurrence
- while true
- @next_occurrence_count += 1
- result = next_time
- self.next_time = recurrence_rule.advance(result, self)
- if result_passes_filters?(result)
- @count += 1
- return recurrence_rule.exhausted?(@count, result) ? nil : result_hash(result)
- end
- end
- end
- end
-
- class NegativeSetposEnumerator < Enumerator
-
- def initialize(recurrence_rule, component, setpos_list)
- super
- @current_set = []
- @valids = []
- end
-
- def next_occurrence
- while true
- result = advance
- if result >= start_time
- @count += 1
- return recurrence_rule.exhausted?(@count, result) ? nil : result_hash(result)
- end
- end
- end
-
- def advance
- if @valids.empty?
- fill_set
- @valids = @setpos_list.map {|sp| sp < 0 ? @current_set.length + sp : sp - 1}
- current_time_index = @current_set.index(@start_time)
- if current_time_index
- @valids << current_time_index
- end
- @valids = @valids.uniq.sort
- end
- @current_set[@valids.shift]
- end
-
-
- def fill_set
- @current_set = [next_time]
- while true
- self.next_time = recurrence_rule.advance(next_time, self)
- if recurrence_rule.in_same_set?(@current_set.last, next_time)
- @current_set << next_time
- else
- return
- end
- end
- end
- end
-
- def Enumerator.for(recurrence_rule, component, setpos_list)
- if !setpos_list || setpos_list.all? {|setpos| setpos > 1}
- self.new(recurrence_rule, component, setpos_list)
- else
- NegativeSetposEnumerator.new(recurrence_rule, start_time, end_time, setpos_list)
- end
- end
-
- # Instances of RecurringDay are used to represent values in BYDAY recurrence rule parts
- #
- class RecurringDay
-
- DayNames = %w{SU MO TU WE TH FR SA} unless defined? DayNames
- day_nums = {}
- unless defined? DayNums
- DayNames.each_with_index { |name, i| day_nums[name] = i }
- DayNums = day_nums
- end
-
- attr_reader :source
- def initialize(source, rrule)
- @source = source
- @rrule = rrule
- wd_match = source.match(/([+-]?\d*)(SU|MO|TU|WE|TH|FR|SA)/)
- if wd_match
- @day, @ordinal = wd_match[2], wd_match[1]
- end
- end
-
- def valid?
- !@day.nil?
- end
-
- def ==(another)
- self.class === another && to_a = another.to_a
- end
-
- def to_a
- [@day, @ordinal]
- end
-
- def to_s
- "#{@ordinal}#{@day}"
- end
-
- def ordinal_match(date_or_time)
- if @ordinal == ""
- true
- else
- n = @ordinal.to_i
- if @rrule.freq == "YEARLY"
- date_or_time.nth_wday_in_year?(n, DayNums[@day])
- else
- date_or_time.nth_wday_in_month?(n, DayNums[@day])
- end
- end
- end
-
- # Determine if a particular date, time, or date_time is included in the recurrence
- def include?(date_or_time)
- date_or_time.wday == DayNums[@day] && ordinal_match(date_or_time)
- end
- end
-
- class RecurringNumberedSpan
- attr_reader :source
- def initialize(source)
- @source = source
- end
-
- def valid?
- (1..last).include?(source) || (-last..-1).include?(source)
- end
-
- def ==(another)
- self.class == another.class && source == another.source
- end
-
- def to_s
- source.to_s
- end
- end
-
- # Instances of RecurringMonthDay represent BYMONTHDAY parts in recurrence rules
- class RecurringMonthDay < RecurringNumberedSpan
-
- def last
- 31
- end
-
- def target_for(date_or_time)
- if @source > 0
- @source
- else
- date_or_time.days_in_month + @source + 1
- end
- end
-
- def include?(date_or_time)
- date_or_time.mday == target_for(date_or_time)
- end
- end
-
- class RecurringYearDay < RecurringNumberedSpan
-
- def last
- 366
- end
-
- def leap_year?(year)
- year % 4 == 0 && (year % 400 == 0 || year % 100 != 0)
- end
-
-
- def length_of_year(year)
- leap_year?(year) ? 366 : 365
- end
-
- def include?(date_or_time)
- if @source > 0
- target = @source
- else
- target = length_of_year(date_or_time.year) + @source + 1
- end
- date_or_time.yday == target
- end
- end
-
- class RecurringNumberedWeek < RecurringNumberedSpan
- def last
- 53
- end
-
- def include?(date_or_time, wkst=1)
- date_or_time.iso_week_num(wkst) == @source
- end
- end
-
attr_reader :count, :until
def initialize(value_hash)
@@ -456,6 +218,14 @@ def to_ical
result << "WKST=#{wkst}" unless wkst == "MO"
result.join(";")
end
+
+ def Enumerator.for(recurrence_rule, component, setpos_list)
+ if !setpos_list || setpos_list.all? {|setpos| setpos > 1}
+ self.new(recurrence_rule, component, setpos_list)
+ else
+ NegativeSetposEnumerator.new(recurrence_rule, start_time, end_time, setpos_list)
+ end
+ end
# if the recurrence rule has a bysetpos part we need to search starting with the
# first time in the frequency period containing the start time specified by DTSTART
@@ -0,0 +1,63 @@
+module RiCal
+ class PropertyValue
+ class RecurrenceRule < PropertyValue
+ class Enumerator
+ attr_accessor :start_time, :duration, :next_time, :recurrence_rule
+ attr_reader :reset_second, :reset_minute, :reset_hour, :reset_day, :reset_month
+ def initialize(recurrence_rule, component, setpos_list)
+ self.recurrence_rule = recurrence_rule
+ self.start_time = component.default_start_time
+ self.duration = component.default_duration
+ self.next_time = recurrence_rule.adjust_start(self.start_time)
+ @count = 0
+ @setpos_list = setpos_list
+ @setpos = 1
+ @reset_second = recurrence_rule.reset_second || start_time.sec
+ @reset_minute = recurrence_rule.reset_minute || start_time.min
+ @reset_hour = recurrence_rule.reset_hour || start_time.hour
+ @reset_day = recurrence_rule.reset_day || start_time.day
+ @reset_month = recurrence_rule.reset_month || start_time.month
+ @next_occurrence_count = 0
+ end
+
+ def result_hash(date_time_value)
+ {:start => date_time_value, :end => nil}
+ end
+
+ def result_passes_setpos_filter?(result)
+ result_setpos = @setpos
+ if recurrence_rule.in_same_set?(result, next_time)
+ @setpos += 1
+ else
+ @setpos = 1
+ end
+ if (result == start_time) || (result > start_time && @setpos_list.include?(result_setpos))
+ return true
+ else
+ return false
+ end
+ end
+
+ def result_passes_filters?(result)
+ if @setpos_list
+ result_passes_setpos_filter?(result)
+ else
+ result >= start_time
+ end
+ end
+
+ def next_occurrence
+ while true
+ @next_occurrence_count += 1
+ result = next_time
+ self.next_time = recurrence_rule.advance(result, self)
+ if result_passes_filters?(result)
+ @count += 1
+ return recurrence_rule.exhausted?(@count, result) ? nil : result_hash(result)
+ end
+ end
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,51 @@
+module RiCal
+ class PropertyValue
+ class RecurrenceRule < PropertyValue
+
+ class NegativeSetposEnumerator < Enumerator
+
+ def initialize(recurrence_rule, component, setpos_list)
+ super
+ @current_set = []
+ @valids = []
+ end
+
+ def next_occurrence
+ while true
+ result = advance
+ if result >= start_time
+ @count += 1
+ return recurrence_rule.exhausted?(@count, result) ? nil : result_hash(result)
+ end
+ end
+ end
+
+ def advance
+ if @valids.empty?
+ fill_set
+ @valids = @setpos_list.map {|sp| sp < 0 ? @current_set.length + sp : sp - 1}
+ current_time_index = @current_set.index(@start_time)
+ if current_time_index
+ @valids << current_time_index
+ end
+ @valids = @valids.uniq.sort
+ end
+ @current_set[@valids.shift]
+ end
+
+
+ def fill_set
+ @current_set = [next_time]
+ while true
+ self.next_time = recurrence_rule.advance(next_time, self)
+ if recurrence_rule.in_same_set?(@current_set.last, next_time)
+ @current_set << next_time
+ else
+ return
+ end
+ end
+ end
+ end
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 046e179

Please sign in to comment.