rubyredrick-ri_cal 0.0.2

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 (123) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +122 -0
  3. data/README.txt +271 -0
  4. data/Rakefile +31 -0
  5. data/bin/ri_cal +8 -0
  6. data/component_attributes/alarm.yml +10 -0
  7. data/component_attributes/calendar.yml +4 -0
  8. data/component_attributes/component_property_defs.yml +180 -0
  9. data/component_attributes/event.yml +45 -0
  10. data/component_attributes/freebusy.yml +16 -0
  11. data/component_attributes/journal.yml +35 -0
  12. data/component_attributes/timezone.yml +3 -0
  13. data/component_attributes/timezone_period.yml +11 -0
  14. data/component_attributes/todo.yml +46 -0
  15. data/copyrights.txt +2 -0
  16. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  17. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  18. data/docs/incrementers.txt +7 -0
  19. data/docs/rfc2445.pdf +0 -0
  20. data/lib/ri_cal/component/alarm.rb +22 -0
  21. data/lib/ri_cal/component/calendar.rb +199 -0
  22. data/lib/ri_cal/component/event.rb +30 -0
  23. data/lib/ri_cal/component/freebusy.rb +19 -0
  24. data/lib/ri_cal/component/journal.rb +22 -0
  25. data/lib/ri_cal/component/t_z_info_timezone.rb +124 -0
  26. data/lib/ri_cal/component/timezone/daylight_period.rb +26 -0
  27. data/lib/ri_cal/component/timezone/standard_period.rb +24 -0
  28. data/lib/ri_cal/component/timezone/timezone_period.rb +54 -0
  29. data/lib/ri_cal/component/timezone.rb +193 -0
  30. data/lib/ri_cal/component/todo.rb +26 -0
  31. data/lib/ri_cal/component.rb +224 -0
  32. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  33. data/lib/ri_cal/core_extensions/array.rb +7 -0
  34. data/lib/ri_cal/core_extensions/date/conversions.rb +27 -0
  35. data/lib/ri_cal/core_extensions/date.rb +13 -0
  36. data/lib/ri_cal/core_extensions/date_time/conversions.rb +27 -0
  37. data/lib/ri_cal/core_extensions/date_time.rb +13 -0
  38. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  39. data/lib/ri_cal/core_extensions/object.rb +8 -0
  40. data/lib/ri_cal/core_extensions/string/conversions.rb +32 -0
  41. data/lib/ri_cal/core_extensions/string.rb +8 -0
  42. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  43. data/lib/ri_cal/core_extensions/time/conversions.rb +27 -0
  44. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
  45. data/lib/ri_cal/core_extensions/time.rb +11 -0
  46. data/lib/ri_cal/core_extensions.rb +6 -0
  47. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  48. data/lib/ri_cal/occurrence_enumerator.rb +172 -0
  49. data/lib/ri_cal/parser.rb +138 -0
  50. data/lib/ri_cal/properties/alarm.rb +390 -0
  51. data/lib/ri_cal/properties/calendar.rb +164 -0
  52. data/lib/ri_cal/properties/event.rb +1526 -0
  53. data/lib/ri_cal/properties/freebusy.rb +594 -0
  54. data/lib/ri_cal/properties/journal.rb +1240 -0
  55. data/lib/ri_cal/properties/timezone.rb +151 -0
  56. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  57. data/lib/ri_cal/properties/todo.rb +1562 -0
  58. data/lib/ri_cal/property_value/array.rb +19 -0
  59. data/lib/ri_cal/property_value/cal_address.rb +12 -0
  60. data/lib/ri_cal/property_value/date.rb +119 -0
  61. data/lib/ri_cal/property_value/date_time/additive_methods.rb +43 -0
  62. data/lib/ri_cal/property_value/date_time/time_machine.rb +180 -0
  63. data/lib/ri_cal/property_value/date_time/timezone_support.rb +65 -0
  64. data/lib/ri_cal/property_value/date_time.rb +324 -0
  65. data/lib/ri_cal/property_value/duration.rb +106 -0
  66. data/lib/ri_cal/property_value/geo.rb +12 -0
  67. data/lib/ri_cal/property_value/integer.rb +13 -0
  68. data/lib/ri_cal/property_value/occurrence_list.rb +82 -0
  69. data/lib/ri_cal/property_value/period.rb +63 -0
  70. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +98 -0
  71. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +77 -0
  72. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +149 -0
  73. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +54 -0
  74. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +32 -0
  75. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +794 -0
  76. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +132 -0
  77. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +61 -0
  78. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +34 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +50 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +126 -0
  81. data/lib/ri_cal/property_value/recurrence_rule.rb +146 -0
  82. data/lib/ri_cal/property_value/text.rb +41 -0
  83. data/lib/ri_cal/property_value/uri.rb +12 -0
  84. data/lib/ri_cal/property_value/utc_offset.rb +34 -0
  85. data/lib/ri_cal/property_value.rb +110 -0
  86. data/lib/ri_cal/required_timezones.rb +56 -0
  87. data/lib/ri_cal/time_with_floating_timezone.rb +59 -0
  88. data/lib/ri_cal.rb +134 -0
  89. data/ri_cal.gemspec +47 -0
  90. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  91. data/script/console +10 -0
  92. data/script/destroy +14 -0
  93. data/script/generate +14 -0
  94. data/script/txt2html +71 -0
  95. data/spec/ri_cal/component/alarm_spec.rb +13 -0
  96. data/spec/ri_cal/component/calendar_spec.rb +55 -0
  97. data/spec/ri_cal/component/event_spec.rb +157 -0
  98. data/spec/ri_cal/component/freebusy_spec.rb +13 -0
  99. data/spec/ri_cal/component/journal_spec.rb +13 -0
  100. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +37 -0
  101. data/spec/ri_cal/component/timezone_spec.rb +155 -0
  102. data/spec/ri_cal/component/todo_spec.rb +61 -0
  103. data/spec/ri_cal/component_spec.rb +212 -0
  104. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +189 -0
  105. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +46 -0
  106. data/spec/ri_cal/occurrence_enumerator_spec.rb +218 -0
  107. data/spec/ri_cal/parser_spec.rb +304 -0
  108. data/spec/ri_cal/property_value/date_spec.rb +22 -0
  109. data/spec/ri_cal/property_value/date_time_spec.rb +448 -0
  110. data/spec/ri_cal/property_value/duration_spec.rb +80 -0
  111. data/spec/ri_cal/property_value/period_spec.rb +50 -0
  112. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +22 -0
  113. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1815 -0
  114. data/spec/ri_cal/property_value/text_spec.rb +14 -0
  115. data/spec/ri_cal/property_value/utc_offset_spec.rb +49 -0
  116. data/spec/ri_cal/property_value_spec.rb +111 -0
  117. data/spec/ri_cal/required_timezones_spec.rb +68 -0
  118. data/spec/ri_cal_spec.rb +54 -0
  119. data/spec/spec.opts +4 -0
  120. data/spec/spec_helper.rb +24 -0
  121. data/tasks/ri_cal.rake +403 -0
  122. data/tasks/spec.rake +35 -0
  123. metadata +201 -0
