ri_cal 0.8.2 → 0.8.4

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.
Files changed (53) hide show
  1. data/History.txt +10 -0
  2. data/Manifest.txt +23 -3
  3. data/lib/ri_cal.rb +28 -16
  4. data/lib/ri_cal/component.rb +11 -7
  5. data/lib/ri_cal/component/alarm.rb +0 -2
  6. data/lib/ri_cal/component/calendar.rb +0 -2
  7. data/lib/ri_cal/component/event.rb +0 -2
  8. data/lib/ri_cal/component/freebusy.rb +0 -2
  9. data/lib/ri_cal/component/journal.rb +0 -3
  10. data/lib/ri_cal/component/non_standard.rb +0 -2
  11. data/lib/ri_cal/component/timezone.rb +5 -5
  12. data/lib/ri_cal/component/timezone/timezone_period.rb +0 -2
  13. data/lib/ri_cal/component/todo.rb +0 -2
  14. data/lib/ri_cal/core_extensions.rb +8 -3
  15. data/lib/ri_cal/core_extensions/array.rb +1 -1
  16. data/lib/ri_cal/core_extensions/date.rb +3 -3
  17. data/lib/ri_cal/core_extensions/date_time.rb +4 -4
  18. data/lib/ri_cal/core_extensions/object.rb +1 -1
  19. data/lib/ri_cal/core_extensions/string.rb +1 -1
  20. data/lib/ri_cal/core_extensions/time.rb +5 -4
  21. data/lib/ri_cal/fast_date_time.rb +1 -1
  22. data/lib/ri_cal/{invalid_timezone_identifer.rb → invalid_timezone_identifier.rb} +0 -0
  23. data/lib/ri_cal/properties.rb +12 -0
  24. data/lib/ri_cal/property_value.rb +14 -5
  25. data/lib/ri_cal/property_value/duration.rb +1 -1
  26. data/lib/ri_cal/property_value/recurrence_rule.rb +13 -4
  27. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +16 -13
  28. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +1 -1
  29. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +134 -0
  30. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_day_incrementer.rb +82 -0
  31. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
  32. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
  33. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
  34. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
  35. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +34 -0
  36. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
  37. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +65 -0
  38. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
  39. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
  40. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +71 -0
  41. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
  42. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +96 -0
  43. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
  44. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
  45. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +39 -0
  46. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
  47. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
  48. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
  49. data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
  50. data/ri_cal.gemspec +3 -3
  51. metadata +25 -5
  52. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +0 -793
  53. data/sample_ical_files/from_ical_dot_app/test1.ics +0 -38
@@ -17,7 +17,7 @@ module RiCal
17
17
  @setpos_list = setpos_list
18
18
  @setpos = 1
19
19
  @next_occurrence_count = 0
20
- @incrementer = YearlyIncrementer.from_rrule(recurrence_rule, start_time)
20
+ @incrementer = recurrence_rule.incrementer_from_start_time(start_time)
21
21
  end
22
22
 
23
23
  def self.for(recurrence_rule, component, setpos_list) # :nodoc:
