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
@@ -0,0 +1,65 @@
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 ByWeekNoIncrementer < ListIncrementer #:nodoc:
8
+ attr_reader :wkst
9
+ # include WeeklyBydayMethods
10
+
11
+ def initialize(rrule, list, sub_cycle_incrementer)
12
+ @wkst = rrule.wkst_day
13
+ super(rrule, list, sub_cycle_incrementer)
14
+ end
15
+
16
+ def self.for_rrule(rrule)
17
+ conditional_incrementer(rrule, :byweekno, WeeklyIncrementer)
18
+ end
19
+
20
+ def weeknum_incrementer?
21
+ true
22
+ end
23
+
24
+ def first_within_outer_cycle(previous_occurrence, outer_range)
25
+ new_range_start = outer_range.first
26
+ new_range_end = new_range_start.end_of_iso_year(wkst)
27
+ super(previous_occurrence, outer_range.first..new_range_end)
28
+ end
29
+
30
+ def start_of_cycle(date_time)
31
+ result = date_time.at_start_of_iso_year(wkst)
32
+ result
33
+ end
34
+
35
+ def occurrences_for(date_time)
36
+ iso_year, year_start = *date_time.iso_year_and_week_one_start(wkst)
37
+ week_one_occurrence = date_time.change(
38
+ :year => year_start.year,
39
+ :month => year_start.month,
40
+ :day => year_start.day
41
+ )
42
+ weeks_in_year_plus_one = week_one_occurrence.iso_weeks_in_year(wkst)
43
+ weeks = list.map {|recurring_weeknum|
44
+ wk_num = recurring_weeknum.ordinal
45
+ (wk_num > 0) ? wk_num : weeks_in_year_plus_one + wk_num
46
+ }.uniq.sort
47
+ weeks.map {|wk_num| week_one_occurrence.advance(:days => (wk_num - 1) * 7)}
48
+ end
49
+
50
+ def candidate_acceptible?(candidate)
51
+ list.include?(candidate.iso_week_num(wkst))
52
+ end
53
+
54
+ def advance_cycle(date_time)
55
+ date_time.at_start_of_next_iso_year(wkst)
56
+ end
57
+
58
+ def end_of_occurrence(date_time)
59
+ date_time.end_of_week_with_wkst(wkst)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ 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 ByYeardayIncrementer < ByNumberedDayIncrementer #:nodoc:
8
+ def self.for_rrule(rrule)
9
+ conditional_incrementer(rrule, :byyearday, ByMonthdayIncrementer)
10
+ end
11
+
12
+ def start_of_cycle(date_time)
13
+ date_time.change(:month => 1, :day => 1)
14
+ end
15
+
16
+ def scope_of(date_time)
17
+ date_time.year
18
+ end
19
+
20
+ def advance_cycle(date_time)
21
+ first_day_of_year(advance_year(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,28 @@
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 DailyIncrementer < FrequencyIncrementer #:nodoc:
8
+
9
+ def self.for_rrule(rrule)
10
+ conditional_incrementer(rrule, "DAILY", OccurrenceIncrementer::ByHourIncrementer)
11
+ end
12
+
13
+ def daily_incrementer?
14
+ true
15
+ end
16
+
17
+ def advance_what
18
+ :days
19
+ end
20
+
21
+ def end_of_occurrence(date_time)
22
+ date_time.end_of_day
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,71 @@
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
+ # A FrequenceIncrementer represents the xxxLY and FREQ parts of a recurrence rule
9
+ # A FrequenceIncrementer has a single occurrence within each cycle.
10
+ class FrequencyIncrementer < OccurrenceIncrementer #:nodoc:
11
+ attr_accessor :interval, :outer_occurrence, :skip_increment
12
+
13
+ alias_method :cycle_start, :current_occurrence
14
+
15
+ def initialize(rrule, sub_cycle_incrementer)
16
+ super(rrule, sub_cycle_incrementer)
17
+ self.interval = rrule.interval
18
+ end
19
+
20
+ def self.conditional_incrementer(rrule, freq_str, sub_cycle_class)
21
+ sub_cycle_incrementer = sub_cycle_class.for_rrule(rrule)
22
+ if rrule.freq == freq_str
23
+ new(rrule, sub_cycle_incrementer)
24
+ else
25
+ sub_cycle_incrementer
26
+ end
27
+ end
28
+
29
+ def multiplier
30
+ 1
31
+ end
32
+
33
+ def step(occurrence)
34
+ occurrence.advance(advance_what => (interval * multiplier))
35
+ end
36
+
37
+ def first_within_outer_cycle(previous_occurrence, outer_cycle_range)
38
+ if outer_range
39
+ first_occurrence = outer_cycle_range.first
40
+ else
41
+ first_occurrence = step(previous_occurrence)
42
+ end
43
+ self.outer_range = outer_cycle_range
44
+ sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(first_occurrence))
45
+ end
46
+
47
+ # Advance to the next occurrence, if the result is within the current cycles of all outer incrementers
48
+ def next_cycle(previous_occurrence)
49
+ if current_occurrence
50
+ candidate = sub_cycle_incrementer.cycle_adjust(step(current_occurrence))
51
+ else
52
+ candidate = step(previous_occurrence)
53
+ end
54
+ if outermost?
55
+ sub_occurrence = sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
56
+ until sub_occurrence
57
+ candidate = sub_cycle_incrementer.cycle_adjust(step(candidate))
58
+ sub_occurrence = sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
59
+ end
60
+ sub_occurrence
61
+ elsif in_outer_cycle?(candidate)
62
+ sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
63
+ else
64
+ nil
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,23 @@
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 HourlyIncrementer < FrequencyIncrementer #:nodoc:
8
+ def self.for_rrule(rrule)
9
+ conditional_incrementer(rrule, "HOURLY", ByMinuteIncrementer)
10
+ end
11
+
12
+ def advance_what
13
+ :hours
14
+ end
15
+
16
+ def end_of_occurrence(date_time)
17
+ date_time.end_of_hour
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,96 @@
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
+ # A ListIncrementer represents a byxxx part of a recurrence rule
9
+ # It contains a list of simple values or recurring values
10
+ # It keeps a collection of occurrences within a given range called a cycle
11
+ # When the collection of occurrences is exhausted it is refreshed if there is no
12
+ # outer incrementer, or if a new cycle would start in the current cycle of the outer incrementers.
13
+ class ListIncrementer < OccurrenceIncrementer #:nodoc:
14
+ attr_accessor :occurrences, :list, :outer_occurrence, :cycle_start
15
+
16
+ def initialize(rrule, list, sub_cycle_incrementer)
17
+ super(rrule, sub_cycle_incrementer)
18
+ self.list = list
19
+ end
20
+
21
+ def self.conditional_incrementer(rrule, by_part, sub_cycle_class)
22
+ sub_cycle_incrementer = sub_cycle_class.for_rrule(rrule)
23
+ list = rrule.by_rule_list(by_part)
24
+ if list
25
+ new(rrule, list, sub_cycle_incrementer)
26
+ else
27
+ sub_cycle_incrementer
28
+ end
29
+ end
30
+
31
+ # Advance to the next occurrence, if the result is within the current cycles of all outer incrementers
32
+ def next_cycle(previous_occurrence)
33
+ unless occurrences
34
+ self.occurrences = occurrences_for(previous_occurrence)
35
+ end
36
+ candidate = next_candidate(previous_occurrence)
37
+ if candidate
38
+ sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
39
+ else
40
+ nil
41
+ end
42
+ end
43
+
44
+ def first_within_outer_cycle(previous_occurrence, outer_range)
45
+ self.outer_range = outer_range
46
+ self.occurrences = occurrences_within(outer_range)
47
+ occurrences.each { |occurrence|
48
+ sub = sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(occurrence))
49
+ return sub if sub && sub > previous_occurrence
50
+ }
51
+ nil
52
+ end
53
+
54
+ def next_candidate(date_time)
55
+ candidate = next_in_list(date_time)
56
+ if outermost?
57
+ while candidate.nil?
58
+ get_next_occurrences
59
+ candidate = next_in_list(date_time)
60
+ end
61
+ end
62
+ candidate
63
+ end
64
+
65
+ def next_in_list(date_time)
66
+ occurrences.find {|occurrence| occurrence > date_time}
67
+ end
68
+
69
+ def get_next_occurrences
70
+ adv_cycle = advance_cycle(start_of_cycle(occurrences.first))
71
+ self.occurrences = occurrences_for(adv_cycle)
72
+ end
73
+
74
+ def cycle_adjust(date_time)
75
+ sub_cycle_incrementer.cycle_adjust(start_of_cycle(date_time))
76
+ end
77
+
78
+ def occurrences_for(date_time)
79
+ list.map {|value| date_time.change(varying_time_attribute => value)}
80
+ end
81
+
82
+ def occurrences_within(date_time_range)
83
+ result = []
84
+ date_time = date_time_range.first
85
+ while date_time <= date_time_range.last
86
+ result << occurrences_for(date_time)
87
+ date_time = advance_cycle(date_time)
88
+ end
89
+ result.flatten
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+
@@ -0,0 +1,23 @@
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 MinutelyIncrementer < FrequencyIncrementer #:nodoc:
8
+ def self.for_rrule(rrule)
9
+ conditional_incrementer(rrule, "MINUTELY", BySecondIncrementer)
10
+ end
11
+
12
+ def advance_what
13
+ :minutes
14
+ end
15
+
16
+ def end_of_occurrence(date_time)
17
+ date_time.end_of_minute
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
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 MonthlyIncrementer < FrequencyIncrementer #:nodoc:
8
+
9
+ def self.for_rrule(rrule)
10
+ conditional_incrementer(rrule, "MONTHLY", ByWeekNoIncrementer)
11
+ end
12
+
13
+ def advance_what
14
+ :months
15
+ end
16
+
17
+ def step(date_time)
18
+ if contains_daily_incrementer?
19
+ result = super(date_time).change(:day => 1)
20
+ result
21
+ else
22
+ super(date_time)
23
+ end
24
+ end
25
+
26
+ def end_of_occurrence(date_time)
27
+ date_time.end_of_month
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ class OccurrenceIncrementer # :nodoc:
5
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ class NullSubCycleIncrementer #:nodoc:
8
+ def self.next_time(previous)
9
+ nil
10
+ end
11
+
12
+ def self.add_outer_incrementer(incrementer)
13
+ end
14
+
15
+ def self.first_within_outer_cycle(previous_occurrence, outer_cycle_range)
16
+ outer_cycle_range.first
17
+ end
18
+
19
+ def self.first_sub_occurrence(previous_occurrence, outer_cycle_range)
20
+ nil
21
+ end
22
+
23
+ def self.cycle_adjust(date_time)
24
+ date_time
25
+ end
26
+
27
+ def self.to_s
28
+ "NULL-INCR"
29
+ end
30
+
31
+ def inspect
32
+ to_s
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,28 @@
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 SecondlyIncrementer < FrequencyIncrementer #:nodoc:
8
+
9
+ def self.for_rrule(rrule)
10
+ if rrule.freq == "SECONDLY"
11
+ new(rrule, nil)
12
+ else
13
+ nil
14
+ end
15
+ end
16
+
17
+ def advance_what
18
+ :seconds
19
+ end
20
+
21
+ def end_of_occurrence(date_time)
22
+ date_time
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end