ri_cal 0.5.0

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