@@ -0,0 +1,134 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+
8
+ attr_accessor :sub_cycle_incrementer, :current_occurrence, :outer_range
9
+ attr_accessor :outer_incrementers
10
+ attr_accessor :contains_daily_incrementer, :contains_weeknum_incrementer
11
+ attr_reader :leaf_iterator
12
+ parent_path = "ri_cal/property_value/recurrence_rule/occurrence_incrementer"
13
+
14
+ autoload :ByDayIncrementer, "#{parent_path}/by_day_incrementer.rb"
15
+ autoload :ByHourIncrementer, "#{parent_path}/by_hour_incrementer.rb"
16
+ autoload :ByMinuteIncrementer, "#{parent_path}/by_minute_incrementer.rb"
17
+ autoload :ByMonthIncrementer, "#{parent_path}/by_month_incrementer.rb"
18
+ autoload :ByMonthdayIncrementer, "#{parent_path}/by_monthday_incrementer.rb"
19
+ autoload :ByNumberedDayIncrementer, "#{parent_path}/by_numbered_day_incrementer.rb"
20
+ autoload :BySecondIncrementer, "#{parent_path}/by_second_incrementer.rb"
21
+ autoload :ByYeardayIncrementer, "#{parent_path}/by_yearday_incrementer.rb"
22
+ autoload :ByWeekNoIncrementer, "#{parent_path}/by_weekno_incrementer.rb"
23
+ autoload :DailyIncrementer, "#{parent_path}/daily_incrementer.rb"
24
+ autoload :FrequencyIncrementer, "#{parent_path}/frequency_incrementer.rb"
25
+ autoload :HourlyIncrementer, "#{parent_path}/hourly_incrementer.rb"
26
+ autoload :ListIncrementer, "#{parent_path}/list_incrementer.rb"
27
+ autoload :MinutelyIncrementer, "#{parent_path}/minutely_incrementer.rb"
28
+ autoload :MonthlyIncrementer, "#{parent_path}/monthly_incrementer.rb"
29
+ autoload :NullSubCycleIncrementer, "#{parent_path}/null_sub_cycle_incrementer.rb"
30
+ autoload :SecondlyIncrementer, "#{parent_path}/secondly_incrementer.rb"
31
+ autoload :WeeklyIncrementer, "#{parent_path}/weekly_incrementer.rb"
32
+ autoload :YearlyIncrementer, "#{parent_path}/yearly_incrementer.rb"
33
+
34
+ include RecurrenceRule::TimeManipulation
35
+
36
+ def initialize(rrule, sub_cycle_incrementer)
37
+ self.sub_cycle_incrementer = sub_cycle_incrementer
38
+ @outermost = true
39
+ self.outer_incrementers = []
40
+ if sub_cycle_incrementer
41
+ self.contains_daily_incrementer = sub_cycle_incrementer.daily_incrementer? ||
42
+ sub_cycle_incrementer.contains_daily_incrementer?
43
+ self.contains_weeknum_incrementer = sub_cycle_incrementer.weeknum_incrementer?||
44
+ sub_cycle_incrementer.contains_weeknum_incrementer?
45
+ sub_cycle_incrementer.add_outer_incrementer(self)
46
+ else
47
+ self.sub_cycle_incrementer = NullSubCycleIncrementer
48
+ end
49
+ end
50
+
51
+ def self.from_rrule(recurrence_rule, start_time)
52
+ YearlyIncrementer.from_rrule(recurrence_rule, start_time)
53
+ end
54
+
55
+ def add_outer_incrementer(incrementer)
56
+ @outermost = false
57
+ self.outer_incrementers << incrementer
58
+ sub_cycle_incrementer.add_outer_incrementer(incrementer)
59
+ end
60
+
61
+ def outermost?
62
+ @outermost
63
+ end
64
+
65
+ def to_s
66
+ if sub_cycle_incrementer
67
+ "#{self.short_name}->#{sub_cycle_incrementer}"
68
+ else
69
+ self.short_name
70
+ end
71
+ end
72
+
73
+ def short_name
74
+ @short_name ||= self.class.name.split("::").last
75
+ end
76
+
77
+ # Return the next time after previous_occurrence generated by this incrementer
78
+ # But the occurrence is outside the current cycle of any outer incrementer(s) return
79
+ # nil which will cause the outer incrementer to step to its next cycle.
80
+ def next_time(previous_occurrence)
81
+ if current_occurrence
82
+ sub_occurrence = sub_cycle_incrementer.next_time(previous_occurrence)
83
+ else #first time
84
+ sub_occurrence = sub_cycle_incrementer.first_sub_occurrence(previous_occurrence, update_cycle_range(previous_occurrence))
85
+ end
86
+ if sub_occurrence
87
+ candidate = sub_occurrence
88
+ else
89
+ candidate = next_cycle(previous_occurrence)
90
+ end
91
+ if in_outer_cycle?(candidate)
92
+ candidate
93
+ else
94
+ nil
95
+ end
96
+ end
97
+
98
+ def update_cycle_range(date_time)
99
+ self.current_occurrence = date_time
100
+ (date_time..end_of_occurrence(date_time))
101
+ end
102
+
103
+ def in_outer_cycle?(candidate)
104
+ candidate && (outer_range.nil? || (outer_range.first <= candidate && outer_range.last >= candidate))
105
+ end
106
+
107
+ def first_sub_occurrence(previous_occurrence, outer_cycle_range)
108
+ first_within_outer_cycle(previous_occurrence, outer_cycle_range)
109
+ end
110
+
111
+ # Advance to the next cycle, if the result is within the current cycles of all outer incrementers
112
+ def next_cycle(previous_occurrence)
113
+ raise "next_cycle is a subclass responsibility"
114
+ end
115
+
116
+ def contains_daily_incrementer?
117
+ @contains_daily_incrementer
118
+ end
119
+
120
+ def daily_incrementer?
121
+ false
122
+ end
123
+
124
+ def contains_weeknum_incrementer?
125
+ @contains_weeknum_incrementer
126
+ end
127
+
128
+ def weeknum_incrementer?
129
+ false
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,82 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class ByDayIncrementer < ListIncrementer #:nodoc:
8
+
9
+ def initialize(rrule, list, by_monthday_list, by_yearday_list, parent)
10
+ super(rrule, list, parent)
11
+ @monthday_filters = by_monthday_list
12
+ @yearday_filters = by_yearday_list
13
+ @by_day_scope = rrule.by_day_scope
14
+
15
+ case rrule.by_day_scope
16
+ when :yearly
17
+ @cycle_advance_proc = lambda {|date_time| first_day_of_year(advance_year(date_time))}
18
+ @current_proc = lambda {|date_time| same_year?(current, date_time)}
19
+ @first_day_proc = lambda {|date_time| first_day_of_year(date_time)}
20
+ when :monthly
21
+ @cycle_advance_proc = lambda {|date_time| first_day_of_month(advance_month(date_time))}
22
+ @current_proc = lambda {|date_time| same_month?(current, date_time)}
23
+ @first_day_proc = lambda {|date_time| first_day_of_month(date_time)}
24
+ when :weekly
25
+ @cycle_advance_proc = lambda {|date_time| first_day_of_week(rrule.wkst_day, advance_week(date_time))}
26
+ @current_proc = lambda {|date_time| same_week?(rrule.wkst_day, current, date_time)}
27
+ @first_day_proc = lambda {|date_time| first_day_of_week(rrule.wkst_day, date_time)}
28
+ else
29
+ raise "Invalid recurrence rule, byday needs to be scoped by month, week or year"
30
+ end
31
+ end
32
+
33
+ def self.for_rrule(rrule)
34
+ list = rrule.by_rule_list(:byday)
35
+ if list
36
+ sub_cycle_incrementer = OccurrenceIncrementer::DailyIncrementer.for_rrule(rrule)
37
+ new(rrule, list, rrule.by_rule_list(:bymonthday), rrule.by_rule_list(:byyearday), sub_cycle_incrementer)
38
+ else
39
+ OccurrenceIncrementer::ByYeardayIncrementer.for_rrule(rrule)
40
+ end
41
+ end
42
+
43
+ def daily_incrementer?
44
+ true
45
+ end
46
+
47
+ def start_of_cycle(date_time)
48
+ @first_day_proc.call(date_time)
49
+ end
50
+
51
+ def occurrences_for(date_time)
52
+ first_day = start_of_cycle(date_time)
53
+ result = list.map {|recurring_day| recurring_day.matches_for(first_day)}.flatten.uniq.sort
54
+ if @monthday_filters
55
+ result = result.select {|occurrence| @monthday_filters.any? {|recurring_day| recurring_day.include?(occurrence)}}
56
+ end
57
+ if @yearday_filters
58
+ result = result.select {|occurrence| @yearday_filters.any? {|recurring_day| recurring_day.include?(occurrence)}}
59
+ end
60
+ result
61
+ end
62
+
63
+ def candidate_acceptible?(candidate)
64
+ list.any? {|recurring_day| recurring_day.include?(candidate)}
65
+ end
66
+
67
+ def varying_time_attribute
68
+ :day
69
+ end
70
+
71
+ def advance_cycle(date_time)
72
+ @cycle_advance_proc.call(date_time)
73
+ end
74
+
75
+ def end_of_occurrence(date_time)
76
+ date_time.end_of_day
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,31 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class ByHourIncrementer < ListIncrementer #:nodoc:
8
+ def self.for_rrule(rrule)
9
+ conditional_incrementer(rrule, :byhour, HourlyIncrementer)
10
+ end
11
+
12
+ def start_of_cycle(date_time)
13
+ date_time.change(:hour => 0)
14
+ end
15
+
16
+ def varying_time_attribute
17
+ :hour
18
+ end
19
+
20
+ def advance_cycle(date_time)
21
+ first_hour_of_day(advance_day(date_time))
22
+ end
23
+
24
+ def end_of_occurrence(date_time)
25
+ date_time.end_of_hour
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class ByMinuteIncrementer < ListIncrementer #:nodoc:
8
+ def self.for_rrule(rrule)
9
+ conditional_incrementer(rrule, :byminute, MinutelyIncrementer)
10
+ end
11
+
12
+ def advance_cycle(date_time)
13
+ date_time.advance(:hours => 1).start_of_hour
14
+ end
15
+
16
+ def start_of_cycle(date_time)
17
+ date_time.change(:min => 0)
18
+ end
19
+
20
+ def end_of_occurrence(date_time)
21
+ date_time.end_of_minute
22
+ end
23
+
24
+ def varying_time_attribute
25
+ :min
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class ByMonthIncrementer < ListIncrementer #:nodoc:
8
+
9
+ def self.for_rrule(rrule)
10
+ conditional_incrementer(rrule, :bymonth, MonthlyIncrementer)
11
+ end
12
+
13
+ def occurrences_for(date_time)
14
+ if contains_daily_incrementer?
15
+ list.map {|value| date_time.change(:month => value, :day => 1)}
16
+ else
17
+ list.map {|value| date_time.in_month(value)}
18
+ end
19
+ end
20
+
21
+ def range_advance(date_time)
22
+ advance_year(date_time)
23
+ end
24
+
25
+ def start_of_cycle(date_time)
26
+ if contains_daily_incrementer?
27
+ date_time.change(:month => 1, :day => 1)
28
+ else
29
+ date_time.change(:month => 1)
30
+ end
31
+ end
32
+
33
+ def varying_time_attribute
34
+ :month
35
+ end
36
+
37
+ def advance_cycle(date_time)
38
+ if contains_daily_incrementer?
39
+ first_day_of_year(advance_year(date_time))
40
+ else
41
+ advance_year(date_time).change(:month => 1)
42
+ end
43
+ end
44
+
45
+ def end_of_occurrence(date_time)
46
+ date_time.end_of_month
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class ByMonthdayIncrementer < ByNumberedDayIncrementer #:nodoc:
8
+ def self.for_rrule(rrule)
9
+ conditional_incrementer(rrule, :bymonthday, DailyIncrementer)
10
+ end
11
+
12
+ def scope_of(date_time)
13
+ date_time.month
14
+ end
15
+
16
+ def start_of_cycle(date_time)
17
+ date_time.change(:day => 1)
18
+ end
19
+
20
+ def advance_cycle(date_time)
21
+ first_day_of_month(advance_month(date_time))
22
+ end
23
+
24
+ def end_of_occurrence(date_time)
25
+ date_time.end_of_day
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class ByNumberedDayIncrementer < ListIncrementer #:nodoc:
8
+
9
+ def daily_incrementer?
10
+ true
11
+ end
12
+
13
+ def occurrences_for(date_time)
14
+ if occurrences && @scoping_value == scope_of(date_time)
15
+ occurrences
16
+ else
17
+ @scoping_value = scope_of(date_time)
18
+ self.occurrences = list.map {|numbered_day| numbered_day.target_date_time_for(date_time)}.uniq.sort
19
+ occurrences
20
+ end
21
+ end
22
+
23
+ def end_of_occurrence(date_time)
24
+ date_time.end_of_day
25
+ end
26
+
27
+ def candidate_acceptible?(candidate)
28
+ list.any? {|by_part| by_part.include?(candidate)}
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,32 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceIncrementer # :nodoc:
7
+ class BySecondIncrementer < ListIncrementer #:nodoc:
8
+
9
+ def self.for_rrule(rrule)
10
+ conditional_incrementer(rrule, :bysecond, SecondlyIncrementer)
11
+ end
12
+
13
+ def varying_time_attribute
14
+ :sec
15
+ end
16
+
17
+ def start_of_cycle(date_time)
18
+ date_time.start_of_minute
19
+ end
20
+
21
+ def advance_cycle(date_time)
22
+ date_time.advance(:minutes => 1).start_of_minute
23
+ end
24
+
25
+ def end_of_occurrence(date_time)
26
+ date_time
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end