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,1815 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+
6
+ require 'rubygems'
7
+
8
+ FirstOfMonth = RiCal::PropertyValue::RecurrenceRule::RecurringMonthDay.new(1)
9
+ TenthOfMonth = RiCal::PropertyValue::RecurrenceRule::RecurringMonthDay.new(10)
10
+ FirstOfYear = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(1)
11
+ TenthOfYear = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(10)
12
+ SecondWeekOfYear = RiCal::PropertyValue::RecurrenceRule::RecurringNumberedWeek.new(2)
13
+ LastWeekOfYear = RiCal::PropertyValue::RecurrenceRule::RecurringNumberedWeek.new(-1)
14
+
15
+ # rfc 2445 4.3.10 p.40
16
+ describe RiCal::PropertyValue::RecurrenceRule do
17
+
18
+ describe "initialized from hash" do
19
+ it "should require a frequency" do
20
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, {})
21
+ @it.should_not be_valid
22
+ @it.errors.should include("RecurrenceRule must have a value for FREQ")
23
+ end
24
+
25
+ it "accept reject an invalid frequency" do
26
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "blort")
27
+ @it.should_not be_valid
28
+ @it.errors.should include("Invalid frequency 'blort'")
29
+ end
30
+
31
+ %w{secondly SECONDLY minutely MINUTELY hourly HOURLY daily DAILY weekly WEEKLY monthly MONTHLY
32
+ yearly YEARLY
33
+ }.each do | freq_val |
34
+ it "should accept a frequency of #{freq_val}" do
35
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => freq_val).should be_valid
36
+ end
37
+ end
38
+
39
+ it "should reject setting both until and count" do
40
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :until => Time.now, :count => 10)
41
+ @it.should_not be_valid
42
+ @it.errors.should include("COUNT and UNTIL cannot both be specified")
43
+ end
44
+
45
+ describe "interval parameter" do
46
+
47
+ # p 42
48
+ it "should default to 1" do
49
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily").interval.should == 1
50
+ end
51
+
52
+ it "should accept an explicit value" do
53
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :interval => 42).interval.should == 42
54
+ end
55
+
56
+ it "should reject a negative value" do
57
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :interval => -1)
58
+ @it.should_not be_valid
59
+ end
60
+ end
61
+
62
+ describe "bysecond parameter" do
63
+
64
+ it "should accept a single integer" do
65
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bysecond => 10)
66
+ @it.send(:by_list)[:bysecond].should == [10]
67
+ end
68
+
69
+ it "should accept an array of integers" do
70
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bysecond => [10, 20])
71
+ @it.send(:by_list)[:bysecond].should == [10, 20]
72
+ end
73
+
74
+ it "should reject invalid values" do
75
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bysecond => [-1, 0, 59, 60])
76
+ @it.should_not be_valid
77
+ @it.errors.should == ['-1 is invalid for bysecond', '60 is invalid for bysecond']
78
+ end
79
+ end
80
+
81
+ describe "byminute parameter" do
82
+
83
+ it "should accept a single integer" do
84
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byminute => 10)
85
+ @it.send(:by_list)[:byminute].should == [10]
86
+ end
87
+
88
+ it "should accept an array of integers" do
89
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byminute => [10, 20])
90
+ @it.send(:by_list)[:byminute].should == [10, 20]
91
+ end
92
+
93
+ it "should reject invalid values" do
94
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byminute => [-1, 0, 59, 60])
95
+ @it.should_not be_valid
96
+ @it.errors.should == ['-1 is invalid for byminute', '60 is invalid for byminute']
97
+ end
98
+ end
99
+
100
+ describe "byhour parameter" do
101
+
102
+ it "should accept a single integer" do
103
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byhour => 10)
104
+ @it.send(:by_list)[:byhour].should == [10]
105
+ end
106
+
107
+ it "should accept an array of integers" do
108
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byhour => [10, 12])
109
+ @it.send(:by_list)[:byhour].should == [10, 12]
110
+ end
111
+
112
+ it "should reject invalid values" do
113
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byhour => [-1, 0, 23, 24])
114
+ @it.should_not be_valid
115
+ @it.errors.should == ['-1 is invalid for byhour', '24 is invalid for byhour']
116
+ end
117
+ end
118
+
119
+ describe "byday parameter" do
120
+
121
+ def anyMonday(rule)
122
+ RiCal::PropertyValue::RecurrenceRule::RecurringDay.new("MO", rule)
123
+ end
124
+
125
+ def anyWednesday(rule)
126
+ RiCal::PropertyValue::RecurrenceRule::RecurringDay.new("WE", rule)
127
+ end
128
+
129
+
130
+ it "should accept a single value" do
131
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byday => 'MO')
132
+ @it.send(:by_list)[:byday].should == [anyMonday(@it)]
133
+ end
134
+
135
+ it "should accept an array of values" do
136
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byday => ['MO', 'WE'])
137
+ @it.send(:by_list)[:byday].should == [anyMonday(@it), anyWednesday(@it)]
138
+ end
139
+
140
+ it "should reject invalid values" do
141
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byday => ['VE'])
142
+ @it.should_not be_valid
143
+ @it.errors.should == ['"VE" is not a valid day']
144
+ end
145
+ end
146
+
147
+ describe "bymonthday parameter" do
148
+
149
+ it "should accept a single value" do
150
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonthday => 1)
151
+ @it.send(:by_list)[:bymonthday].should == [FirstOfMonth]
152
+ end
153
+
154
+ it "should accept an array of values" do
155
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonthday => [1, 10])
156
+ @it.send(:by_list)[:bymonthday].should == [FirstOfMonth, TenthOfMonth]
157
+ end
158
+
159
+ it "should reject invalid values" do
160
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonthday => [0, 32, 'VE'])
161
+ @it.should_not be_valid
162
+ @it.errors.should == ['0 is not a valid month day','32 is not a valid month day', '"VE" is not a valid month day']
163
+ end
164
+ end
165
+
166
+ describe "byyearday parameter" do
167
+
168
+ it "should accept a single value" do
169
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byyearday => 1)
170
+ @it.send(:by_list)[:byyearday].should == [FirstOfYear]
171
+ end
172
+
173
+ it "should accept an array of values" do
174
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byyearday => [1, 10])
175
+ @it.send(:by_list)[:byyearday].should == [FirstOfYear, TenthOfYear]
176
+ end
177
+
178
+ it "should reject invalid values" do
179
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byyearday => [0, 370, 'VE'])
180
+ @it.should_not be_valid
181
+ @it.errors.should == ['0 is not a valid year day', '370 is not a valid year day', '"VE" is not a valid year day']
182
+ end
183
+ end
184
+
185
+ describe "byweekno parameter" do
186
+
187
+ it "should accept a single value" do
188
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byweekno => 2)
189
+ @it.send(:by_list)[:byweekno].should == [SecondWeekOfYear]
190
+ end
191
+
192
+ it "should accept an array of values" do
193
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byweekno => [2, -1])
194
+ @it.send(:by_list)[:byweekno].should == [SecondWeekOfYear, LastWeekOfYear]
195
+ end
196
+
197
+ it "should reject invalid values" do
198
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byweekno => [0, 54, 'VE'])
199
+ @it.should_not be_valid
200
+ @it.errors.should == ['0 is not a valid week number', '54 is not a valid week number', '"VE" is not a valid week number']
201
+ end
202
+ end
203
+
204
+ describe "bymonth parameter" do
205
+
206
+ it "should accept a single integer" do
207
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => 10)
208
+ @it.send(:by_list)[:bymonth].should == [10]
209
+ end
210
+
211
+ it "should accept an array of integers" do
212
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => [10, 12])
213
+ @it.send(:by_list)[:bymonth].should == [10, 12]
214
+ end
215
+
216
+ it "should reject invalid values" do
217
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => [-1, 0, 1, 12, 13])
218
+ @it.should_not be_valid
219
+ @it.errors.should == ['-1 is invalid for bymonth', '0 is invalid for bymonth', '13 is invalid for bymonth']
220
+ end
221
+ end
222
+
223
+ describe "bysetpos parameter" do
224
+
225
+ it "should accept a single integer" do
226
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => 10, :bysetpos => 2)
227
+ @it.send(:by_list)[:bysetpos].should == [2]
228
+ end
229
+
230
+ it "should accept an array of integers" do
231
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => 10, :bysetpos => [2, 3])
232
+ @it.send(:by_list)[:bysetpos].should == [2, 3]
233
+ end
234
+
235
+ it "should reject invalid values" do
236
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => 10, :bysetpos => [-367, -366, -1, 0, 1, 366, 367])
237
+ @it.should_not be_valid
238
+ @it.errors.should == ['-367 is invalid for bysetpos', '0 is invalid for bysetpos', '367 is invalid for bysetpos']
239
+ end
240
+
241
+ it "should require another BYxxx rule part" do
242
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bysetpos => 2)
243
+ @it.should_not be_valid
244
+ @it.errors.should == ['bysetpos cannot be used without another by_xxx rule part']
245
+ end
246
+ end
247
+
248
+ describe "wkst parameter" do
249
+
250
+ it "should default to MO" do
251
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily")
252
+ @it.wkst.should == 'MO'
253
+ end
254
+
255
+ it "should accept a single string" do
256
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :wkst => 'SU')
257
+ @it.wkst.should == 'SU'
258
+ end
259
+
260
+ %w{MO TU WE TH FR SA SU}.each do |valid|
261
+ it "should accept #{valid} as a valid value" do
262
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :wkst => valid).should be_valid
263
+ end
264
+ end
265
+
266
+ it "should reject invalid values" do
267
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :wkst => "bogus")
268
+ @it.should_not be_valid
269
+ @it.errors.should == ['"bogus" is invalid for wkst']
270
+ end
271
+ end
272
+
273
+ describe "freq accessors" do
274
+ before(:each) do
275
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => 'daily')
276
+ end
277
+
278
+ it "should convert the initial value to uppercase" do
279
+ @it.freq.should == 'DAILY'
280
+ end
281
+
282
+ it "should convert the setter value to uppercase " do
283
+ @it.freq = 'weekly'
284
+ @it.freq.should == 'WEEKLY'
285
+ end
286
+
287
+ it "should not accept an invalid value" do
288
+ @it.freq = 'bogus'
289
+ @it.should_not be_valid
290
+ end
291
+ end
292
+ end
293
+
294
+ describe "initialized from parser" do
295
+
296
+ describe "from 'FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30'" do
297
+
298
+ before(:all) do
299
+ lambda {
300
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :value => 'FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30')
301
+ }.should_not raise_error
302
+ end
303
+
304
+ it "should have a frequency of yearly" do
305
+ @it.freq.should == "YEARLY"
306
+ end
307
+
308
+ it "should have an interval of 2" do
309
+ @it.interval.should == 2
310
+ end
311
+ end
312
+ end
313
+
314
+ describe "to_ical" do
315
+
316
+ it "should handle basic cases" do
317
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily").to_ical.should == "FREQ=DAILY"
318
+ end
319
+
320
+ it "should handle multiple parts" do
321
+ @it = RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :count => 10, :interval => 2).to_ical
322
+ @it.should match(/^FREQ=DAILY;/)
323
+ parts = @it.split(';')
324
+ parts.should include("COUNT=10")
325
+ parts.should include("INTERVAL=2")
326
+ end
327
+
328
+ it "should supress the default interval value" do
329
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :interval => 1).to_ical.should_not match(/INTERVAL=/)
330
+ end
331
+
332
+ it "should support the wkst value" do
333
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :wkst => 'SU').to_ical.split(";").should include("WKST=SU")
334
+ end
335
+
336
+ it "should supress the default wkst value" do
337
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :wkst => 'MO').to_ical.split(";").should_not include("WKST=SU")
338
+ end
339
+
340
+ it "should handle a scalar bysecond" do
341
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bysecond => 15).to_ical.split(";").should include("BYSECOND=15")
342
+ end
343
+
344
+ it "should handle an array bysecond" do
345
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bysecond => [15, 45]).to_ical.split(";").should include("BYSECOND=15,45")
346
+ end
347
+
348
+ it "should handle a scalar byday" do
349
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :byday => 'MO').to_ical.split(";").should include("BYDAY=MO")
350
+ end
351
+
352
+ it "should handle an array byday" do
353
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byday => ["MO", "-3SU"]).to_ical.split(";").should include("BYDAY=MO,-3SU")
354
+ end
355
+
356
+ it "should handle a scalar bymonthday" do
357
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :bymonthday => 14).to_ical.split(";").should include("BYMONTHDAY=14")
358
+ end
359
+
360
+ it "should handle an array bymonthday" do
361
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonthday => [15, -10]).to_ical.split(";").should include("BYMONTHDAY=15,-10")
362
+ end
363
+
364
+ it "should handle a scalar byyearday" do
365
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :byyearday => 14).to_ical.split(";").should include("BYYEARDAY=14")
366
+ end
367
+
368
+ it "should handle an array byyearday" do
369
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byyearday => [15, -10]).to_ical.split(";").should include("BYYEARDAY=15,-10")
370
+ end
371
+
372
+ it "should handle a scalar byweekno" do
373
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :byweekno => 14).to_ical.split(";").should include("BYWEEKNO=14")
374
+ end
375
+
376
+ it "should handle an array byyearday" do
377
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :byweekno => [15, -10]).to_ical.split(";").should include("BYWEEKNO=15,-10")
378
+ end
379
+
380
+ it "should handle a scalar bymonth" do
381
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :bymonth => 2).to_ical.split(";").should include("BYMONTH=2")
382
+ end
383
+
384
+ it "should handle an array bymonth" do
385
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :bymonth => [5, 6]).to_ical.split(";").should include("BYMONTH=5,6")
386
+ end
387
+
388
+ it "should handle a scalar bysetpos" do
389
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :byday => %w{MO TU WE TH FR}, :bysetpos => -1).to_ical.split(";").should include("BYSETPOS=-1")
390
+ end
391
+
392
+ it "should handle an array bysetpos" do
393
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "monthly", :byday => %w{MO TU WE TH FR}, :bysetpos => [2, -1]).to_ical.split(";").should include("BYSETPOS=-1,2")
394
+ end
395
+
396
+ it "should handle until as a date" do
397
+ RiCal::PropertyValue::RecurrenceRule.new(nil, :freq => "daily", :until => Date.new(2009,10,17)).to_ical.should include("UNTIL=20091017")
398
+ end
399
+ end
400
+
401
+ def ruby19_date_str_fix(string)
402
+ end
403
+
404
+ describe "#enumerator" do
405
+
406
+ def self.enumeration_spec(description, dtstart_string, tzid, rrule_string, expectation, debug=false)
407
+ if expectation.last == "..."
408
+ expectation = expectation[0..-2]
409
+ iterations = expectation.length
410
+ else
411
+ iterations = expectation.length + 1
412
+ end
413
+
414
+ describe description do
415
+ before(:each) do
416
+ RiCal.debug = debug
417
+ rrule = RiCal::PropertyValue::RecurrenceRule.new(nil, :value => rrule_string)
418
+ default_start_time = RiCal::PropertyValue::DateTime.new(nil, :value => dtstart_string, :tzid => tzid)
419
+ @enum = rrule.enumerator(mock("EventValue", :default_start_time => default_start_time, :default_duration => nil))
420
+ @expectations = (expectation.map {|str| RiCal::PropertyValue::DateTime.new(nil, :value => str.gsub(/E.T$/,''), :tzid => tzid)})
421
+ end
422
+
423
+ after(:each) do
424
+ RiCal.debug = false
425
+ end
426
+
427
+ after(:each) do
428
+ RiCal.debug = false
429
+ end
430
+
431
+ it "should produce the correct occurrences" do
432
+ actuals = []
433
+ (0..(iterations-1)).each do |i|
434
+ occurrence = @enum.next_occurrence
435
+ break if occurrence.nil?
436
+ actuals << occurrence[:start]
437
+ # This is a little strange, we do this to avoid O(n*2)
438
+ unless actuals.last == @expectations[i]
439
+ actuals.should == @expectations[0,actuals.length]
440
+ end
441
+ end
442
+ actuals.length.should == @expectations.length
443
+ end
444
+ end
445
+ end
446
+
447
+ enumeration_spec(
448
+ "Daily for 10 occurrences (RFC 2445 p 118)",
449
+ "19970902T090000",
450
+ "US-Eastern",
451
+ "FREQ=DAILY;COUNT=10",
452
+ [
453
+ "Sep 2, 1997 9:00 AM EDT",
454
+ "Sep 3, 1997 9:00 AM EDT",
455
+ "Sep 4, 1997 9:00 AM EDT",
456
+ "Sep 5, 1997 9:00 AM EDT",
457
+ "Sep 6, 1997 9:00 AM EDT",
458
+ "Sep 7, 1997 9:00 AM EDT",
459
+ "Sep 8, 1997 9:00 AM EDT",
460
+ "Sep 9, 1997 9:00 AM EDT",
461
+ "Sep 10, 1997 9:00 AM EDT",
462
+ "Sep 11, 1997 9:00 AM EDT"
463
+ ]
464
+ )
465
+
466
+ enumeration_spec(
467
+ "Daily until December 24, 1997 (RFC 2445 p 118)",
468
+ "19970902T090000",
469
+ "US-Eastern",
470
+ "FREQ=DAILY;UNTIL=19971224T000000Z",
471
+ [
472
+ "Sep 2, 1997 9:00 AM EDT",
473
+ "Sep 3, 1997 9:00 AM EDT",
474
+ "Sep 4, 1997 9:00 AM EDT",
475
+ "Sep 5, 1997 9:00 AM EDT",
476
+ "Sep 6, 1997 9:00 AM EDT",
477
+ "Sep 7, 1997 9:00 AM EDT",
478
+ "Sep 8, 1997 9:00 AM EDT",
479
+ "Sep 9, 1997 9:00 AM EDT",
480
+ "Sep 10, 1997 9:00 AM EDT",
481
+ "Sep 11, 1997 9:00 AM EDT",
482
+ "Sep 12, 1997 9:00 AM EDT",
483
+ "Sep 13, 1997 9:00 AM EDT",
484
+ "Sep 14, 1997 9:00 AM EDT",
485
+ "Sep 15, 1997 9:00 AM EDT",
486
+ "Sep 16, 1997 9:00 AM EDT",
487
+ "Sep 17, 1997 9:00 AM EDT",
488
+ "Sep 18, 1997 9:00 AM EDT",
489
+ "Sep 19, 1997 9:00 AM EDT",
490
+ "Sep 20, 1997 9:00 AM EDT",
491
+ "Sep 21, 1997 9:00 AM EDT",
492
+ "Sep 22, 1997 9:00 AM EDT",
493
+ "Sep 23, 1997 9:00 AM EDT",
494
+ "Sep 24, 1997 9:00 AM EDT",
495
+ "Sep 25, 1997 9:00 AM EDT",
496
+ "Sep 26, 1997 9:00 AM EDT",
497
+ "Sep 27, 1997 9:00 AM EDT",
498
+ "Sep 28, 1997 9:00 AM EDT",
499
+ "Sep 29, 1997 9:00 AM EDT",
500
+ "Sep 30, 1997 9:00 AM EDT",
501
+ "Oct 1, 1997 9:00 AM EDT",
502
+ "Oct 2, 1997 9:00 AM EDT",
503
+ "Oct 3, 1997 9:00 AM EDT",
504
+ "Oct 4, 1997 9:00 AM EDT",
505
+ "Oct 5, 1997 9:00 AM EDT",
506
+ "Oct 6, 1997 9:00 AM EDT",
507
+ "Oct 7, 1997 9:00 AM EDT",
508
+ "Oct 8, 1997 9:00 AM EDT",
509
+ "Oct 9, 1997 9:00 AM EDT",
510
+ "Oct 10, 1997 9:00 AM EDT",
511
+ "Oct 11, 1997 9:00 AM EDT",
512
+ "Oct 12, 1997 9:00 AM EDT",
513
+ "Oct 13, 1997 9:00 AM EDT",
514
+ "Oct 14, 1997 9:00 AM EDT",
515
+ "Oct 15, 1997 9:00 AM EDT",
516
+ "Oct 16, 1997 9:00 AM EDT",
517
+ "Oct 17, 1997 9:00 AM EDT",
518
+ "Oct 18, 1997 9:00 AM EDT",
519
+ "Oct 19, 1997 9:00 AM EDT",
520
+ "Oct 20, 1997 9:00 AM EDT",
521
+ "Oct 21, 1997 9:00 AM EDT",
522
+ "Oct 22, 1997 9:00 AM EDT",
523
+ "Oct 23, 1997 9:00 AM EDT",
524
+ "Oct 24, 1997 9:00 AM EDT",
525
+ "Oct 25, 1997 9:00 AM EDT",
526
+ "Oct 26, 1997 9:00 AM EST",
527
+ "Oct 27, 1997 9:00 AM EST",
528
+ "Oct 28, 1997 9:00 AM EST",
529
+ "Oct 29, 1997 9:00 AM EST",
530
+ "Oct 30, 1997 9:00 AM EST",
531
+ "Oct 31, 1997 9:00 AM EST",
532
+ "Nov 01, 1997 9:00 AM EST",
533
+ "Nov 02, 1997 9:00 AM EST",
534
+ "Nov 03, 1997 9:00 AM EST",
535
+ "Nov 04, 1997 9:00 AM EST",
536
+ "Nov 05, 1997 9:00 AM EST",
537
+ "Nov 06, 1997 9:00 AM EST",
538
+ "Nov 07, 1997 9:00 AM EST",
539
+ "Nov 08, 1997 9:00 AM EST",
540
+ "Nov 09, 1997 9:00 AM EST",
541
+ "Nov 10, 1997 9:00 AM EST",
542
+ "Nov 11, 1997 9:00 AM EST",
543
+ "Nov 12, 1997 9:00 AM EST",
544
+ "Nov 13, 1997 9:00 AM EST",
545
+ "Nov 14, 1997 9:00 AM EST",
546
+ "Nov 15, 1997 9:00 AM EST",
547
+ "Nov 16, 1997 9:00 AM EST",
548
+ "Nov 17, 1997 9:00 AM EST",
549
+ "Nov 18, 1997 9:00 AM EST",
550
+ "Nov 19, 1997 9:00 AM EST",
551
+ "Nov 20, 1997 9:00 AM EST",
552
+ "Nov 21, 1997 9:00 AM EST",
553
+ "Nov 22, 1997 9:00 AM EST",
554
+ "Nov 23, 1997 9:00 AM EST",
555
+ "Nov 24, 1997 9:00 AM EST",
556
+ "Nov 25, 1997 9:00 AM EST",
557
+ "Nov 26, 1997 9:00 AM EST",
558
+ "Nov 27, 1997 9:00 AM EST",
559
+ "Nov 28, 1997 9:00 AM EST",
560
+ "Nov 29, 1997 9:00 AM EST",
561
+ "Nov 30, 1997 9:00 AM EST",
562
+ "Dec 01, 1997 9:00 AM EST",
563
+ "Dec 02, 1997 9:00 AM EST",
564
+ "Dec 03, 1997 9:00 AM EST",
565
+ "Dec 04, 1997 9:00 AM EST",
566
+ "Dec 05, 1997 9:00 AM EST",
567
+ "Dec 06, 1997 9:00 AM EST",
568
+ "Dec 07, 1997 9:00 AM EST",
569
+ "Dec 08, 1997 9:00 AM EST",
570
+ "Dec 09, 1997 9:00 AM EST",
571
+ "Dec 10, 1997 9:00 AM EST",
572
+ "Dec 11, 1997 9:00 AM EST",
573
+ "Dec 12, 1997 9:00 AM EST",
574
+ "Dec 13, 1997 9:00 AM EST",
575
+ "Dec 14, 1997 9:00 AM EST",
576
+ "Dec 15, 1997 9:00 AM EST",
577
+ "Dec 16, 1997 9:00 AM EST",
578
+ "Dec 17, 1997 9:00 AM EST",
579
+ "Dec 18, 1997 9:00 AM EST",
580
+ "Dec 19, 1997 9:00 AM EST",
581
+ "Dec 20, 1997 9:00 AM EST",
582
+ "Dec 21, 1997 9:00 AM EST",
583
+ "Dec 22, 1997 9:00 AM EST",
584
+ "Dec 23, 1997 9:00 AM EST",
585
+ ]
586
+ )
587
+
588
+ enumeration_spec(
589
+ "Every other day - forever (RFC 2445 p 118)",
590
+ "19970902T090000",
591
+ "US-Eastern",
592
+ "FREQ=DAILY;INTERVAL=2",
593
+ [
594
+ "Sep 2, 1997 9:00 AM EDT",
595
+ "Sep 4, 1997 9:00 AM EDT",
596
+ "Sep 6, 1997 9:00 AM EDT",
597
+ "Sep 8, 1997 9:00 AM EDT",
598
+ "Sep 10, 1997 9:00 AM EDT",
599
+ "Sep 12, 1997 9:00 AM EDT",
600
+ "Sep 14, 1997 9:00 AM EDT",
601
+ "Sep 16, 1997 9:00 AM EDT",
602
+ "Sep 18, 1997 9:00 AM EDT",
603
+ "Sep 20, 1997 9:00 AM EDT",
604
+ "Sep 22, 1997 9:00 AM EDT",
605
+ "Sep 24, 1997 9:00 AM EDT",
606
+ "Sep 26, 1997 9:00 AM EDT",
607
+ "Sep 28, 1997 9:00 AM EDT",
608
+ "Sep 30, 1997 9:00 AM EDT",
609
+ "Oct 2, 1997 9:00 AM EDT",
610
+ "Oct 4, 1997 9:00 AM EDT",
611
+ "Oct 6, 1997 9:00 AM EDT",
612
+ "Oct 8, 1997 9:00 AM EDT",
613
+ "Oct 10, 1997 9:00 AM EDT",
614
+ "Oct 12, 1997 9:00 AM EDT",
615
+ "Oct 14, 1997 9:00 AM EDT",
616
+ "Oct 16, 1997 9:00 AM EDT",
617
+ "Oct 18, 1997 9:00 AM EDT",
618
+ "Oct 20, 1997 9:00 AM EDT",
619
+ "Oct 22, 1997 9:00 AM EDT",
620
+ "Oct 24, 1997 9:00 AM EDT",
621
+ "Oct 26, 1997 9:00 AM EST",
622
+ "Oct 28, 1997 9:00 AM EST",
623
+ "Oct 30, 1997 9:00 AM EST",
624
+ "Nov 01, 1997 9:00 AM EST",
625
+ "Nov 03, 1997 9:00 AM EST",
626
+ "Nov 05, 1997 9:00 AM EST",
627
+ "Nov 07, 1997 9:00 AM EST",
628
+ "Nov 09, 1997 9:00 AM EST",
629
+ "Nov 11, 1997 9:00 AM EST",
630
+ "Nov 13, 1997 9:00 AM EST",
631
+ "Nov 15, 1997 9:00 AM EST",
632
+ "Nov 17, 1997 9:00 AM EST",
633
+ "Nov 19, 1997 9:00 AM EST",
634
+ "Nov 21, 1997 9:00 AM EST",
635
+ "Nov 23, 1997 9:00 AM EST",
636
+ "Nov 25, 1997 9:00 AM EST",
637
+ "Nov 27, 1997 9:00 AM EST",
638
+ "Nov 29, 1997 9:00 AM EST",
639
+ "Dec 01, 1997 9:00 AM EST",
640
+ "Dec 03, 1997 9:00 AM EST",
641
+ "..."
642
+ ]
643
+ )
644
+
645
+ enumeration_spec(
646
+ "Every 10 days, 5 occurrences (RFC 2445 p 118-19)",
647
+ "19970902T090000",
648
+ "US-Eastern",
649
+ "FREQ=DAILY;INTERVAL=10;COUNT=5",
650
+ [
651
+ "Sep 2, 1997 9:00 AM EDT",
652
+ "Sep 12, 1997 9:00 AM EDT",
653
+ "Sep 22, 1997 9:00 AM EDT",
654
+ "Oct 2, 1997 9:00 AM EDT",
655
+ "Oct 12, 1997 9:00 AM EDT"
656
+ ]
657
+ )
658
+
659
+ enumeration_spec(
660
+ "Everyday in January, for 3 years (RFC 2445 p 119)",
661
+ "19980101T090000",
662
+ "US-Eastern",
663
+ "FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1",
664
+ [
665
+ "Jan 01, 1998 9:00 AM EST",
666
+ "Jan 02, 1998 9:00 AM EST",
667
+ "Jan 03, 1998 9:00 AM EST",
668
+ "Jan 04, 1998 9:00 AM EST",
669
+ "Jan 05, 1998 9:00 AM EST",
670
+ "Jan 06, 1998 9:00 AM EST",
671
+ "Jan 07, 1998 9:00 AM EST",
672
+ "Jan 08, 1998 9:00 AM EST",
673
+ "Jan 09, 1998 9:00 AM EST",
674
+ "Jan 10, 1998 9:00 AM EST",
675
+ "Jan 11, 1998 9:00 AM EST",
676
+ "Jan 12, 1998 9:00 AM EST",
677
+ "Jan 13, 1998 9:00 AM EST",
678
+ "Jan 14, 1998 9:00 AM EST",
679
+ "Jan 15, 1998 9:00 AM EST",
680
+ "Jan 16, 1998 9:00 AM EST",
681
+ "Jan 17, 1998 9:00 AM EST",
682
+ "Jan 18, 1998 9:00 AM EST",
683
+ "Jan 19, 1998 9:00 AM EST",
684
+ "Jan 20, 1998 9:00 AM EST",
685
+ "Jan 21, 1998 9:00 AM EST",
686
+ "Jan 22, 1998 9:00 AM EST",
687
+ "Jan 23, 1998 9:00 AM EST",
688
+ "Jan 24, 1998 9:00 AM EST",
689
+ "Jan 25, 1998 9:00 AM EST",
690
+ "Jan 26, 1998 9:00 AM EST",
691
+ "Jan 27, 1998 9:00 AM EST",
692
+ "Jan 28, 1998 9:00 AM EST",
693
+ "Jan 29, 1998 9:00 AM EST",
694
+ "Jan 30, 1998 9:00 AM EST",
695
+ "Jan 31, 1998 9:00 AM EST",
696
+ "Jan 01, 1999 9:00 AM EST",
697
+ "Jan 02, 1999 9:00 AM EST",
698
+ "Jan 03, 1999 9:00 AM EST",
699
+ "Jan 04, 1999 9:00 AM EST",
700
+ "Jan 05, 1999 9:00 AM EST",
701
+ "Jan 06, 1999 9:00 AM EST",
702
+ "Jan 07, 1999 9:00 AM EST",
703
+ "Jan 08, 1999 9:00 AM EST",
704
+ "Jan 09, 1999 9:00 AM EST",
705
+ "Jan 10, 1999 9:00 AM EST",
706
+ "Jan 11, 1999 9:00 AM EST",
707
+ "Jan 12, 1999 9:00 AM EST",
708
+ "Jan 13, 1999 9:00 AM EST",
709
+ "Jan 14, 1999 9:00 AM EST",
710
+ "Jan 15, 1999 9:00 AM EST",
711
+ "Jan 16, 1999 9:00 AM EST",
712
+ "Jan 17, 1999 9:00 AM EST",
713
+ "Jan 18, 1999 9:00 AM EST",
714
+ "Jan 19, 1999 9:00 AM EST",
715
+ "Jan 20, 1999 9:00 AM EST",
716
+ "Jan 21, 1999 9:00 AM EST",
717
+ "Jan 22, 1999 9:00 AM EST",
718
+ "Jan 23, 1999 9:00 AM EST",
719
+ "Jan 24, 1999 9:00 AM EST",
720
+ "Jan 25, 1999 9:00 AM EST",
721
+ "Jan 26, 1999 9:00 AM EST",
722
+ "Jan 27, 1999 9:00 AM EST",
723
+ "Jan 28, 1999 9:00 AM EST",
724
+ "Jan 29, 1999 9:00 AM EST",
725
+ "Jan 30, 1999 9:00 AM EST",
726
+ "Jan 31, 1999 9:00 AM EST",
727
+ "Jan 01, 2000 9:00 AM EST",
728
+ "Jan 02, 2000 9:00 AM EST",
729
+ "Jan 03, 2000 9:00 AM EST",
730
+ "Jan 04, 2000 9:00 AM EST",
731
+ "Jan 05, 2000 9:00 AM EST",
732
+ "Jan 06, 2000 9:00 AM EST",
733
+ "Jan 07, 2000 9:00 AM EST",
734
+ "Jan 08, 2000 9:00 AM EST",
735
+ "Jan 09, 2000 9:00 AM EST",
736
+ "Jan 10, 2000 9:00 AM EST",
737
+ "Jan 11, 2000 9:00 AM EST",
738
+ "Jan 12, 2000 9:00 AM EST",
739
+ "Jan 13, 2000 9:00 AM EST",
740
+ "Jan 14, 2000 9:00 AM EST",
741
+ "Jan 15, 2000 9:00 AM EST",
742
+ "Jan 16, 2000 9:00 AM EST",
743
+ "Jan 17, 2000 9:00 AM EST",
744
+ "Jan 18, 2000 9:00 AM EST",
745
+ "Jan 19, 2000 9:00 AM EST",
746
+ "Jan 20, 2000 9:00 AM EST",
747
+ "Jan 21, 2000 9:00 AM EST",
748
+ "Jan 22, 2000 9:00 AM EST",
749
+ "Jan 23, 2000 9:00 AM EST",
750
+ "Jan 24, 2000 9:00 AM EST",
751
+ "Jan 25, 2000 9:00 AM EST",
752
+ "Jan 26, 2000 9:00 AM EST",
753
+ "Jan 27, 2000 9:00 AM EST",
754
+ "Jan 28, 2000 9:00 AM EST",
755
+ "Jan 29, 2000 9:00 AM EST",
756
+ "Jan 30, 2000 9:00 AM EST",
757
+ "Jan 31, 2000 9:00 AM EST"
758
+ ], true
759
+ )
760
+
761
+ enumeration_spec(
762
+ "Weekly for 10 occurrences (RFC 2445 p 119)",
763
+ "19970902T090000",
764
+ "US-Eastern",
765
+ "FREQ=WEEKLY;COUNT=10",
766
+ [
767
+ "Sep 2, 1997 9:00 AM EDT",
768
+ "Sep 9, 1997 9:00 AM EDT",
769
+ "Sep 16, 1997 9:00 AM EDT",
770
+ "Sep 23, 1997 9:00 AM EDT",
771
+ "Sep 30, 1997 9:00 AM EDT",
772
+ "Oct 7, 1997 9:00 AM EDT",
773
+ "Oct 14, 1997 9:00 AM EDT",
774
+ "Oct 21, 1997 9:00 AM EDT",
775
+ "Oct 28, 1997 9:00 AM EST",
776
+ "Nov 4, 1997 9:00 AM EST"
777
+ ]
778
+ )
779
+
780
+ enumeration_spec(
781
+ "Weekly until December 24, 1997 (RFC 2445 p 119)",
782
+ "19970902T090000",
783
+ "US-Eastern",
784
+ "FREQ=WEEKLY;UNTIL=19971224T000000Z",
785
+ [
786
+ "Sep 2, 1997 9:00 AM EDT",
787
+ "Sep 9, 1997 9:00 AM EDT",
788
+ "Sep 16, 1997 9:00 AM EDT",
789
+ "Sep 23, 1997 9:00 AM EDT",
790
+ "Sep 30, 1997 9:00 AM EDT",
791
+ "Oct 7, 1997 9:00 AM EDT",
792
+ "Oct 14, 1997 9:00 AM EDT",
793
+ "Oct 21, 1997 9:00 AM EDT",
794
+ "Oct 28, 1997 9:00 AM EST",
795
+ "Nov 4, 1997 9:00 AM EST",
796
+ "Nov 11, 1997 9:00 AM EST",
797
+ "Nov 18, 1997 9:00 AM EST",
798
+ "Nov 25, 1997 9:00 AM EST",
799
+ "Dec 2, 1997 9:00 AM EST",
800
+ "Dec 9, 1997 9:00 AM EST",
801
+ "Dec 16, 1997 9:00 AM EST",
802
+ "Dec 23, 1997 9:00 AM EST"
803
+ ]
804
+ )
805
+
806
+ enumeration_spec(
807
+ "Every other week - forever (RFC 2445 p 119)",
808
+ "19970902T090000",
809
+ "US-Eastern",
810
+ "FREQ=WEEKLY;INTERVAL=2;WKST=SU",
811
+ [
812
+ "Sep 2, 1997 9:00 AM EDT",
813
+ "Sep 16, 1997 9:00 AM EDT",
814
+ "Sep 30, 1997 9:00 AM EDT",
815
+ "Oct 14, 1997 9:00 AM EDT",
816
+ "Oct 28, 1997 9:00 AM EST",
817
+ "Nov 11, 1997 9:00 AM EST",
818
+ "Nov 25, 1997 9:00 AM EST",
819
+ "Dec 9, 1997 9:00 AM EST",
820
+ "Dec 23, 1997 9:00 AM EST",
821
+ "Jan 6, 1998 9:00 AM EST",
822
+ "Jan 20, 1998 9:00 AM EST",
823
+ "Feb 3, 1998 9:00 AM EST",
824
+ "..."
825
+ ]
826
+ )
827
+
828
+ enumeration_spec(
829
+ "Weekly on Tuesday and Thursday for 5 weeks, Alternative 1 (RFC 2445 p 119)",
830
+ "19970902T090000",
831
+ "US-Eastern",
832
+ "FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH",
833
+ [
834
+ "Sep 2, 1997 9:00 AM EDT",
835
+ "Sep 4, 1997 9:00 AM EDT",
836
+ "Sep 9, 1997 9:00 AM EDT",
837
+ "Sep 11, 1997 9:00 AM EDT",
838
+ "Sep 16, 1997 9:00 AM EST",
839
+ "Sep 18, 1997 9:00 AM EST",
840
+ "Sep 23, 1997 9:00 AM EST",
841
+ "Sep 25, 1997 9:00 AM EST",
842
+ "Sep 30, 1997 9:00 AM EST",
843
+ "Oct 2, 1997 9:00 AM EST"
844
+ ]
845
+ )
846
+
847
+ enumeration_spec(
848
+ "Weekly on Tuesday and Thursday for 5 weeks, Alternative 2 (RFC 2445 p 120)",
849
+ "19970902T090000",
850
+ "US-Eastern",
851
+ "FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH",
852
+ [
853
+ "Sep 2, 1997 9:00 AM EDT",
854
+ "Sep 4, 1997 9:00 AM EDT",
855
+ "Sep 9, 1997 9:00 AM EDT",
856
+ "Sep 11, 1997 9:00 AM EDT",
857
+ "Sep 16, 1997 9:00 AM EST",
858
+ "Sep 18, 1997 9:00 AM EST",
859
+ "Sep 23, 1997 9:00 AM EST",
860
+ "Sep 25, 1997 9:00 AM EST",
861
+ "Sep 30, 1997 9:00 AM EST",
862
+ "Oct 2, 1997 9:00 AM EST"
863
+ ]
864
+ )
865
+
866
+ enumeration_spec(
867
+ "Every other week on Monday, Wednesday and Friday until December 24,1997, but starting on Tuesday, September 2, 1997 (RFC 2445 p 120)",
868
+ "19970902T090000",
869
+ "US-Eastern",
870
+ "FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR",
871
+ [
872
+ "Sep 2, 1997 9:00 AM EDT",
873
+ "Sep 3, 1997 9:00 AM EDT",
874
+ "Sep 5, 1997 9:00 AM EDT",
875
+ "Sep 15, 1997 9:00 AM EDT",
876
+ "Sep 17, 1997 9:00 AM EDT",
877
+ "Sep 19, 1997 9:00 AM EDT",
878
+ "Sep 29, 1997 9:00 AM EDT",
879
+ "Oct 1, 1997 9:00 AM EDT",
880
+ "Oct 3, 1997 9:00 AM EDT",
881
+ "Oct 13, 1997 9:00 AM EDT",
882
+ "Oct 15, 1997 9:00 AM EDT",
883
+ "Oct 17, 1997 9:00 AM EDT",
884
+ "Oct 27, 1997 9:00 AM EST",
885
+ "Oct 29, 1997 9:00 AM EST",
886
+ "Oct 31, 1997 9:00 AM EST",
887
+ "Nov 10, 1997 9:00 AM EST",
888
+ "Nov 12, 1997 9:00 AM EST",
889
+ "Nov 14, 1997 9:00 AM EST",
890
+ "Nov 24, 1997 9:00 AM EST",
891
+ "Nov 26, 1997 9:00 AM EST",
892
+ "Nov 28, 1997 9:00 AM EST",
893
+ "Dec 8, 1997 9:00 AM EST",
894
+ "Dec 10, 1997 9:00 AM EST",
895
+ "Dec 12, 1997 9:00 AM EST",
896
+ "Dec 22, 1997 9:00 AM EST"
897
+ ], true
898
+ )
899
+
900
+ enumeration_spec(
901
+ "Every other week on TU and TH for 8 occurrences (RFC 2445 p 120)",
902
+ "19970902T090000",
903
+ "US-Eastern",
904
+ "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH",
905
+ [
906
+ "Sep 2, 1997 9:00 AM EDT",
907
+ "Sep 4, 1997 9:00 AM EDT",
908
+ "Sep 16, 1997 9:00 AM EDT",
909
+ "Sep 18, 1997 9:00 AM EDT",
910
+ "Sep 30, 1997 9:00 AM EDT",
911
+ "Oct 2, 1997 9:00 AM EDT",
912
+ "Oct 14, 1997 9:00 AM EDT",
913
+ "Oct 16, 1997 9:00 AM EDT"
914
+ ], true
915
+ )
916
+
917
+ enumeration_spec(
918
+ "Monthly on the 1st Friday for ten occurrences (RFC 2445 p 120)",
919
+ "19970905T090000",
920
+ "US-Eastern",
921
+ "FREQ=MONTHLY;COUNT=10;BYDAY=1FR",
922
+ [
923
+ "Sep 5, 1997 9:00 AM EDT",
924
+ "Oct 3, 1997 9:00 AM EDT",
925
+ "Nov 7, 1997 9:00 AM EST",
926
+ "Dec 5, 1997 9:00 AM EST",
927
+ "Jan 2, 1998 9:00 AM EST",
928
+ "Feb 6, 1998 9:00 AM EST",
929
+ "Mar 6, 1998 9:00 AM EST",
930
+ "Apr 3, 1998 9:00 AM EST",
931
+ "May 1, 1998 9:00 AM EDT",
932
+ "Jun 5, 1998 9:00 AM EDT",
933
+ ]
934
+ )
935
+
936
+ enumeration_spec(
937
+ "Monthly on the 1st Friday until December 24, 1997 (RFC 2445 p 120)",
938
+ "19970905T090000",
939
+ "US-Eastern",
940
+ "FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR",
941
+ [
942
+ "Sep 5, 1997 9:00 AM EDT",
943
+ "Oct 3, 1997 9:00 AM EDT",
944
+ "Nov 7, 1997 9:00 AM EST",
945
+ "Dec 5, 1997 9:00 AM EST"
946
+ ]
947
+ )
948
+
949
+ enumeration_spec(
950
+ "Every other month on the 1st and last Sunday of the month for 10 occurrences (RFC 2445 p 120)",
951
+ "19970907T090000",
952
+ "US-Eastern",
953
+ "FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU",
954
+ [
955
+ "Sep 7, 1997 9:00 AM EDT",
956
+ "Sep 28, 1997 9:00 AM EDT",
957
+ "Nov 2, 1997 9:00 AM EST",
958
+ "Nov 30, 1997 9:00 AM EST",
959
+ "Jan 4, 1998 9:00 AM EST",
960
+ "Jan 25, 1998 9:00 AM EST",
961
+ "Mar 1, 1998 9:00 AM EST",
962
+ "Mar 29, 1998 9:00 AM EST",
963
+ "May 3, 1998 9:00 AM EDT",
964
+ "May 31, 1998 9:00 AM EST"
965
+ ]
966
+ )
967
+
968
+ enumeration_spec(
969
+ "Monthly on the second to last Monday of the month for 6 months (RFC 2445 p 121)",
970
+ "19970922T090000",
971
+ "US-Eastern",
972
+ "FREQ=MONTHLY;COUNT=6;BYDAY=-2MO",
973
+ [
974
+ "Sep 22, 1997 9:00 AM EDT",
975
+ "Oct 20, 1997 9:00 AM EDT",
976
+ "Nov 17, 1997 9:00 AM EST",
977
+ "Dec 22, 1997 9:00 AM EST",
978
+ "Jan 19, 1998 9:00 AM EST",
979
+ "Feb 16, 1998 9:00 AM EST"
980
+ ]
981
+ )
982
+
983
+ enumeration_spec(
984
+ "Monthly on the third the to last day of the month forever (RFC 2445 p 121)",
985
+ "19970928T090000",
986
+ "US-Eastern",
987
+ "FREQ=MONTHLY;BYMONTHDAY=-3",
988
+ [
989
+ "Sep 28, 1997 9:00 AM EDT",
990
+ "Oct 29, 1997 9:00 AM EDT",
991
+ "Nov 28, 1997 9:00 AM EST",
992
+ "Dec 29, 1997 9:00 AM EST",
993
+ "Jan 29, 1998 9:00 AM EST",
994
+ "Feb 26, 1998 9:00 AM EST",
995
+ "..."
996
+ ]
997
+ )
998
+
999
+ enumeration_spec(
1000
+ "Monthly on the first and last day of the month for 10 occurrences (RFC 2445 p 121)",
1001
+ "19970930T090000",
1002
+ "US-Eastern",
1003
+ "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1",
1004
+ [
1005
+ "Sep 30, 1997 9:00 AM EDT",
1006
+ "Oct 1, 1997 9:00 AM EDT",
1007
+ "Oct 31, 1997 9:00 AM EST",
1008
+ "Nov 1, 1997 9:00 AM EST",
1009
+ "Nov 30, 1997 9:00 AM EST",
1010
+ "Dec 1, 1997 9:00 AM EST",
1011
+ "Dec 31, 1997 9:00 AM EST",
1012
+ "Jan 1, 1998 9:00 AM EST",
1013
+ "Jan 31, 1998 9:00 AM EST",
1014
+ "Feb 1, 1998 9:00 AM EST"
1015
+ ]
1016
+ )
1017
+
1018
+ enumeration_spec(
1019
+ "Every 18 months on the 10th thru 15th of the month for 10 occurrences (RFC 2445 p 121)",
1020
+ "19970910T090000",
1021
+ "US-Eastern",
1022
+ "FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15",
1023
+ [
1024
+ "Sep 10, 1997 9:00 AM EDT",
1025
+ "Sep 11, 1997 9:00 AM EDT",
1026
+ "Sep 12, 1997 9:00 AM EDT",
1027
+ "Sep 13, 1997 9:00 AM EDT",
1028
+ "Sep 14, 1997 9:00 AM EDT",
1029
+ "Sep 15, 1997 9:00 AM EDT",
1030
+ "Mar 10, 1999 9:00 AM EDT",
1031
+ "Mar 11, 1999 9:00 AM EDT",
1032
+ "Mar 12, 1999 9:00 AM EDT",
1033
+ "Mar 13, 1999 9:00 AM EDT"
1034
+ ]
1035
+ )
1036
+
1037
+ enumeration_spec(
1038
+ "Every Tuesday, every other month (RFC 2445 p 122)",
1039
+ "19970902T090000",
1040
+ "US-Eastern",
1041
+ "FREQ=MONTHLY;INTERVAL=2;BYDAY=TU",
1042
+ [
1043
+ "Sep 2, 1997 9:00 AM EDT",
1044
+ "Sep 9, 1997 9:00 AM EDT",
1045
+ "Sep 16, 1997 9:00 AM EDT",
1046
+ "Sep 23, 1997 9:00 AM EDT",
1047
+ "Sep 30, 1997 9:00 AM EDT",
1048
+ "Nov 4, 1997 9:00 AM EST",
1049
+ "Nov 11, 1997 9:00 AM EST",
1050
+ "Nov 18, 1997 9:00 AM EST",
1051
+ "Nov 25, 1997 9:00 AM EST",
1052
+ "Jan 6, 1998 9:00 AM EST",
1053
+ "Jan 13, 1998 9:00 AM EST",
1054
+ "Jan 20, 1998 9:00 AM EST",
1055
+ "Jan 27, 1998 9:00 AM EST",
1056
+ "Mar 3, 1998 9:00 AM EST",
1057
+ "Mar 10, 1998 9:00 AM EST",
1058
+ "Mar 17, 1998 9:00 AM EST",
1059
+ "Mar 24, 1998 9:00 AM EST",
1060
+ "Mar 31, 1998 9:00 AM EST",
1061
+ "..."
1062
+ ]
1063
+ )
1064
+
1065
+ enumeration_spec(
1066
+ "Yearly in June and July for 10 occurrences (RFC 2445 p 122)",
1067
+ "19970610T090000",
1068
+ "US-Eastern",
1069
+ "FREQ=YEARLY;COUNT=10;BYMONTH=6,7",
1070
+ [
1071
+ "Jun 10, 1997 9:00 AM EDT",
1072
+ "Jul 10, 1997 9:00 AM EDT",
1073
+ "Jun 10, 1998 9:00 AM EDT",
1074
+ "Jul 10, 1998 9:00 AM EDT",
1075
+ "Jun 10, 1999 9:00 AM EDT",
1076
+ "Jul 10, 1999 9:00 AM EDT",
1077
+ "Jun 10, 2000 9:00 AM EDT",
1078
+ "Jul 10, 2000 9:00 AM EDT",
1079
+ "Jun 10, 2001 9:00 AM EDT",
1080
+ "Jul 10, 2001 9:00 AM EDT"
1081
+ ]
1082
+ )
1083
+
1084
+ enumeration_spec(
1085
+ "Every other year on January, February, and March for 10 occurrences (RFC 2445 p 122)",
1086
+ "19970310T090000",
1087
+ "US-Eastern",
1088
+ "FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3",
1089
+ [
1090
+ "Mar 10, 1997 9:00 AM EST",
1091
+ "Jan 10, 1999 9:00 AM EST",
1092
+ "Feb 10, 1999 9:00 AM EST",
1093
+ "Mar 10, 1999 9:00 AM EST",
1094
+ "Jan 10, 2001 9:00 AM EST",
1095
+ "Feb 10, 2001 9:00 AM EST",
1096
+ "Mar 10, 2001 9:00 AM EST",
1097
+ "Jan 10, 2003 9:00 AM EST",
1098
+ "Feb 10, 2003 9:00 AM EST",
1099
+ "Mar 10, 2003 9:00 AM EST",
1100
+ ]
1101
+ )
1102
+
1103
+ enumeration_spec(
1104
+ "Every 3rd year on the 1st, 100th and 200th day for 10 occurrences (RFC 2445 p 122)",
1105
+ "19970101T090000",
1106
+ "US-Eastern",
1107
+ "FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200",
1108
+ [
1109
+ "Jan 1, 1997 9:00 AM EST",
1110
+ "Apr 10, 1997 9:00 AM EDT",
1111
+ "Jul 19, 1997 9:00 AM EDT",
1112
+ "Jan 1, 2000 9:00 AM EST",
1113
+ "Apr 9, 2000 9:00 AM EDT",
1114
+ "Jul 18, 2000 9:00 AM EDT",
1115
+ "Jan 1, 2003 9:00 AM EST",
1116
+ "Apr 10, 2003 9:00 AM EDT",
1117
+ "Jul 19, 2003 9:00 AM EDT",
1118
+ "Jan 1, 2006 9:00 AM EST"
1119
+ ]
1120
+ )
1121
+
1122
+ enumeration_spec(
1123
+ "Every 20th Monday of the year, forever (RFC 2445 p 122-3)",
1124
+ "19970519T090000",
1125
+ "US-Eastern",
1126
+ "FREQ=YEARLY;BYDAY=20MO",
1127
+ [
1128
+ "May 19, 1997 9:00 AM EDT",
1129
+ "May 18, 1998 9:00 AM EDT",
1130
+ "May 17, 1999 9:00 AM EDT",
1131
+ "..."
1132
+ ]
1133
+ )
1134
+
1135
+ enumeration_spec(
1136
+ "Every second to last Wednesday of the year, forever",
1137
+ "19971224T090000",
1138
+ "US-Eastern",
1139
+ "FREQ=YEARLY;BYDAY=-2WE",
1140
+ [
1141
+ "Dec 24, 1997 9:00 AM EDT",
1142
+ "Dec 23, 1998 9:00 AM EDT",
1143
+ "Dec 22, 1999 9:00 AM EDT",
1144
+ "Dec 20, 2000 9:00 AM EDT",
1145
+ "..."
1146
+ ]
1147
+ )
1148
+
1149
+ enumeration_spec(
1150
+ "Monday of week number 20 (where the default start of the week is Monday), forever (RFC 2445 p 123)",
1151
+ "19970512T090000",
1152
+ "US-Eastern",
1153
+ "FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO",
1154
+ [
1155
+ "May 12, 1997 9:00 AM EDT",
1156
+ "May 11, 1998 9:00 AM EDT",
1157
+ "May 17, 1999 9:00 AM EDT",
1158
+ "..."
1159
+ ]
1160
+ )
1161
+
1162
+ enumeration_spec(
1163
+ "Every Thursday in March, forever (RFC 2445 p 123)",
1164
+ "19970313T090000",
1165
+ "US-Eastern",
1166
+ "FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
1167
+ [
1168
+ "Mar 13, 1997 9:00 AM EST",
1169
+ "Mar 20, 1997 9:00 AM EST",
1170
+ "Mar 27, 1997 9:00 AM EST",
1171
+ "Mar 5, 1998 9:00 AM EST",
1172
+ "Mar 12, 1998 9:00 AM EST",
1173
+ "Mar 19, 1998 9:00 AM EST",
1174
+ "Mar 26, 1998 9:00 AM EST",
1175
+ "Mar 4, 1999 9:00 AM EST",
1176
+ "Mar 11, 1999 9:00 AM EST",
1177
+ "Mar 18, 1999 9:00 AM EST",
1178
+ "Mar 25, 1999 9:00 AM EST",
1179
+ "..."
1180
+ ]
1181
+ )
1182
+
1183
+ enumeration_spec(
1184
+ "Every Thursday, but only during June, July, and August, forever (RFC 2445 p 123)",
1185
+ "19970605T090000",
1186
+ "US-Eastern",
1187
+ "FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8",
1188
+ [
1189
+ "Jun 05, 1997 9:00 AM EDT",
1190
+ "Jun 12, 1997 9:00 AM EDT",
1191
+ "Jun 19, 1997 9:00 AM EDT",
1192
+ "Jun 26, 1997 9:00 AM EDT",
1193
+ "Jul 03, 1997 9:00 AM EDT",
1194
+ "Jul 10, 1997 9:00 AM EDT",
1195
+ "Jul 17, 1997 9:00 AM EDT",
1196
+ "Jul 24, 1997 9:00 AM EDT",
1197
+ "Jul 31, 1997 9:00 AM EDT",
1198
+ "Aug 07, 1997 9:00 AM EDT",
1199
+ "Aug 14, 1997 9:00 AM EDT",
1200
+ "Aug 21, 1997 9:00 AM EDT",
1201
+ "Aug 28, 1997 9:00 AM EDT",
1202
+ "Jun 04, 1998 9:00 AM EDT",
1203
+ "Jun 11, 1998 9:00 AM EDT",
1204
+ "Jun 18, 1998 9:00 AM EDT",
1205
+ "Jun 25, 1998 9:00 AM EDT",
1206
+ "Jul 02, 1998 9:00 AM EDT",
1207
+ "Jul 09, 1998 9:00 AM EDT",
1208
+ "Jul 16, 1998 9:00 AM EDT",
1209
+ "Jul 23, 1998 9:00 AM EDT",
1210
+ "Jul 30, 1998 9:00 AM EDT",
1211
+ "Aug 06, 1998 9:00 AM EDT",
1212
+ "Aug 13, 1998 9:00 AM EDT",
1213
+ "Aug 20, 1998 9:00 AM EDT",
1214
+ "Aug 27, 1998 9:00 AM EDT",
1215
+ "Jun 03, 1999 9:00 AM EDT",
1216
+ "Jun 10, 1999 9:00 AM EDT",
1217
+ "Jun 17, 1999 9:00 AM EDT",
1218
+ "Jun 24, 1999 9:00 AM EDT",
1219
+ "Jul 01, 1999 9:00 AM EDT",
1220
+ "Jul 08, 1999 9:00 AM EDT",
1221
+ "Jul 15, 1999 9:00 AM EDT",
1222
+ "Jul 22, 1999 9:00 AM EDT",
1223
+ "Jul 29, 1999 9:00 AM EDT",
1224
+ "Aug 05, 1999 9:00 AM EDT",
1225
+ "Aug 12, 1999 9:00 AM EDT",
1226
+ "Aug 19, 1999 9:00 AM EDT",
1227
+ "Aug 26, 1999 9:00 AM EDT",
1228
+ "..."
1229
+ ]
1230
+ )
1231
+
1232
+ enumeration_spec(
1233
+ "Every Friday the 13th, forever (RFC 2445 p 123-4)",
1234
+ "19970902T090000",
1235
+ "US-Eastern",
1236
+ "FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13",
1237
+ [
1238
+ # The RFC example uses exdate to exclude the start date, this is a slightly altered
1239
+ # use case
1240
+ "Sep 2, 1997 9:00 AM EST",
1241
+ "Feb 13, 1998 9:00 AM EST",
1242
+ "Mar 13, 1998 9:00 AM EST",
1243
+ "Nov 13, 1998 9:00 AM EST",
1244
+ "Aug 13, 1999 9:00 AM EDT",
1245
+ "Oct 13, 2000 9:00 AM EST",
1246
+ "..."
1247
+ ]
1248
+ )
1249
+
1250
+ enumeration_spec(
1251
+ "The first Saturday that follows the first Sunday of the month, forever (RFC 2445 p 124)",
1252
+ "19970913T090000",
1253
+ "US-Eastern",
1254
+ "FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13",
1255
+ [
1256
+ "Sep 13, 1997 9:00 AM EDT",
1257
+ "Oct 11, 1997 9:00 AM EDT",
1258
+ "Nov 8, 1997 9:00 AM EST",
1259
+ "Dec 13, 1997 9:00 AM EST",
1260
+ "Jan 10, 1998 9:00 AM EST",
1261
+ "Feb 7, 1998 9:00 AM EST",
1262
+ "Mar 7, 1998 9:00 AM EST",
1263
+ "Apr 11, 1998 9:00 AM EDT",
1264
+ "May 9, 1998 9:00 AM EDT",
1265
+ "Jun 13, 1998 9:00 AM EDT",
1266
+ "..."
1267
+ ]
1268
+ )
1269
+
1270
+ enumeration_spec(
1271
+ "Every four years, the first Tuesday after a Monday in November, forever(U.S. Presidential Election day) (RFC 2445 p 124)",
1272
+ "19961105T090000",
1273
+ "US-Eastern",
1274
+ "FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8",
1275
+ [
1276
+ "Nov 5, 1996 9:00 AM EDT",
1277
+ "Nov 7, 2000 9:00 AM EDT",
1278
+ "Nov 2, 2004 9:00 AM EDT",
1279
+ "..."
1280
+ ]
1281
+ )
1282
+
1283
+ enumeration_spec(
1284
+ "3rd instance into the month of one of Tuesday, Wednesday or Thursday, for the next 3 months (RFC 2445 p 124)",
1285
+ "19970904T090000",
1286
+ "US-Eastern",
1287
+ "FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3",
1288
+ [
1289
+ "Sep 4, 1997 9:00 AM EDT",
1290
+ "Oct 7, 1997 9:00 AM EDT",
1291
+ "Nov 6, 1997 9:00 AM EST",
1292
+ ]
1293
+ )
1294
+
1295
+ enumeration_spec(
1296
+ "The 2nd to last weekday of the month (RFC 2445 p 124)",
1297
+ "19970929T090000",
1298
+ "US-Eastern",
1299
+ "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2",
1300
+ [
1301
+ "Sep 29, 1997 9:00 AM EDT",
1302
+ "Oct 30, 1997 9:00 AM EST",
1303
+ "Nov 27, 1997 9:00 AM EST",
1304
+ "Dec 30, 1997 9:00 AM EST",
1305
+ "Jan 29, 1998 9:00 AM EST",
1306
+ "Feb 26, 1998 9:00 AM EST",
1307
+ "Mar 30, 1998 9:00 AM EST",
1308
+ "..."
1309
+ ]
1310
+ )
1311
+
1312
+ enumeration_spec(
1313
+ "Every 3 hours from 9:00 AM to 5:00 PM on a specific day (RFC 2445 p 125)",
1314
+ "19970902T090000",
1315
+ "US-Eastern",
1316
+ "FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z",
1317
+ [
1318
+ "Sep 2, 1997 9:00 EDT",
1319
+ "Sep 2, 1997 12:00 EDT",
1320
+ "Sep 2, 1997 15:00 EDT",
1321
+ ]
1322
+ )
1323
+
1324
+ enumeration_spec(
1325
+ "Every 15 minutes for 6 occurrences (RFC 2445 p 125)",
1326
+ "19970902T090000",
1327
+ "US-Eastern",
1328
+ "FREQ=MINUTELY;INTERVAL=15;COUNT=6",
1329
+ [
1330
+ "Sep 2, 1997 09:00 EDT",
1331
+ "Sep 2, 1997 09:15 EDT",
1332
+ "Sep 2, 1997 09:30 EDT",
1333
+ "Sep 2, 1997 09:45 EDT",
1334
+ "Sep 2, 1997 10:00 EDT",
1335
+ "Sep 2, 1997 10:15 EDT",
1336
+ ]
1337
+ )
1338
+
1339
+ enumeration_spec(
1340
+ "Every hour and a half for 4 occurrences (RFC 2445 p 125)",
1341
+ "19970902T090000",
1342
+ "US-Eastern",
1343
+ "FREQ=MINUTELY;INTERVAL=90;COUNT=4",
1344
+ [
1345
+ "Sep 2, 1997 09:00 EDT",
1346
+ "Sep 2, 1997 10:30 EDT",
1347
+ "Sep 2, 1997 12:00 EDT",
1348
+ "Sep 2, 1997 13:30 EDT",
1349
+ ]
1350
+ )
1351
+
1352
+ enumeration_spec(
1353
+ "Every 20 minutes from 9:00 AM to 4:40 PM every day - alternative 1 (RFC 2445 p 125)",
1354
+ "19970902T090000",
1355
+ "US-Eastern",
1356
+ "FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40",
1357
+ [
1358
+ "Sep 2, 1997 09:00 EDT",
1359
+ "Sep 2, 1997 09:20 EDT",
1360
+ "Sep 2, 1997 09:40 EDT",
1361
+ "Sep 2, 1997 10:00 EDT",
1362
+ "Sep 2, 1997 10:20 EDT",
1363
+ "Sep 2, 1997 10:40 EDT",
1364
+ "Sep 2, 1997 11:00 EDT",
1365
+ "Sep 2, 1997 11:20 EDT",
1366
+ "Sep 2, 1997 11:40 EDT",
1367
+ "Sep 2, 1997 12:00 EDT",
1368
+ "Sep 2, 1997 12:20 EDT",
1369
+ "Sep 2, 1997 12:40 EDT",
1370
+ "Sep 2, 1997 13:00 EDT",
1371
+ "Sep 2, 1997 13:20 EDT",
1372
+ "Sep 2, 1997 13:40 EDT",
1373
+ "Sep 2, 1997 14:00 EDT",
1374
+ "Sep 2, 1997 14:20 EDT",
1375
+ "Sep 2, 1997 14:40 EDT",
1376
+ "Sep 2, 1997 15:00 EDT",
1377
+ "Sep 2, 1997 15:20 EDT",
1378
+ "Sep 2, 1997 15:40 EDT",
1379
+ "Sep 2, 1997 16:00 EDT",
1380
+ "Sep 2, 1997 16:20 EDT",
1381
+ "Sep 2, 1997 16:40 EDT",
1382
+ "Sep 3, 1997 09:00 EDT",
1383
+ "Sep 3, 1997 09:20 EDT",
1384
+ "Sep 3, 1997 09:40 EDT",
1385
+ "Sep 3, 1997 10:00 EDT",
1386
+ "Sep 3, 1997 10:20 EDT",
1387
+ "Sep 3, 1997 10:40 EDT",
1388
+ "Sep 3, 1997 11:00 EDT",
1389
+ "Sep 3, 1997 11:20 EDT",
1390
+ "Sep 3, 1997 11:40 EDT",
1391
+ "Sep 3, 1997 12:00 EDT",
1392
+ "Sep 3, 1997 12:20 EDT",
1393
+ "Sep 3, 1997 12:40 EDT",
1394
+ "Sep 3, 1997 13:00 EDT",
1395
+ "Sep 3, 1997 13:20 EDT",
1396
+ "Sep 3, 1997 13:40 EDT",
1397
+ "Sep 3, 1997 14:00 EDT",
1398
+ "Sep 3, 1997 14:20 EDT",
1399
+ "Sep 3, 1997 14:40 EDT",
1400
+ "Sep 3, 1997 15:00 EDT",
1401
+ "Sep 3, 1997 15:20 EDT",
1402
+ "Sep 3, 1997 15:40 EDT",
1403
+ "Sep 3, 1997 16:00 EDT",
1404
+ "Sep 3, 1997 16:20 EDT",
1405
+ "Sep 3, 1997 16:40 EDT",
1406
+ "..."
1407
+ ]
1408
+ )
1409
+
1410
+ enumeration_spec(
1411
+ "Every 20 minutes from 9:00 AM to 4:40 PM every day - alternative 2 (RFC 2445 p 125)",
1412
+ "19970902T090000",
1413
+ "US-Eastern",
1414
+ "FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16",
1415
+ [
1416
+ "Sep 2, 1997 09:00 EDT",
1417
+ "Sep 2, 1997 09:20 EDT",
1418
+ "Sep 2, 1997 09:40 EDT",
1419
+ "Sep 2, 1997 10:00 EDT",
1420
+ "Sep 2, 1997 10:20 EDT",
1421
+ "Sep 2, 1997 10:40 EDT",
1422
+ "Sep 2, 1997 11:00 EDT",
1423
+ "Sep 2, 1997 11:20 EDT",
1424
+ "Sep 2, 1997 11:40 EDT",
1425
+ "Sep 2, 1997 12:00 EDT",
1426
+ "Sep 2, 1997 12:20 EDT",
1427
+ "Sep 2, 1997 12:40 EDT",
1428
+ "Sep 2, 1997 13:00 EDT",
1429
+ "Sep 2, 1997 13:20 EDT",
1430
+ "Sep 2, 1997 13:40 EDT",
1431
+ "Sep 2, 1997 14:00 EDT",
1432
+ "Sep 2, 1997 14:20 EDT",
1433
+ "Sep 2, 1997 14:40 EDT",
1434
+ "Sep 2, 1997 15:00 EDT",
1435
+ "Sep 2, 1997 15:20 EDT",
1436
+ "Sep 2, 1997 15:40 EDT",
1437
+ "Sep 2, 1997 16:00 EDT",
1438
+ "Sep 2, 1997 16:20 EDT",
1439
+ "Sep 2, 1997 16:40 EDT",
1440
+ "Sep 3, 1997 09:00 EDT",
1441
+ "Sep 3, 1997 09:20 EDT",
1442
+ "Sep 3, 1997 09:40 EDT",
1443
+ "Sep 3, 1997 10:00 EDT",
1444
+ "Sep 3, 1997 10:20 EDT",
1445
+ "Sep 3, 1997 10:40 EDT",
1446
+ "Sep 3, 1997 11:00 EDT",
1447
+ "Sep 3, 1997 11:20 EDT",
1448
+ "Sep 3, 1997 11:40 EDT",
1449
+ "Sep 3, 1997 12:00 EDT",
1450
+ "Sep 3, 1997 12:20 EDT",
1451
+ "Sep 3, 1997 12:40 EDT",
1452
+ "Sep 3, 1997 13:00 EDT",
1453
+ "Sep 3, 1997 13:20 EDT",
1454
+ "Sep 3, 1997 13:40 EDT",
1455
+ "Sep 3, 1997 14:00 EDT",
1456
+ "Sep 3, 1997 14:20 EDT",
1457
+ "Sep 3, 1997 14:40 EDT",
1458
+ "Sep 3, 1997 15:00 EDT",
1459
+ "Sep 3, 1997 15:20 EDT",
1460
+ "Sep 3, 1997 15:40 EDT",
1461
+ "Sep 3, 1997 16:00 EDT",
1462
+ "Sep 3, 1997 16:20 EDT",
1463
+ "Sep 3, 1997 16:40 EDT",
1464
+ "..."
1465
+ ]
1466
+ )
1467
+
1468
+ enumeration_spec(
1469
+ "An example where the days generated makes a difference because of WKST (MO case) (RFC 2445 p 125)",
1470
+ "19970805T090000",
1471
+ "US-Eastern",
1472
+ "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO",
1473
+ [
1474
+ "Aug 05, 1997 09:00 EDT",
1475
+ "Aug 10, 1997 09:00 EDT",
1476
+ "Aug 19, 1997 09:00 EDT",
1477
+ "Aug 24, 1997 09:00 EDT"
1478
+ ]
1479
+ )
1480
+
1481
+ enumeration_spec(
1482
+ "An example where the days generated makes a difference because of WKST (MO case) (RFC 2445 p 125)",
1483
+ "19970805T090000",
1484
+ "US-Eastern",
1485
+ "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU",
1486
+ [
1487
+ "Aug 05, 1997 09:00 EDT",
1488
+ "Aug 17, 1997 09:00 EDT",
1489
+ "Aug 19, 1997 09:00 EDT",
1490
+ "Aug 31, 1997 09:00 EDT"
1491
+ ]
1492
+ )
1493
+ end
1494
+ end
1495
+
1496
+ describe RiCal::PropertyValue::RecurrenceRule::RecurringDay do
1497
+
1498
+ def recurring(day)
1499
+ RiCal::PropertyValue::RecurrenceRule::RecurringDay.new(day, RiCal::PropertyValue::RecurrenceRule.new(nil, :value => "FREQ=MONTHLY"))
1500
+ end
1501
+
1502
+ describe "MO - any monday" do
1503
+ before(:each) do
1504
+ @it= recurring("MO")
1505
+ end
1506
+
1507
+ it "should include all Mondays" do
1508
+ [1, 8, 15, 22, 29].each do | day |
1509
+ @it.should include(Date.parse("Dec #{day} 2008"))
1510
+ end
1511
+ end
1512
+
1513
+ it "should not include non-Mondays" do
1514
+ (9..14).each do | day |
1515
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1516
+ end
1517
+ end
1518
+ end
1519
+
1520
+ describe "TU - any Tuesday" do
1521
+ before(:each) do
1522
+ @it= recurring("TU")
1523
+ end
1524
+
1525
+ it "should include all Tuesdays" do
1526
+ [2, 9, 16, 23, 30].each do | day |
1527
+ @it.should include(Date.parse("Dec #{day} 2008"))
1528
+ end
1529
+ end
1530
+
1531
+ it "should not include non-Tuesdays" do
1532
+ (10..15).each do | day |
1533
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1534
+ end
1535
+ end
1536
+ end
1537
+
1538
+ describe "WE - any Wednesday" do
1539
+ before(:each) do
1540
+ @it= recurring("WE")
1541
+ end
1542
+
1543
+ it "should include all Wednesdays" do
1544
+ [3, 10, 17, 24, 31].each do | day |
1545
+ @it.should include(Date.parse("Dec #{day} 2008"))
1546
+ end
1547
+ end
1548
+
1549
+ it "should not include non-Wednesdays" do
1550
+ (11..16).each do | day |
1551
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1552
+ end
1553
+ end
1554
+ end
1555
+
1556
+ describe "TH - any Thursday" do
1557
+ before(:each) do
1558
+ @it= recurring("TH")
1559
+ end
1560
+
1561
+ it "should include all Thursdays" do
1562
+ [4, 11, 18, 25].each do | day |
1563
+ @it.should include(Date.parse("Dec #{day} 2008"))
1564
+ end
1565
+ end
1566
+
1567
+ it "should not include non-Thursdays" do
1568
+ (5..10).each do | day |
1569
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1570
+ end
1571
+ end
1572
+ end
1573
+
1574
+ describe "FR - any Friday" do
1575
+ before(:each) do
1576
+ @it= recurring("FR")
1577
+ end
1578
+
1579
+ it "should include all Fridays" do
1580
+ [5, 12, 19, 26].each do | day |
1581
+ @it.should include(Date.parse("Dec #{day} 2008"))
1582
+ end
1583
+ end
1584
+
1585
+ it "should not include non-Fridays" do
1586
+ (6..11).each do | day |
1587
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1588
+ end
1589
+ end
1590
+ end
1591
+
1592
+ describe "SA - any Saturday" do
1593
+ before(:each) do
1594
+ @it= recurring("SA")
1595
+ end
1596
+
1597
+ it "should include all Saturdays" do
1598
+ [6, 13, 20, 27].each do | day |
1599
+ @it.should include(Date.parse("Dec #{day} 2008"))
1600
+ end
1601
+ end
1602
+
1603
+ it "should not include non-Saturdays" do
1604
+ (7..12).each do | day |
1605
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1606
+ end
1607
+ end
1608
+ end
1609
+
1610
+ describe "SU - any Sunday" do
1611
+ before(:each) do
1612
+ @it= recurring("SU")
1613
+ end
1614
+
1615
+ it "should include all Sundays" do
1616
+ [7, 14, 21, 28].each do | day |
1617
+ @it.should include(Date.parse("Dec #{day} 2008"))
1618
+ end
1619
+ end
1620
+
1621
+ it "should not include non-Saturdays" do
1622
+ (8..13).each do | day |
1623
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1624
+ end
1625
+ end
1626
+ end
1627
+
1628
+ describe "1MO - first Monday" do
1629
+ before(:each) do
1630
+ @it = recurring("1MO")
1631
+ end
1632
+
1633
+ it "should match the first Monday of the month" do
1634
+ @it.should include(Date.parse("Nov 3 2008"))
1635
+ end
1636
+
1637
+ it "should not include other Mondays" do
1638
+ [10, 17, 24].each do |day|
1639
+ @it.should_not include(Date.parse("Nov #{day} 2008"))
1640
+ end
1641
+ end
1642
+ end
1643
+
1644
+ describe "5MO - Fifth Monday" do
1645
+ before(:each) do
1646
+ @it = recurring("5MO")
1647
+ end
1648
+
1649
+ it "should match the fifth Monday of a month with five Mondays" do
1650
+ @it.should include(Date.parse("Dec 29 2008"))
1651
+ end
1652
+ end
1653
+
1654
+ describe "-1MO - last Monday" do
1655
+ before(:each) do
1656
+ @it = recurring("-1MO")
1657
+ end
1658
+
1659
+ it "should match the last Monday of the month" do
1660
+ @it.should include(Date.parse("Dec 29 2008"))
1661
+ end
1662
+
1663
+ it "should not include other Mondays" do
1664
+ [1, 8, 15, 22].each do |day|
1665
+ @it.should_not include(Date.parse("Dec #{day} 2008"))
1666
+ end
1667
+ end
1668
+
1669
+ it "should match February 28 for a non leap year when appropriate" do
1670
+ @it.should include(Date.parse("Feb 28 2005"))
1671
+ end
1672
+
1673
+ it "should match February 29 for a non leap year when appropriate" do
1674
+ @it.should include(Date.parse("Feb 29 1988"))
1675
+ end
1676
+ end
1677
+ end
1678
+
1679
+ describe RiCal::PropertyValue::RecurrenceRule::RecurringMonthDay do
1680
+
1681
+ describe "with a value of 1" do
1682
+ before(:each) do
1683
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringMonthDay.new(1)
1684
+ end
1685
+
1686
+ it "should match the first of each month" do
1687
+ (1..12).each do |month|
1688
+ @it.should include(Date.new(2008, month, 1))
1689
+ end
1690
+ end
1691
+
1692
+ it "should not match other days of the month" do
1693
+ (2..31).each do |day|
1694
+ @it.should_not include(Date.new(2008, 1, day))
1695
+ end
1696
+ end
1697
+
1698
+ describe "with a value of -1" do
1699
+ before(:each) do
1700
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringMonthDay.new(-1)
1701
+ end
1702
+
1703
+ it "should match the last of each month" do
1704
+ {
1705
+ 1 => 31, 2 => 29, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31,
1706
+ 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31
1707
+ }.each do |month, last|
1708
+ @it.should include(Date.new(2008, month, last))
1709
+ end
1710
+ @it.should include(Date.new(2007, 2, 28))
1711
+ end
1712
+
1713
+ it "should not match other days of the month" do
1714
+ (1..30).each do |day|
1715
+ @it.should_not include(Date.new(2008, 1, day))
1716
+ end
1717
+ end
1718
+ end
1719
+ end
1720
+ end
1721
+
1722
+ describe RiCal::PropertyValue::RecurrenceRule::RecurringYearDay do
1723
+
1724
+ describe "with a value of 20" do
1725
+ before(:each) do
1726
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(20)
1727
+ end
1728
+
1729
+ it "should include January 20 in a non-leap year" do
1730
+ @it.should include(Date.new(2007, 1, 20))
1731
+ end
1732
+
1733
+ it "should include January 20 in a leap year" do
1734
+ @it.should include(Date.new(2008, 1, 20))
1735
+ end
1736
+ end
1737
+
1738
+ describe "with a value of 60" do
1739
+ before(:each) do
1740
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(60)
1741
+ end
1742
+
1743
+ it "should include March 1 in a non-leap year" do
1744
+ @it.should include(Date.new(2007, 3, 1))
1745
+ end
1746
+
1747
+ it "should include February 29 in a leap year" do
1748
+ @it.should include(Date.new(2008, 2, 29))
1749
+ end
1750
+ end
1751
+
1752
+ describe "with a value of -1" do
1753
+ before(:each) do
1754
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(-1)
1755
+ end
1756
+
1757
+ it "should include December 31 in a non-leap year" do
1758
+ @it.should include(Date.new(2007,12, 31))
1759
+ end
1760
+
1761
+ it "should include December 31 in a leap year" do
1762
+ @it.should include(Date.new(2008,12, 31))
1763
+ end
1764
+ end
1765
+
1766
+ describe "with a value of -365" do
1767
+ before(:each) do
1768
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(-365)
1769
+ end
1770
+
1771
+ it "should include January 1 in a non-leap year" do
1772
+ @it.should include(Date.new(2007,1, 1))
1773
+ end
1774
+
1775
+ it "should include January 2 in a leap year" do
1776
+ @it.should include(Date.new(2008,1, 2))
1777
+ end
1778
+ end
1779
+
1780
+ describe "with a value of -366" do
1781
+ before(:each) do
1782
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringYearDay.new(-366)
1783
+ end
1784
+
1785
+ it "should not include January 1 in a non-leap year" do
1786
+ @it.should_not include(Date.new(2007,1, 1))
1787
+ end
1788
+
1789
+ it "should include January 1 in a leap year" do
1790
+ @it.should include(Date.new(2008,1, 1))
1791
+ end
1792
+ end
1793
+ end
1794
+
1795
+ describe RiCal::PropertyValue::RecurrenceRule::RecurringNumberedWeek do
1796
+ before(:each) do
1797
+ @it = RiCal::PropertyValue::RecurrenceRule::RecurringNumberedWeek.new(50)
1798
+ end
1799
+
1800
+ it "should not include Dec 10, 2000" do
1801
+ @it.should_not include(Date.new(2000, 12, 10))
1802
+ end
1803
+
1804
+ it "should include Dec 11, 2000" do
1805
+ @it.should include(Date.new(2000, 12, 11))
1806
+ end
1807
+
1808
+ it "should include Dec 17, 2000" do
1809
+ @it.should include(Date.new(2000, 12, 17))
1810
+ end
1811
+
1812
+ it "should not include Dec 18, 2000" do
1813
+ @it.should_not include(Date.new(2000, 12, 18))
1814
+ end
1815
+ end