@@ -0,0 +1,77 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ class Enumerator # :nodoc:
8
+ # base_time gets changed everytime the time is updated by the recurrence rule's frequency
9
+ attr_accessor :start_time, :duration, :next_time, :recurrence_rule, :base_time
10
+ def initialize(recurrence_rule, component, setpos_list)
11
+ self.recurrence_rule = recurrence_rule
12
+ self.start_time = component.default_start_time
13
+ self.duration = component.default_duration
14
+ self.next_time = recurrence_rule.adjust_start(self.start_time)
15
+ self.base_time = next_time
16
+ @bounded = recurrence_rule.bounded?
17
+ @count = 0
18
+ @setpos_list = setpos_list
19
+ @setpos = 1
20
+ @next_occurrence_count = 0
21
+ @incrementer = YearlyIncrementer.from_rrule(recurrence_rule, start_time)
22
+ end
23
+
24
+ def self.for(recurrence_rule, component, setpos_list) # :nodoc:
25
+ if !setpos_list || setpos_list.all? {|setpos| setpos > 1}
26
+ self.new(recurrence_rule, component, setpos_list)
27
+ else
28
+ NegativeSetposEnumerator.new(recurrence_rule, component, setpos_list)
29
+ end
30
+ end
31
+
32
+
33
+ def bounded?
34
+ @bounded
35
+ end
36
+
37
+ def result_hash(date_time_value)
38
+ {:start => date_time_value, :end => nil}
39
+ end
40
+
41
+ def result_passes_setpos_filter?(result)
42
+ result_setpos = @setpos
43
+ if recurrence_rule.in_same_set?(result, next_time)
44
+ @setpos += 1
45
+ else
46
+ @setpos = 1
47
+ end
48
+ if (result == start_time) || (result > start_time && @setpos_list.include?(result_setpos))
49
+ return true
50
+ else
51
+ return false
52
+ end
53
+ end
54
+
55
+ def result_passes_filters?(result)
56
+ if @setpos_list
57
+ result_passes_setpos_filter?(result)
58
+ else
59
+ result >= start_time
60
+ end
61
+ end
62
+
63
+ def next_occurrence
64
+ while true
65
+ @next_occurrence_count += 1
66
+ result = next_time
67
+ self.next_time = @incrementer.next_time(result)
68
+ if result_passes_filters?(result)
69
+ @count += 1
70
+ return recurrence_rule.exhausted?(@count, result) ? nil : result_hash(result)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,149 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ module InitializationMethods # :nodoc:
8
+
9
+ attr_reader :by_day_scope
10
+
11
+ def add_to_options_hash(options_hash, key, value)
12
+ options_hash[key] = value if value
13
+ options_hash
14
+ end
15
+
16
+ def add_byrule_strings_to_options_hash(options_hash, key)
17
+ if (rules = by_list[key])
18
+ if rules.length = 1
19
+ options_hash[key] = rules.first.source
20
+ else
21
+ options_hash[key] = rules.map {|rule| rule.source}
22
+ end
23
+ end
24
+ end
25
+
26
+ def to_options_hash
27
+ options_hash = {:freq => freq, :interval => interval}
28
+ options_hash[:params] = params unless params.empty?
29
+ add_to_options_hash(options_hash, :count, @count)
30
+ add_to_options_hash(options_hash, :until, @until)
31
+ add_to_options_hash(options_hash, :interval, @interval)
32
+ [:bysecond, :byminute, :byhour, :bymonth, :bysetpos].each do |bypart|
33
+ add_to_options_hash(options_hash, bypart, by_list[bypart])
34
+ end
35
+ [:byday, :bymonthday, :byyearday, :byweekno].each do |bypart|
36
+ add_byrule_strings_to_options_hash(options_hash, bypart)
37
+ end
38
+ options_hash
39
+ end
40
+
41
+ def initialize_from_value_part(part, dup_hash) # :nodoc:
42
+ part_name, value = part.split("=")
43
+ attribute = part_name.downcase
44
+ errors << "Repeated rule part #{attribute} last occurrence was used" if dup_hash[attribute]
45
+ case attribute
46
+ when "freq"
47
+ self.freq = value
48
+ when "wkst"
49
+ self.wkst = value
50
+ when "until"
51
+ @until = PropertyValue.date_or_date_time(self, :value => value)
52
+ when "count"
53
+ @count = value.to_i
54
+ when "interval"
55
+ self.interval = value.to_i
56
+ when "bysecond", "byminute", "byhour", "bymonthday", "byyearday", "byweekno", "bymonth", "bysetpos"
57
+ send("#{attribute}=", value.split(",").map {|int| int.to_i})
58
+ when "byday"
59
+ self.byday = value.split(",")
60
+ else
61
+ errors << "Invalid rule part #{part}"
62
+ end
63
+ end
64
+
65
+ def by_list
66
+ @by_list ||= {}
67
+ end
68
+
69
+ def calc_by_day_scope
70
+ case freq
71
+ when "YEARLY"
72
+ scope = :yearly
73
+ when "MONTHLY"
74
+ scope = :monthly
75
+ when "WEEKLY"
76
+ scope = :weekly
77
+ else
78
+ scope = :daily
79
+ end
80
+ scope = :monthly if scope != :weekly && @by_list_hash[:bymonth]
81
+ scope = :weekly if scope != :daily && @by_list_hash[:byweekno]
82
+ @by_day_scope = scope
83
+ end
84
+
85
+ def bysecond=(val)
86
+ @by_list_hash[:bysecond] = val
87
+ end
88
+
89
+ def byminute=(val)
90
+ @by_list_hash[:byminute] = val
91
+ end
92
+
93
+ def byhour=(val)
94
+ @by_list_hash[:byhour] = val
95
+ end
96
+
97
+ def bymonth=(val)
98
+ @by_list_hash[:bymonth] = val
99
+ end
100
+
101
+ def bysetpos=(val)
102
+ @by_list_hash[:bysetpos] = val
103
+ end
104
+
105
+ def byday=(val)
106
+ @by_list_hash[:byday] = val
107
+ end
108
+
109
+ def bymonthday=(val)
110
+ @by_list_hash[:bymonthday] = val
111
+ end
112
+
113
+ def byyearday=(val)
114
+ @by_list_hash[:byyearday] = val
115
+ end
116
+
117
+ def byweekno=(val)
118
+ @by_list_hash[:byweekno] = val
119
+ end
120
+
121
+ def init_by_lists
122
+ [:bysecond,
123
+ :byminute,
124
+ :byhour,
125
+ :bymonth,
126
+ :bysetpos
127
+ ].each do |which|
128
+ if val = @by_list_hash[which]
129
+ by_list[which] = [val].flatten.sort
130
+ end
131
+ end
132
+ if val = @by_list_hash[:byday]
133
+ byday_scope = calc_by_day_scope
134
+ by_list[:byday] = [val].flatten.map {|day| RecurringDay.new(day, self, byday_scope)}
135
+ end
136
+ if val = @by_list_hash[:bymonthday]
137
+ by_list[:bymonthday] = [val].flatten.map {|md| RecurringMonthDay.new(md)}
138
+ end
139
+ if val = @by_list_hash[:byyearday]
140
+ by_list[:byyearday] = [val].flatten.map {|yd| RecurringYearDay.new(yd)}
141
+ end
142
+ if val = @by_list_hash[:byweekno]
143
+ by_list[:byweekno] = [val].flatten.map {|wkno| RecurringNumberedWeek.new(wkno, self)}
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,54 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ class NegativeSetposEnumerator < Enumerator # :nodoc:
8
+
9
+ def initialize(recurrence_rule, component, setpos_list)
10
+ super
11
+ @current_set = []
12
+ @valids = []
13
+ end
14
+
15
+ def next_occurrence
16
+ while true
17
+ result = advance
18
+ if result >= start_time
19
+ @count += 1
20
+ return recurrence_rule.exhausted?(@count, result) ? nil : result_hash(result)
21
+ end
22
+ end
23
+ end
24
+
25
+
26
+
27
+ def advance
28
+ if @valids.empty?
29
+ fill_set
30
+ @valids = @setpos_list.map {|sp| sp < 0 ? @current_set.length + sp : sp - 1}
31
+ current_time_index = @current_set.index(@start_time)
32
+ if current_time_index
33
+ @valids << current_time_index
34
+ end
35
+ @valids = @valids.uniq.sort
36
+ end
37
+ @current_set[@valids.shift]
38
+ end
39
+
40
+ def fill_set
41
+ @current_set = [next_time]
42
+ while true
43
+ self.next_time = @incrementer.next_time(next_time)
44
+ if recurrence_rule.in_same_set?(@current_set.last, next_time)
45
+ @current_set << next_time
46
+ else
47
+ return
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,32 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class RecurrenceRule < PropertyValue
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ class NumberedSpan # :nodoc:
8
+ attr_reader :source
9
+ def initialize(source, rule = nil)
10
+ @source = source
11
+ @rule = rule
12
+ end
13
+
14
+ def valid?
15
+ (1..last).include?(source) || (-last..-1).include?(source)
16
+ end
17
+
18
+ def ==(another)
19
+ self.class == another.class && source == another.source
20
+ end
21
+
22
+ def to_s
23
+ source.to_s
24
+ end
25
+
26
+ def ordinal
27
+ @source
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end