ri_cal 0.8.2 → 0.8.4

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