ri_cal 0.5.0
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.
- data/History.txt +45 -0
- data/Manifest.txt +129 -0
- data/README.txt +394 -0
- data/Rakefile +31 -0
- data/bin/ri_cal +8 -0
- data/component_attributes/alarm.yml +10 -0
- data/component_attributes/calendar.yml +4 -0
- data/component_attributes/component_property_defs.yml +180 -0
- data/component_attributes/event.yml +45 -0
- data/component_attributes/freebusy.yml +16 -0
- data/component_attributes/journal.yml +35 -0
- data/component_attributes/timezone.yml +3 -0
- data/component_attributes/timezone_period.yml +11 -0
- data/component_attributes/todo.yml +46 -0
- data/copyrights.txt +1 -0
- data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
- data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
- data/docs/incrementers.txt +7 -0
- data/docs/rfc2445.pdf +0 -0
- data/lib/ri_cal.rb +144 -0
- data/lib/ri_cal/component.rb +247 -0
- data/lib/ri_cal/component/alarm.rb +21 -0
- data/lib/ri_cal/component/calendar.rb +219 -0
- data/lib/ri_cal/component/event.rb +60 -0
- data/lib/ri_cal/component/freebusy.rb +18 -0
- data/lib/ri_cal/component/journal.rb +30 -0
- data/lib/ri_cal/component/t_z_info_timezone.rb +123 -0
- data/lib/ri_cal/component/timezone.rb +196 -0
- data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
- data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
- data/lib/ri_cal/component/timezone/timezone_period.rb +53 -0
- data/lib/ri_cal/component/todo.rb +43 -0
- data/lib/ri_cal/core_extensions.rb +6 -0
- data/lib/ri_cal/core_extensions/array.rb +7 -0
- data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
- data/lib/ri_cal/core_extensions/date.rb +13 -0
- data/lib/ri_cal/core_extensions/date/conversions.rb +61 -0
- data/lib/ri_cal/core_extensions/date_time.rb +15 -0
- data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
- data/lib/ri_cal/core_extensions/object.rb +8 -0
- data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
- data/lib/ri_cal/core_extensions/string.rb +8 -0
- data/lib/ri_cal/core_extensions/string/conversions.rb +63 -0
- data/lib/ri_cal/core_extensions/time.rb +13 -0
- data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
- data/lib/ri_cal/core_extensions/time/conversions.rb +61 -0
- data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
- data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
- data/lib/ri_cal/floating_timezone.rb +32 -0
- data/lib/ri_cal/invalid_property_value.rb +8 -0
- data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
- data/lib/ri_cal/occurrence_enumerator.rb +206 -0
- data/lib/ri_cal/occurrence_period.rb +17 -0
- data/lib/ri_cal/parser.rb +138 -0
- data/lib/ri_cal/properties/alarm.rb +390 -0
- data/lib/ri_cal/properties/calendar.rb +164 -0
- data/lib/ri_cal/properties/event.rb +1526 -0
- data/lib/ri_cal/properties/freebusy.rb +594 -0
- data/lib/ri_cal/properties/journal.rb +1240 -0
- data/lib/ri_cal/properties/timezone.rb +151 -0
- data/lib/ri_cal/properties/timezone_period.rb +416 -0
- data/lib/ri_cal/properties/todo.rb +1562 -0
- data/lib/ri_cal/property_value.rb +149 -0
- data/lib/ri_cal/property_value/array.rb +27 -0
- data/lib/ri_cal/property_value/cal_address.rb +11 -0
- data/lib/ri_cal/property_value/date.rb +175 -0
- data/lib/ri_cal/property_value/date_time.rb +335 -0
- data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
- data/lib/ri_cal/property_value/date_time/time_machine.rb +181 -0
- data/lib/ri_cal/property_value/date_time/timezone_support.rb +96 -0
- data/lib/ri_cal/property_value/duration.rb +110 -0
- data/lib/ri_cal/property_value/geo.rb +11 -0
- data/lib/ri_cal/property_value/integer.rb +12 -0
- data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
- data/lib/ri_cal/property_value/period.rb +82 -0
- data/lib/ri_cal/property_value/recurrence_rule.rb +145 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +97 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
- data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
- data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
- data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +793 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +60 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +49 -0
- data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
- data/lib/ri_cal/property_value/text.rb +40 -0
- data/lib/ri_cal/property_value/uri.rb +11 -0
- data/lib/ri_cal/property_value/utc_offset.rb +33 -0
- data/lib/ri_cal/required_timezones.rb +55 -0
- data/ri_cal.gemspec +49 -0
- data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/spec/ri_cal/component/alarm_spec.rb +12 -0
- data/spec/ri_cal/component/calendar_spec.rb +54 -0
- data/spec/ri_cal/component/event_spec.rb +601 -0
- data/spec/ri_cal/component/freebusy_spec.rb +12 -0
- data/spec/ri_cal/component/journal_spec.rb +37 -0
- data/spec/ri_cal/component/t_z_info_timezone_spec.rb +36 -0
- data/spec/ri_cal/component/timezone_spec.rb +218 -0
- data/spec/ri_cal/component/todo_spec.rb +112 -0
- data/spec/ri_cal/component_spec.rb +224 -0
- data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
- data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
- data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
- data/spec/ri_cal/occurrence_enumerator_spec.rb +573 -0
- data/spec/ri_cal/parser_spec.rb +303 -0
- data/spec/ri_cal/property_value/date_spec.rb +53 -0
- data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
- data/spec/ri_cal/property_value/duration_spec.rb +126 -0
- data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
- data/spec/ri_cal/property_value/period_spec.rb +49 -0
- data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
- data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
- data/spec/ri_cal/property_value/text_spec.rb +25 -0
- data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
- data/spec/ri_cal/property_value_spec.rb +125 -0
- data/spec/ri_cal/required_timezones_spec.rb +67 -0
- data/spec/ri_cal_spec.rb +53 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +46 -0
- data/tasks/gem_loader/load_active_support.rb +3 -0
- data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
- data/tasks/ri_cal.rake +410 -0
- data/tasks/spec.rake +50 -0
- metadata +221 -0
|
@@ -0,0 +1,78 @@
|
|
|
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::CoreExtensions::String::Conversions do
|
|
6
|
+
context "#to_ri_cal_date_time_value" do
|
|
7
|
+
|
|
8
|
+
it "should produce a DateTime property for a valid RFC 2445 datetime string" do
|
|
9
|
+
"20090304T123456".to_ri_cal_date_time_value.should == RiCal::PropertyValue::DateTime.new(nil, :value => "20090304T123456")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should produce a DateTime property for a valid RFC 2445 datetime string with a TZID parameter" do
|
|
13
|
+
"TZID=America/New_York:20090304T123456".to_ri_cal_date_time_value.should == RiCal::PropertyValue::DateTime.new(nil, :params => {"TZID" => "America/New_York"}, :value => "20090304T123456")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should raise an InvalidPropertyValue error if the string is not a valid RFC 2445 datetime string" do
|
|
17
|
+
lambda {"20090304".to_ri_cal_date_time_value}.should raise_error(RiCal::InvalidPropertyValue)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "#to_ri_cal_duration_value" do
|
|
22
|
+
|
|
23
|
+
it "should produce a Duration property for a valid RFC 2445 duration string" do
|
|
24
|
+
"P1H".to_ri_cal_duration_value.should == RiCal::PropertyValue::Duration.new(nil, :value => "P1H")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should raise an InvalidPropertyValue error if the string is not a valid RFC 2445 datetime string" do
|
|
28
|
+
lambda {"20090304".to_ri_cal_duration_value}.should raise_error(RiCal::InvalidPropertyValue)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "#to_ri_cal_date_or_date_time_value" do
|
|
33
|
+
|
|
34
|
+
it "should produce a DateTime property for a valid RFC 2445 datetime string" do
|
|
35
|
+
"20090304T123456".to_ri_cal_date_or_date_time_value.should == RiCal::PropertyValue::DateTime.new(nil, :value => "20090304T123456")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should produce a DateTime property for a valid RFC 2445 datetime string with a TZID parameter" do
|
|
39
|
+
"TZID=America/New_York:20090304T123456".to_ri_cal_date_or_date_time_value.should == RiCal::PropertyValue::DateTime.new(nil, :params => {"TZID" => "America/New_York"}, :value => "20090304T123456")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should produce a Date property for a valid RFC 2445 date string" do
|
|
43
|
+
"20090304".to_ri_cal_date_or_date_time_value.should == RiCal::PropertyValue::Date.new(nil, :value => "20090304")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
it "should raise an InvalidPropertyValue error if the string is not a valid RFC 2445 date or datetime string" do
|
|
48
|
+
lambda {"2009/03/04".to_ri_cal_date_or_date_time_value}.should raise_error(RiCal::InvalidPropertyValue)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "#to_ri_cal_occurrence_list_value" do
|
|
53
|
+
|
|
54
|
+
it "should produce a DateTime property for a valid RFC 2445 datetime string" do
|
|
55
|
+
"20090304T123456".to_ri_cal_occurrence_list_value.should == RiCal::PropertyValue::DateTime.new(nil, :value => "20090304T123456")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should produce a DateTime property for a valid RFC 2445 datetime string with a TZID parameter" do
|
|
59
|
+
"TZID=America/New_York:20090304T123456".to_ri_cal_occurrence_list_value.should == RiCal::PropertyValue::DateTime.new(nil, :params => {"TZID" => "America/New_York"}, :value => "20090304T123456")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should produce a Date property for a valid RFC 2445 date string" do
|
|
63
|
+
"20090304".to_ri_cal_occurrence_list_value.should == RiCal::PropertyValue::Date.new(nil, :value => "20090304")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should produce a Period property for a valid RFC 2445 period string (two time format)" do
|
|
67
|
+
"20090304T012345/20090304T023456".to_ri_cal_occurrence_list_value.should == RiCal::PropertyValue::Period.new(nil, :value => "20090304T012345/20090304T023456")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should produce a Period property for a valid RFC 2445 period string (time and duration format)" do
|
|
71
|
+
"20090304T012345/P1H".to_ri_cal_occurrence_list_value.should == RiCal::PropertyValue::Period.new(nil, :value => "20090304T012345/P1H")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should raise an InvalidPropertyValue error if the string is not a valid RFC 2445 date or datetime string" do
|
|
75
|
+
lambda {"foobar".to_ri_cal_date_or_date_time_value}.should raise_error(RiCal::InvalidPropertyValue)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
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::CoreExtensions::Time::Calculations do
|
|
6
|
+
|
|
7
|
+
describe ".iso_week_num" do
|
|
8
|
+
|
|
9
|
+
it "should calculate week 1 for January 1, 2001 for a wkst of 1 (Monday)" do
|
|
10
|
+
Date.new(2001, 1,1).iso_week_num(1).should == 1
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should calculate week 1 for January 7, 2001 for a wkst of 1 (Monday)" do
|
|
14
|
+
Date.new(2001, 1,7).iso_week_num(1).should == 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should calculate week 2 for January 8, 2001 for a wkst of 1 (Monday)" do
|
|
18
|
+
Date.new(2001, 1,8).iso_week_num(1).should == 2
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should calculate week 52 for December 31, 2000 for a wkst of 1 (Monday)" do
|
|
22
|
+
Date.new(2000, 12,31).iso_week_num(1).should == 52
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should calculate week 52 for January 1, 2001 for a wkst of 2 (Tuesday)" do
|
|
26
|
+
Date.new(2001, 1, 1).iso_week_num(2).should == 52
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should calculate week 1 for Dec 31, 2003 for a wkst of 1 (Monday)" do
|
|
30
|
+
Date.new(2003, 12, 31).iso_week_num(1).should == 1
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe ".iso_year" do
|
|
35
|
+
it "should be 1999 for January 2 2000" do
|
|
36
|
+
Date.new(2000, 1, 2).iso_year(1).should == 1999
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should be 1998 for December 29, 1997" do
|
|
40
|
+
Date.new(1997, 12, 29).iso_year(1).should == 1998
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe ".iso_year_start" do
|
|
45
|
+
|
|
46
|
+
it "should calculate January 4 1999 for January 2 2000 for a wkst of 1 (Monday)" do
|
|
47
|
+
Date.new(2000, 1, 2).iso_year_start(1).to_s.should == Date.new(1999, 1, 4).to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should calculate January 3 2000 for January 3 2000 for a wkst of 1 (Monday)" do
|
|
51
|
+
Date.new(2000, 1, 3).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should calculate January 3 2000 for January 4 2000 for a wkst of 1 (Monday)" do
|
|
55
|
+
Date.new(2000, 1, 4).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should calculate January 3 2000 for December 31 2000 for a wkst of 1 (Monday)" do
|
|
59
|
+
Date.new(2000, 12, 31).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should calculate week January 1, 2001 for January 1, 2001 for a wkst of 1 (Monday)" do
|
|
63
|
+
Date.new(2001, 1,1).iso_year_start(1).should == Date.new(2001, 1, 1)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should calculate week January 1, 2001 for July 4, 2001 for a wkst of 1 (Monday)" do
|
|
67
|
+
Date.new(2001, 7,4).iso_year_start(1).should == Date.new(2001, 1, 1)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should calculate January 3 2000 for January 3 2000" do
|
|
71
|
+
Date.new(2000, 1, 3).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should calculate January 3 2000 for January 4 2000" do
|
|
75
|
+
Date.new(2000, 1, 4).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# it "should calculate week 1 for January 7, 2001 for a wkst of 1 (Monday)" do
|
|
79
|
+
# Date.new(2001, 1,7).iso_week_num(1).should == 1
|
|
80
|
+
# end
|
|
81
|
+
#
|
|
82
|
+
# it "should calculate week 2 for January 8, 2001 for a wkst of 1 (Monday)" do
|
|
83
|
+
# Date.new(2001, 1,8).iso_week_num(1).should == 2
|
|
84
|
+
# end
|
|
85
|
+
#
|
|
86
|
+
# it "should calculate week 52 for December 31, 2000 for a wkst of 1 (Monday)" do
|
|
87
|
+
# Date.new(2000, 12,31).iso_week_num(1).should == 52
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# it "should calculate week 52 for January 1, 2001 for a wkst of 2 (Tuesday)" do
|
|
91
|
+
# Date.new(2001, 1, 1).iso_week_num(2).should == 52
|
|
92
|
+
# end
|
|
93
|
+
#
|
|
94
|
+
# it "should calculate week 1 for Dec 31, 2003 for a wkst of 1 (Monday)" do
|
|
95
|
+
# Date.new(2003, 12, 31).iso_week_num(1).should == 1
|
|
96
|
+
# end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe "#iso_week_one" do
|
|
100
|
+
|
|
101
|
+
before(:each) do
|
|
102
|
+
@it = RiCal::CoreExtensions::Time::Calculations
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe "with a monday week start" do
|
|
106
|
+
it "should return Jan 3, 2000 for 2000" do
|
|
107
|
+
@it.iso_week_one(2000, 1).should == Date.new(2000, 1, 3)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should return Jan 1, 2001 for 2001" do
|
|
111
|
+
@it.iso_week_one(2001, 1).should == Date.new(2001, 1,1)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should return Dec 31, 2001 for 2002" do
|
|
115
|
+
@it.iso_week_one(2002, 1).should == Date.new(2001, 12, 31)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should return Dec 30, 2002 for 2003" do
|
|
119
|
+
@it.iso_week_one(2003, 1).should == Date.new(2002, 12, 30)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "should return Dec 29, 2003 for 2004" do
|
|
123
|
+
@it.iso_week_one(2004, 1).should == Date.new(2003, 12, 29)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "should return Jan 2, 2001 for 2001 with a Tuesday week start" do
|
|
128
|
+
@it.iso_week_one(2001, 2).should == Date.new(2001, 1, 2)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should return Jan 3, 2001 for 2001 with a Wednesday week start" do
|
|
132
|
+
@it.iso_week_one(2001, 3).should == Date.new(2001, 1, 3)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should return Jan 4, 2001 for 2001 with a Thursday week start" do
|
|
136
|
+
@it.iso_week_one(2001, 4).should == Date.new(2001, 1, 4)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should return Dec 29, 2000 for 2001 with a Friday week start" do
|
|
140
|
+
@it.iso_week_one(2001, 5).should == Date.new(2000, 12, 29)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should return Dec 30, 2000 for 2001 with a Saturday week start" do
|
|
144
|
+
@it.iso_week_one(2001, 6).should == Date.new(2000, 12, 30)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "should return Dec 31, 2000 for 2001 with a Sunday week start" do
|
|
148
|
+
@it.iso_week_one(2001, 0).should == Date.new(2000, 12, 31)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe ".leap_year?" do
|
|
153
|
+
it "should return true for 2000" do
|
|
154
|
+
Date.parse("1/3/2000").should be_leap_year
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "should return false for 2007" do
|
|
158
|
+
Date.parse("1/3/2007").should_not be_leap_year
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should return true for 2008" do
|
|
162
|
+
Date.parse("1/3/2008").should be_leap_year
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "should return false for 2100" do
|
|
166
|
+
Date.parse("1/3/2100").should_not be_leap_year
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
describe ".days_in_month" do
|
|
171
|
+
|
|
172
|
+
it "should return 29 for February in a leap year" do
|
|
173
|
+
Date.new(2008, 2, 1).days_in_month.should == 29
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "should return 28 for February in a non-leap year" do
|
|
177
|
+
Date.new(2009, 2, 1).days_in_month.should == 28
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "should return 31 for January in a leap year" do
|
|
181
|
+
Date.new(2008, 1, 1).days_in_month.should == 31
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should return 31 for January in a non-leap year" do
|
|
185
|
+
Date.new(2009, 1, 1).days_in_month.should == 31
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
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::CoreExtensions::Time::WeekDayPredicates do
|
|
6
|
+
|
|
7
|
+
describe ".nth_wday_in_month" do
|
|
8
|
+
it "should return Feb 28, 2005 for the 4th Monday for a date in February 2005" do
|
|
9
|
+
expected = RiCal::PropertyValue::Date.new(nil, :value => "20050228")
|
|
10
|
+
it =Date.parse("Feb 7, 2005").nth_wday_in_month(4, 1)
|
|
11
|
+
it.should == expected
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe ".nth_wday_in_month?" do
|
|
16
|
+
it "should return true for Feb 28, 2005 for the 4th Monday" do
|
|
17
|
+
Date.parse("Feb 28, 2005").nth_wday_in_month?(4, 1).should be
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe ".start_of_week_with_wkst" do
|
|
22
|
+
describe "for Wednesday Sept 10 1997" do
|
|
23
|
+
before(:each) do
|
|
24
|
+
@date = Date.parse("Sept 10, 1997")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should return a Date of Sept 7, 1997 00:00 for a wkst of 0 - Sunday" do
|
|
28
|
+
@date.start_of_week_with_wkst(0).should == Date.parse("Sept 7, 1997")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should return a Date of Sept 8, 1997 00:00 for a wkst of 1 - Monday" do
|
|
32
|
+
@date.start_of_week_with_wkst(1).should == Date.parse("Sept 8, 1997")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should return a Date of Sept 10, 1997 00:00 for a wkst of 3 - Wednesday" do
|
|
36
|
+
@date.start_of_week_with_wkst(3).should == Date.parse("Sept 10, 1997")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should return a Date of Sept 4, 1997 00:00 for a wkst of 4 - Thursday" do
|
|
40
|
+
@date.start_of_week_with_wkst(4).should == Date.parse("Sept 4, 1997")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,573 @@
|
|
|
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.rb])
|
|
4
|
+
|
|
5
|
+
def mock_enumerator(name, next_occurrence)
|
|
6
|
+
mock(name, :next_occurrence => next_occurrence, :bounded? => true, :empty? => false)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Note that this is more of a functional spec
|
|
10
|
+
describe RiCal::OccurrenceEnumerator do
|
|
11
|
+
|
|
12
|
+
Fr13Unbounded_Zulu = <<-TEXT
|
|
13
|
+
BEGIN:VEVENT
|
|
14
|
+
DTSTART:19970902T090000Z
|
|
15
|
+
EXDATE:19970902T090000Z
|
|
16
|
+
RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
|
|
17
|
+
END:VEVENT
|
|
18
|
+
TEXT
|
|
19
|
+
|
|
20
|
+
Fr13Unbounded_Eastern = <<-TEXT
|
|
21
|
+
BEGIN:VEVENT
|
|
22
|
+
DTSTART;TZID=US-Eastern:19970902T090000
|
|
23
|
+
EXDATE;TZID=US-Eastern:19970902T090000
|
|
24
|
+
RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
|
|
25
|
+
END:VEVENT
|
|
26
|
+
TEXT
|
|
27
|
+
|
|
28
|
+
Fr13UnboundedZuluExpectedFive = [
|
|
29
|
+
"19980213T090000Z",
|
|
30
|
+
"19980313T090000Z",
|
|
31
|
+
"19981113T090000Z",
|
|
32
|
+
"19990813T090000Z",
|
|
33
|
+
"20001013T090000Z"
|
|
34
|
+
].map {|start| src = <<-TEXT
|
|
35
|
+
BEGIN:VEVENT
|
|
36
|
+
DTSTART:#{start}
|
|
37
|
+
RECURRENCE-ID:#{start}
|
|
38
|
+
END:VEVENT
|
|
39
|
+
TEXT
|
|
40
|
+
RiCal.parse_string(src).first
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe ".occurrences" do
|
|
44
|
+
describe "with an unbounded component" do
|
|
45
|
+
before(:each) do
|
|
46
|
+
@it = RiCal.parse_string(Fr13Unbounded_Zulu).first
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should raise an ArgumentError with no options to limit result" do
|
|
50
|
+
lambda {@it.occurrences}.should raise_error(ArgumentError)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should have the right five occurrences when :count => 5 option is used" do
|
|
54
|
+
result = @it.occurrences(:count => 5)
|
|
55
|
+
result.should == Fr13UnboundedZuluExpectedFive
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe ".occurrences" do
|
|
62
|
+
before(:each) do
|
|
63
|
+
@it = RiCal.parse_string(Fr13Unbounded_Zulu).first
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe "with :starting specified" do
|
|
67
|
+
it "should exclude dates before :starting" do
|
|
68
|
+
result = @it.occurrences(:starting => Fr13UnboundedZuluExpectedFive[1].dtstart,
|
|
69
|
+
:before => Fr13UnboundedZuluExpectedFive[-1].dtstart)
|
|
70
|
+
result.map{|o|o.dtstart}.should == Fr13UnboundedZuluExpectedFive[1..-2].map{|e| e.dtstart}
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "with :before specified" do
|
|
75
|
+
it "should exclude dates after :before" do
|
|
76
|
+
result = @it.occurrences(:before => Fr13UnboundedZuluExpectedFive[3].dtstart,
|
|
77
|
+
:count => 5)
|
|
78
|
+
result.map{|o|o.dtstart}.should == Fr13UnboundedZuluExpectedFive[0..2].map{|e| e.dtstart}
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
describe ".each" do
|
|
85
|
+
describe " for Every Friday the 13th, forever" do
|
|
86
|
+
before(:each) do
|
|
87
|
+
event = RiCal.parse_string(Fr13Unbounded_Zulu).first
|
|
88
|
+
@result = []
|
|
89
|
+
event.each do |occurrence|
|
|
90
|
+
break if @result.length >= 5
|
|
91
|
+
@result << occurrence
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "should have the right first six occurrences" do
|
|
96
|
+
# TODO - Need to properly deal with timezones
|
|
97
|
+
@result.should == Fr13UnboundedZuluExpectedFive
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe RiCal::OccurrenceEnumerator::OccurrenceMerger do
|
|
105
|
+
before(:each) do
|
|
106
|
+
@merger = RiCal::OccurrenceEnumerator::OccurrenceMerger
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe ".for" do
|
|
110
|
+
it "should return an EmptyEnumerator if the rules parameter is nil" do
|
|
111
|
+
@merger.for(nil, nil).should == RiCal::OccurrenceEnumerator::EmptyRulesEnumerator
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should return an EmptyEnumerator if the rules parameter is empty" do
|
|
115
|
+
@merger.for(nil, []).should == RiCal::OccurrenceEnumerator::EmptyRulesEnumerator
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe "with a single rrule" do
|
|
119
|
+
before(:each) do
|
|
120
|
+
@component = mock("component", :dtstart => :dtstart_value)
|
|
121
|
+
@rrule = mock("rrule", :enumerator => :rrule_enumerator)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should return the enumerator the rrule" do
|
|
125
|
+
@merger.for(@component, [@rrule]).should == :rrule_enumerator
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should pass the component to the enumerator instantiation" do
|
|
129
|
+
@rrule.should_receive(:enumerator).with(@component)
|
|
130
|
+
@merger.for(@component, [@rrule])
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
describe "with multiple rrules" do
|
|
135
|
+
before(:each) do
|
|
136
|
+
@component = mock("component", :dtstart => :dtstart_value)
|
|
137
|
+
@enum1 = mock_enumerator("rrule_enumerator1", :occ1)
|
|
138
|
+
@enum2 = mock_enumerator("rrule_enumerator2", :occ2)
|
|
139
|
+
@rrule1 = mock("rrule", :enumerator => @enum1)
|
|
140
|
+
@rrule2 = mock("rrule", :enumerator => @enum2)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should return an instance of RiCal::OccurrenceEnumerator::OccurrenceMerger" do
|
|
144
|
+
@merger.for(@component, [@rrule1, @rrule2]).should be_kind_of(RiCal::OccurrenceEnumerator::OccurrenceMerger)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "should pass the component to the enumerator instantiation" do
|
|
148
|
+
@rrule1.should_receive(:enumerator).with(@component).and_return(@enum1)
|
|
149
|
+
@rrule2.should_receive(:enumerator).with(@component).and_return(@enum2)
|
|
150
|
+
@merger.for(@component, [@rrule1, @rrule2])
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should preload the next occurrences" do
|
|
154
|
+
@enum1.should_receive(:next_occurrence).and_return(:occ1)
|
|
155
|
+
@enum2.should_receive(:next_occurrence).and_return(:occ2)
|
|
156
|
+
@merger.for(@component, [@rrule1, @rrule2])
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
describe "#zulu_occurrence_range" do
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
describe "#next_occurence" do
|
|
165
|
+
|
|
166
|
+
describe "with unique nexts" do
|
|
167
|
+
before(:each) do
|
|
168
|
+
@enum1 = mock_enumerator("rrule_enumerator1",3)
|
|
169
|
+
@enum2 = mock_enumerator("rrule_enumerator2", 2)
|
|
170
|
+
@rrule1 = mock("rrule", :enumerator => @enum1)
|
|
171
|
+
@rrule2 = mock("rrule", :enumerator => @enum2)
|
|
172
|
+
@it = @merger.new(0, [@rrule1, @rrule2])
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "should return the earliest occurrence" do
|
|
176
|
+
@it.next_occurrence.should == 2
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "should advance the enumerator which returned the result" do
|
|
180
|
+
@enum2.should_receive(:next_occurrence).and_return(4)
|
|
181
|
+
@it.next_occurrence
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should not advance the other enumerator" do
|
|
185
|
+
@enum1.should_not_receive(:next_occurrence)
|
|
186
|
+
@it.next_occurrence
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "should properly update the next array" do
|
|
190
|
+
@enum2.stub!(:next_occurrence).and_return(4)
|
|
191
|
+
@it.next_occurrence
|
|
192
|
+
@it.nexts.should == [3, 4]
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe "with duplicated nexts" do
|
|
197
|
+
before(:each) do
|
|
198
|
+
@enum1 = mock_enumerator("rrule_enumerator1", 2)
|
|
199
|
+
@enum2 = mock_enumerator("rrule_enumerator2", 2)
|
|
200
|
+
@rrule1 = mock("rrule", :enumerator => @enum1)
|
|
201
|
+
@rrule2 = mock("rrule", :enumerator => @enum2)
|
|
202
|
+
@it = @merger.new(0, [@rrule1, @rrule2])
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "should return the earliest occurrence" do
|
|
206
|
+
@it.next_occurrence.should == 2
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it "should advance both enumerators" do
|
|
210
|
+
@enum1.should_receive(:next_occurrence).and_return(5)
|
|
211
|
+
@enum2.should_receive(:next_occurrence).and_return(4)
|
|
212
|
+
@it.next_occurrence
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should properly update the next array" do
|
|
216
|
+
@enum1.stub!(:next_occurrence).and_return(5)
|
|
217
|
+
@enum2.stub!(:next_occurrence).and_return(4)
|
|
218
|
+
@it.next_occurrence
|
|
219
|
+
@it.nexts.should == [5, 4]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe "with all enumerators at end" do
|
|
225
|
+
before(:each) do
|
|
226
|
+
@enum1 = mock_enumerator("rrule_enumerator1", nil)
|
|
227
|
+
@enum2 = mock_enumerator("rrule_enumerator2", nil)
|
|
228
|
+
@rrule1 = mock("rrule", :enumerator => @enum1)
|
|
229
|
+
@rrule2 = mock("rrule", :enumerator => @enum2)
|
|
230
|
+
@it = @merger.new(0, [@rrule1, @rrule2])
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "should return nil" do
|
|
234
|
+
@it.next_occurrence.should == nil
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "should not advance the enumerators which returned the result" do
|
|
238
|
+
@enum1.should_not_receive(:next_occurrence)
|
|
239
|
+
@enum2.should_not_receive(:next_occurrence)
|
|
240
|
+
@it.next_occurrence
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
context "Ticket #4 from paulsm" do
|
|
246
|
+
it "should produce 4 occurrences" do
|
|
247
|
+
cal = RiCal.parse_string <<ENDCAL
|
|
248
|
+
BEGIN:VCALENDAR
|
|
249
|
+
METHOD:PUBLISH
|
|
250
|
+
PRODID:-//Apple Inc.//iCal 3.0//EN
|
|
251
|
+
CALSCALE:GREGORIAN
|
|
252
|
+
X-WR-CALNAME:Australian32Holidays
|
|
253
|
+
X-WR-CALDESC:Australian Public Holidays. Compiled from http://www.indust
|
|
254
|
+
rialrelations.nsw.gov.au/holidays/default.html and the links for the oth
|
|
255
|
+
er states at the bottom of that page
|
|
256
|
+
X-WR-RELCALID:AC1E4CE8-6690-49F6-A144-2F8891DFFD8D
|
|
257
|
+
VERSION:2.0
|
|
258
|
+
X-WR-TIMEZONE:Australia/Sydney
|
|
259
|
+
BEGIN:VEVENT
|
|
260
|
+
SEQUENCE:8
|
|
261
|
+
TRANSP:OPAQUE
|
|
262
|
+
UID:5B5579F3-2137-11D7-B491-00039301B0C2
|
|
263
|
+
DTSTART;VALUE=DATE:20020520
|
|
264
|
+
DTSTAMP:20060602T045619Z
|
|
265
|
+
SUMMARY:Adelaide Cup Carnival and Volunteers Day (SA)
|
|
266
|
+
EXDATE;VALUE=DATE:20060515
|
|
267
|
+
CREATED:20080916T000924Z
|
|
268
|
+
DTEND;VALUE=DATE:20020521
|
|
269
|
+
RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20070520;BYMONTH=5;BYDAY=3MO
|
|
270
|
+
END:VEVENT
|
|
271
|
+
END:VCALENDAR
|
|
272
|
+
ENDCAL
|
|
273
|
+
cal.first.events.first.occurrences.length.should == 4
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
context "Ticket #2 from paulsm" do
|
|
278
|
+
before(:each) do
|
|
279
|
+
cals = RiCal.parse_string <<ENDCAL
|
|
280
|
+
BEGIN:VCALENDAR
|
|
281
|
+
X-WR-TIMEZONE:America/New_York
|
|
282
|
+
PRODID:-//Apple Inc.//iCal 3.0//EN
|
|
283
|
+
CALSCALE:GREGORIAN
|
|
284
|
+
X-WR-CALNAME:test
|
|
285
|
+
VERSION:2.0
|
|
286
|
+
X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
|
|
287
|
+
X-APPLE-CALENDAR-COLOR:#2CA10B
|
|
288
|
+
BEGIN:VTIMEZONE
|
|
289
|
+
TZID:US/Eastern
|
|
290
|
+
BEGIN:DAYLIGHT
|
|
291
|
+
TZOFFSETFROM:-0500
|
|
292
|
+
TZOFFSETTO:-0400
|
|
293
|
+
DTSTART:20070311T020000
|
|
294
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
|
295
|
+
TZNAME:EDT
|
|
296
|
+
END:DAYLIGHT
|
|
297
|
+
BEGIN:STANDARD
|
|
298
|
+
TZOFFSETFROM:-0400
|
|
299
|
+
TZOFFSETTO:-0500
|
|
300
|
+
DTSTART:20071104T020000
|
|
301
|
+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
|
302
|
+
TZNAME:EST
|
|
303
|
+
END:STANDARD
|
|
304
|
+
END:VTIMEZONE
|
|
305
|
+
BEGIN:VEVENT
|
|
306
|
+
SEQUENCE:5
|
|
307
|
+
TRANSP:OPAQUE
|
|
308
|
+
UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
|
|
309
|
+
DTSTART;TZID=US/Eastern:20090224T090000
|
|
310
|
+
DTSTAMP:20090225T000908Z
|
|
311
|
+
SUMMARY:Test Event
|
|
312
|
+
CREATED:20090225T000839Z
|
|
313
|
+
DTEND;TZID=US/Eastern:20090224T100000
|
|
314
|
+
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
|
|
315
|
+
END:VEVENT
|
|
316
|
+
END:VCALENDAR
|
|
317
|
+
ENDCAL
|
|
318
|
+
@event = cals.first.events.first
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
it "the event should be enumerable" do
|
|
323
|
+
lambda {@event.occurrences}.should_not raise_error
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
context "Lighthouse bug #3" do
|
|
328
|
+
before(:each) do
|
|
329
|
+
cals = RiCal.parse_string <<ENDCAL
|
|
330
|
+
BEGIN:VCALENDAR
|
|
331
|
+
VERSION:2.0
|
|
332
|
+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
|
333
|
+
BEGIN:VTIMEZONE
|
|
334
|
+
TZID:/mozilla.org/20070129_1/Europe/Paris
|
|
335
|
+
X-LIC-LOCATION:Europe/Paris
|
|
336
|
+
BEGIN:DAYLIGHT
|
|
337
|
+
TZOFFSETFROM:+0100
|
|
338
|
+
TZOFFSETTO:+0200
|
|
339
|
+
TZNAME:CEST
|
|
340
|
+
DTSTART:19700329T020000
|
|
341
|
+
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
|
|
342
|
+
END:DAYLIGHT
|
|
343
|
+
BEGIN:STANDARD
|
|
344
|
+
TZOFFSETFROM:+0200
|
|
345
|
+
TZOFFSETTO:+0100
|
|
346
|
+
TZNAME:CET
|
|
347
|
+
DTSTART:19701025T030000
|
|
348
|
+
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
|
|
349
|
+
END:STANDARD
|
|
350
|
+
END:VTIMEZONE
|
|
351
|
+
BEGIN:VEVENT
|
|
352
|
+
CREATED:20070606T141629Z
|
|
353
|
+
LAST-MODIFIED:20070606T154611Z
|
|
354
|
+
DTSTAMP:20070607T120859Z
|
|
355
|
+
UID:5d1ae55f-3910-4de9-8b65-d652768fb2f2
|
|
356
|
+
SUMMARY:Lundi de Pâques
|
|
357
|
+
DTSTART;VALUE=DATE;TZID=/mozilla.org/20070129_1/Europe/Paris:20070409
|
|
358
|
+
DTEND;VALUE=DATE;TZID=/mozilla.org/20070129_1/Europe/Paris:20070410
|
|
359
|
+
CATEGORIES:Jours fériés
|
|
360
|
+
END:VEVENT
|
|
361
|
+
END:VCALENDAR
|
|
362
|
+
ENDCAL
|
|
363
|
+
@event = cals.first.events.first
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
it "should be able to enumerate occurrences" do
|
|
367
|
+
@event.occurrences.should == [@event]
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
context "An event with a DATE dtstart, Ticket #6" do
|
|
372
|
+
before(:each) do
|
|
373
|
+
cal = RiCal.parse_string <<ENDCAL
|
|
374
|
+
BEGIN:VCALENDAR
|
|
375
|
+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
|
376
|
+
VERSION:2.0
|
|
377
|
+
BEGIN:VEVENT
|
|
378
|
+
CREATED:20090520T092032Z
|
|
379
|
+
LAST-MODIFIED:20090520T092052Z
|
|
380
|
+
DTSTAMP:20090520T092032Z
|
|
381
|
+
UID:d41c124a-65c3-400e-bd04-1d2ee7b98352
|
|
382
|
+
SUMMARY:event2
|
|
383
|
+
RRULE:FREQ=MONTHLY;INTERVAL=1
|
|
384
|
+
DTSTART;VALUE=DATE:20090603
|
|
385
|
+
DTEND;VALUE=DATE:20090604
|
|
386
|
+
TRANSP:TRANSPARENT
|
|
387
|
+
END:VEVENT
|
|
388
|
+
END:VCALENDAR
|
|
389
|
+
ENDCAL
|
|
390
|
+
@occurrences = cal.first.events.first.occurrences(
|
|
391
|
+
:after => Date.parse('01/01/1990'),
|
|
392
|
+
:before => Date.parse("01/01/2010")
|
|
393
|
+
)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
it "should produce the right dtstart values" do
|
|
397
|
+
@occurrences.map {|o| o.dtstart}.should == [
|
|
398
|
+
Date.parse("2009-06-03"),
|
|
399
|
+
Date.parse("2009-07-03"),
|
|
400
|
+
Date.parse("2009-08-03"),
|
|
401
|
+
Date.parse("2009-09-03"),
|
|
402
|
+
Date.parse("2009-10-03"),
|
|
403
|
+
Date.parse("2009-11-03"),
|
|
404
|
+
Date.parse("2009-12-03")
|
|
405
|
+
]
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
it "should produce events whose dtstarts are all dates" do
|
|
409
|
+
@occurrences.all? {|o| o.dtstart.class == ::Date}.should be_true
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "should produce the right dtend values" do
|
|
413
|
+
@occurrences.map {|o| o.dtend}.should == [
|
|
414
|
+
Date.parse("2009-06-04"),
|
|
415
|
+
Date.parse("2009-07-04"),
|
|
416
|
+
Date.parse("2009-08-04"),
|
|
417
|
+
Date.parse("2009-09-04"),
|
|
418
|
+
Date.parse("2009-10-04"),
|
|
419
|
+
Date.parse("2009-11-04"),
|
|
420
|
+
Date.parse("2009-12-04")
|
|
421
|
+
]
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it "should produce events whose dtstends are all dates" do
|
|
425
|
+
@occurrences.all? {|o| o.dtend.class == ::Date}.should be_true
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
context "bounded? bug" do
|
|
429
|
+
before(:each) do
|
|
430
|
+
events = RiCal.parse_string rectify_ical <<-ENDCAL
|
|
431
|
+
BEGIN:VEVENT
|
|
432
|
+
EXDATE:20090114T163000
|
|
433
|
+
EXDATE:20090128T163000
|
|
434
|
+
EXDATE:20090121T163000
|
|
435
|
+
EXDATE:20090211T163000
|
|
436
|
+
EXDATE:20090204T163000
|
|
437
|
+
EXDATE:20090218T163000
|
|
438
|
+
TRANSP:OPAQUE
|
|
439
|
+
DTSTAMP;VALUE=DATE-TIME:20090107T024340Z
|
|
440
|
+
CREATED;VALUE=DATE-TIME:20090107T024012Z
|
|
441
|
+
DTEND;TZID=US/Mountain;VALUE=DATE-TIME:20090114T180000
|
|
442
|
+
DTSTART;TZID=US/Mountain;VALUE=DATE-TIME:20090114T163000
|
|
443
|
+
UID:15208112-E0FA-4A7C-954C-CFDF19D1B0E7
|
|
444
|
+
RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20090219T065959Z
|
|
445
|
+
SUMMARY:Wild Rose XC/Skate Training Series
|
|
446
|
+
SEQUENCE:11
|
|
447
|
+
LOCATION:Mountain Dell Golf Course
|
|
448
|
+
END:VEVENT
|
|
449
|
+
ENDCAL
|
|
450
|
+
@event = events.first
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
it "should be able to enumerate occurrences" do
|
|
454
|
+
@event.should be_bounded
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
context "EXDATES with timezones bug" do
|
|
459
|
+
before(:each) do
|
|
460
|
+
cals = RiCal.parse_string rectify_ical <<-ENDCAL
|
|
461
|
+
BEGIN:VCALENDAR
|
|
462
|
+
METHOD:PUBLISH
|
|
463
|
+
PRODID:-//Apple Inc.//iCal 3.0//EN
|
|
464
|
+
CALSCALE:GREGORIAN
|
|
465
|
+
X-WR-CALNAME:Utah Cycling
|
|
466
|
+
X-WR-RELCALID:BF579011-36BF-49C6-8C7D-E96F03DE8055
|
|
467
|
+
VERSION:2.0
|
|
468
|
+
X-WR-TIMEZONE:US/Mountain
|
|
469
|
+
BEGIN:VTIMEZONE
|
|
470
|
+
TZID:US/Mountain
|
|
471
|
+
BEGIN:DAYLIGHT
|
|
472
|
+
TZOFFSETFROM:-0700
|
|
473
|
+
TZOFFSETTO:-0600
|
|
474
|
+
DTSTART:20070311T020000
|
|
475
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
|
476
|
+
TZNAME:MDT
|
|
477
|
+
END:DAYLIGHT
|
|
478
|
+
BEGIN:STANDARD
|
|
479
|
+
TZOFFSETFROM:-0600
|
|
480
|
+
TZOFFSETTO:-0700
|
|
481
|
+
DTSTART:20071104T020000
|
|
482
|
+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
|
483
|
+
TZNAME:MST
|
|
484
|
+
END:STANDARD
|
|
485
|
+
END:VTIMEZONE
|
|
486
|
+
BEGIN:VEVENT
|
|
487
|
+
SEQUENCE:11
|
|
488
|
+
TRANSP:OPAQUE
|
|
489
|
+
UID:15208112-E0FA-4A7C-954C-CFDF19D1B0E7
|
|
490
|
+
DTSTART;TZID=US/Mountain:20090114T163000
|
|
491
|
+
DTSTAMP:20090107T024340Z
|
|
492
|
+
SUMMARY:Wild Rose XC/Skate Training Series
|
|
493
|
+
EXDATE;TZID=US/Mountain:20090114T163000
|
|
494
|
+
EXDATE;TZID=US/Mountain:20090128T163000
|
|
495
|
+
EXDATE;TZID=US/Mountain:20090121T163000
|
|
496
|
+
EXDATE;TZID=US/Mountain:20090211T163000
|
|
497
|
+
EXDATE;TZID=US/Mountain:20090204T163000
|
|
498
|
+
EXDATE;TZID=US/Mountain:20090218T163000
|
|
499
|
+
CREATED:20090107T024012Z
|
|
500
|
+
DTEND;TZID=US/Mountain:20090114T180000
|
|
501
|
+
LOCATION:Mountain Dell Golf Course
|
|
502
|
+
RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20090219T065959Z
|
|
503
|
+
END:VEVENT
|
|
504
|
+
END:VCALENDAR
|
|
505
|
+
ENDCAL
|
|
506
|
+
@event = cals.first.events.first
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
it "should have no occurrences" do
|
|
510
|
+
@event.occurrences.length.should == 0
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
describe "#zulu_occurrence_range" do
|
|
516
|
+
context "For an unbounded recurring event" do
|
|
517
|
+
before(:each) do
|
|
518
|
+
@event = RiCal.Event do |e|
|
|
519
|
+
e.dtstart = "TZID=America/New_York:20090525T143500"
|
|
520
|
+
e.dtend = "TZID=America/New_York:20090525T153500"
|
|
521
|
+
e.add_rrule("FREQ=DAILY")
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
it "should return an array with the first dtstart and nil" do
|
|
525
|
+
@event.zulu_occurrence_range.should == [DateTime.civil(2009,5,25,18,35,00, 0), nil]
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
context "For a bounded recurring event" do
|
|
531
|
+
before(:each) do
|
|
532
|
+
@event = RiCal.Event do |e|
|
|
533
|
+
e.dtstart = "TZID=America/New_York:20090525T143500"
|
|
534
|
+
e.dtend = "TZID=America/New_York:20090525T153500"
|
|
535
|
+
e.add_rrule("FREQ=DAILY;COUNT=3")
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
it "should return an array with the first dtstart last dtend converted to utc" do
|
|
539
|
+
@event.zulu_occurrence_range.should == [DateTime.civil(2009,5,25,18,35,00, 0), DateTime.civil(2009,5,27,19,35,00, 0)]
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
context "For an event with no recurrence rules" do
|
|
545
|
+
context "with a non-floating dtstart and dtend" do
|
|
546
|
+
before(:each) do
|
|
547
|
+
@event = RiCal.Event do |e|
|
|
548
|
+
e.dtstart = "TZID=America/New_York:20090525T143500"
|
|
549
|
+
e.dtend = "TZID=America/New_York:20090525T153500"
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
it "should return an array with dtstart and dtend converted to zulu time" do
|
|
554
|
+
@event.zulu_occurrence_range.should == [DateTime.civil(2009,5,25,18,35,00, 0), DateTime.civil(2009,5,25,19,35,00, 0)]
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
context "with a floating dtstart and dtend" do
|
|
558
|
+
before(:each) do
|
|
559
|
+
@event = RiCal.Event do |e|
|
|
560
|
+
e.dtstart = "20090525T143500"
|
|
561
|
+
e.dtend = "20090525T153500"
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
it "should return an array with dtstart in the first timezone and dtend in the last time zone converted to zulu time" do
|
|
566
|
+
@event.zulu_occurrence_range.should == [DateTime.civil(2009,5,25,2,35,00, 0), DateTime.civil(2009,5,26,3,35,00, 0)]
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
end
|