demingfactor-ri_cal 0.9.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.
- checksums.yaml +7 -0
- data/History.txt +402 -0
- data/Manifest.txt +161 -0
- data/README.txt +410 -0
- data/Rakefile +69 -0
- data/VERSION +1 -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/component/alarm.rb +19 -0
- data/lib/ri_cal/component/calendar.rb +257 -0
- data/lib/ri_cal/component/event.rb +58 -0
- data/lib/ri_cal/component/freebusy.rb +16 -0
- data/lib/ri_cal/component/journal.rb +27 -0
- data/lib/ri_cal/component/non_standard.rb +33 -0
- data/lib/ri_cal/component/t_z_info_timezone.rb +153 -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 +76 -0
- data/lib/ri_cal/component/timezone.rb +197 -0
- data/lib/ri_cal/component/todo.rb +42 -0
- data/lib/ri_cal/component.rb +256 -0
- data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
- data/lib/ri_cal/core_extensions/array.rb +7 -0
- data/lib/ri_cal/core_extensions/date/conversions.rb +56 -0
- data/lib/ri_cal/core_extensions/date.rb +13 -0
- data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
- data/lib/ri_cal/core_extensions/date_time.rb +15 -0
- data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
- data/lib/ri_cal/core_extensions/object.rb +8 -0
- data/lib/ri_cal/core_extensions/string/conversions.rb +57 -0
- data/lib/ri_cal/core_extensions/string.rb +8 -0
- data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
- data/lib/ri_cal/core_extensions/time/conversions.rb +42 -0
- data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
- data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +55 -0
- data/lib/ri_cal/core_extensions/time.rb +14 -0
- data/lib/ri_cal/core_extensions.rb +11 -0
- data/lib/ri_cal/fast_date_time.rb +234 -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_identifier.rb +20 -0
- data/lib/ri_cal/occurrence_enumerator.rb +265 -0
- data/lib/ri_cal/occurrence_period.rb +17 -0
- data/lib/ri_cal/parser.rb +148 -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 +1523 -0
- data/lib/ri_cal/properties/freebusy.rb +593 -0
- data/lib/ri_cal/properties/journal.rb +1237 -0
- data/lib/ri_cal/properties/timezone.rb +150 -0
- data/lib/ri_cal/properties/timezone_period.rb +416 -0
- data/lib/ri_cal/properties/todo.rb +1559 -0
- data/lib/ri_cal/properties.rb +12 -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 +184 -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 +159 -0
- data/lib/ri_cal/property_value/date_time/timezone_support.rb +100 -0
- data/lib/ri_cal/property_value/date_time.rb +359 -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 +86 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +100 -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/occurrence_incrementer/by_day_incrementer.rb +86 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +38 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +69 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +80 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +106 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +43 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +135 -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 +64 -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 +53 -0
- data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
- data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
- data/lib/ri_cal/property_value/recurrence_rule.rb +154 -0
- data/lib/ri_cal/property_value/text.rb +44 -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/property_value/zulu_date_time.rb +34 -0
- data/lib/ri_cal/property_value.rb +159 -0
- data/lib/ri_cal/required_timezones.rb +55 -0
- data/lib/ri_cal.rb +187 -0
- data/parked_specs/ri_cal/claudio_a_bug_spec.rb +100 -0
- data/performance/empty_propval/subject.rb +43 -0
- data/performance/paris_eastern/subject.rb +90 -0
- data/performance/penultimate_weekday/subject.rb +15 -0
- data/performance/psm_big_enum/ical.ics +3171 -0
- data/performance/psm_big_enum/subject.rb +16 -0
- data/performance/utah_cycling/subject.rb +55 -0
- data/ri_cal.gemspec +244 -0
- data/script/benchmark_subject +23 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/profile_subject +29 -0
- data/script/txt2html +71 -0
- data/spec/ri_cal/bugreports_spec.rb +276 -0
- data/spec/ri_cal/component/alarm_spec.rb +12 -0
- data/spec/ri_cal/component/calendar_spec.rb +88 -0
- data/spec/ri_cal/component/event_spec.rb +735 -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 +60 -0
- data/spec/ri_cal/component/timezone_spec.rb +236 -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/fast_date_time_spec.rb +77 -0
- data/spec/ri_cal/inf_loop_spec.rb +78 -0
- data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
- data/spec/ri_cal/parser_spec.rb +337 -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 +63 -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 +50 -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 +412 -0
- data/tasks/spec.rake +102 -0
- metadata +246 -0
@@ -0,0 +1,735 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
|
5
|
+
|
6
|
+
describe RiCal::Component::Event do
|
7
|
+
|
8
|
+
context "with change management properties" do
|
9
|
+
it "should use zulu time for all change management datetime properties" do
|
10
|
+
new_york_offset = Rational(-1, 6)
|
11
|
+
cal = RiCal.Calendar
|
12
|
+
event = RiCal::Component::Event.new(cal)
|
13
|
+
event.dtstamp = result_time_in_zone(2010, 4, 1, 9, 23, 45, "America/New_York", new_york_offset)
|
14
|
+
event.created = result_time_in_zone(2010, 4, 1, 9, 23, 45, "America/New_York", new_york_offset)
|
15
|
+
event.last_modified = result_time_in_zone(2010, 4, 1, 12, 23, 45, "America/New_York", new_york_offset)
|
16
|
+
event.to_s.should == "BEGIN:VEVENT
|
17
|
+
CREATED;VALUE=DATE-TIME:20100401T132345Z
|
18
|
+
DTSTAMP;VALUE=DATE-TIME:20100401T132345Z
|
19
|
+
LAST-MODIFIED;VALUE=DATE-TIME:20100401T162345Z
|
20
|
+
END:VEVENT
|
21
|
+
"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context ".finish_time" do
|
26
|
+
it "should be the end of the start day for an event with a date dtstart and no dtend or duration" do
|
27
|
+
@it = RiCal.Event do |evt|
|
28
|
+
evt.dtstart = "20090704"
|
29
|
+
end
|
30
|
+
@it.finish_time.should == DateTime.parse("20090704T235959")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be the end of the end day for an event with a date dtstart and a dtend" do
|
34
|
+
@it = RiCal.Event do |evt|
|
35
|
+
evt.dtstart = "20090704"
|
36
|
+
evt.dtend = "20090706"
|
37
|
+
end
|
38
|
+
@it.finish_time.should == DateTime.parse("20090706T235959")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be the start time for an event with a datetime dtstart and no dtend or duration" do
|
42
|
+
@it = RiCal.Event do |evt|
|
43
|
+
evt.dtstart = "20090704T013000Z"
|
44
|
+
end
|
45
|
+
@it.finish_time.should == DateTime.parse("20090704T013000Z")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be the end time for an event with a datetime dtend" do
|
49
|
+
@it = RiCal.Event do |evt|
|
50
|
+
evt.dtstart = "20090704"
|
51
|
+
evt.dtend = "20090706T120000"
|
52
|
+
end
|
53
|
+
@it.finish_time.should == DateTime.parse("20090706T120000")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be the end time for an event with a datetime dtstart and a duration" do
|
57
|
+
@it = RiCal.Event do |evt|
|
58
|
+
evt.dtstart = "20090704T120000Z"
|
59
|
+
evt.duration = "PT1H30M"
|
60
|
+
end
|
61
|
+
@it.finish_time.should == DateTime.parse("20090704T133000Z")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should uset the timezone of dtstart when event has a duration" do
|
65
|
+
@it = RiCal.Event do |evt|
|
66
|
+
evt.dtstart = "TZID=Australia/Sydney:20090712T200000"
|
67
|
+
evt.duration = "PT1H"
|
68
|
+
end
|
69
|
+
@it.finish_time.should == DateTime.parse("2009-07-12T21:00:00+10:00")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context ".before_range?" do
|
74
|
+
context "with a Date dtstart and no dtend" do
|
75
|
+
before(:each) do
|
76
|
+
@it = RiCal.Event do |evt|
|
77
|
+
evt.dtstart = "20090704"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should be false if the range start is a date before the start date" do
|
82
|
+
@it.before_range?([Date.parse("20090703"), :anything]).should_not be
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should be false if the range start is the start date" do
|
86
|
+
@it.before_range?([Date.parse("20090704"), :anything]).should_not be
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should be true if the range start is a date after the start date" do
|
90
|
+
@it.before_range?([Date.parse("20090705"), :anything]).should be
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "with a Date dtstart and date dtend" do
|
95
|
+
before(:each) do
|
96
|
+
@it = RiCal.Event do |evt|
|
97
|
+
evt.dtstart = "20090704"
|
98
|
+
evt.dtend = "20090706"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should be false if the range start is a date before the end date" do
|
103
|
+
@it.before_range?([Date.parse("20090705"), :anything]).should_not be
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should be false if the range start is the end date" do
|
107
|
+
@it.before_range?([Date.parse("20090706"), :anything]).should_not be
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should be true if the range start is a date after the end date" do
|
111
|
+
@it.before_range?([Date.parse("20090707"), :anything]).should be
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "bug report from Noboyuki Tomizawa" do
|
117
|
+
before(:each) do
|
118
|
+
|
119
|
+
@it = RiCal.Calendar do |cal|
|
120
|
+
cal.event do |event|
|
121
|
+
event.description = "test"
|
122
|
+
event.dtstart = "TZID=Asia/Tokyo:20090530T123000"
|
123
|
+
event.dtend = "TZID=Asia/Tokyo:20090530T123001"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should not fail" do
|
129
|
+
lambda {@it.export}.should_not raise_error
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "rdate property methods" do
|
134
|
+
before(:each) do
|
135
|
+
@event = RiCal.Event do
|
136
|
+
rdate "20090101"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "#rdate=" do
|
141
|
+
|
142
|
+
it "should accept a single Date and replace the existing rdate" do
|
143
|
+
@event.rdate = Date.parse("20090102")
|
144
|
+
@event.rdate.should == [[Date.parse("20090102")]]
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should accept a single rfc2445 date format string and replace the existing rdate" do
|
148
|
+
@event.rdate = "20090102"
|
149
|
+
@event.rdate.should == [[Date.parse("20090102")]]
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should accept a single DateTime and replace the existing rdate" do
|
153
|
+
@event.rdate = DateTime.parse("20090102T012345")
|
154
|
+
@event.rdate.should == [[DateTime.parse("20090102T012345")]]
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should accept a single Time and replace the existing rdate" do
|
158
|
+
::RiCal::PropertyValue::DateTime.default_tzid = 'UTC'
|
159
|
+
@event.rdate = Time.local(2009, 1, 2, 1, 23, 45)
|
160
|
+
@event.rdate.should == [[result_time_in_zone(2009, 1, 2, 1, 23, 45, "UTC")]]
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should accept a single rfc2445 date-time format string and replace the existing rdate" do
|
164
|
+
@event.rdate = "20090102T012345"
|
165
|
+
@event.rdate.should == [[DateTime.parse("20090102T012345")]]
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should accept a tzid prefixed rfc2445 date-time format string and replace the existing rdate" do
|
169
|
+
@event.rdate = "TZID=America/New_York:20090102T012345"
|
170
|
+
@event.rdate.should == [[result_time_in_zone(2009, 1, 2, 1, 23, 45, "America/New_York")]]
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
context "comment property methods" do
|
178
|
+
before(:each) do
|
179
|
+
@event = RiCal.Event
|
180
|
+
@event.comment = "Comment"
|
181
|
+
end
|
182
|
+
|
183
|
+
context "#comment=" do
|
184
|
+
it "should result in a single comment for the event" do
|
185
|
+
@event.comment.should == ["Comment"]
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should replace existing comments" do
|
189
|
+
@event.comment = "Replacement"
|
190
|
+
@event.comment.should == ["Replacement"]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "#comments=" do
|
195
|
+
it "should result in a multiple comments for the event replacing existing comments" do
|
196
|
+
@event.comments = "New1", "New2"
|
197
|
+
@event.comment.should == ["New1", "New2"]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context "#add_comment" do
|
202
|
+
it "should add a single comment" do
|
203
|
+
@event.add_comment "New1"
|
204
|
+
@event.comment.should == ["Comment", "New1"]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "#add_comments" do
|
209
|
+
it "should add multiple comments" do
|
210
|
+
@event.add_comments "New1", "New2"
|
211
|
+
@event.comment.should == ["Comment", "New1", "New2"]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context "#remove_comment" do
|
216
|
+
it "should remove a single comment" do
|
217
|
+
@event.add_comment "New1"
|
218
|
+
@event.remove_comment "Comment"
|
219
|
+
@event.comment.should == ["New1"]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context "#remove_comments" do
|
224
|
+
it "should remove multiple comments" do
|
225
|
+
@event.add_comments "New1", "New2", "New3"
|
226
|
+
@event.remove_comments "New2", "Comment"
|
227
|
+
@event.comment.should == ["New1", "New3"]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context ".dtstart=" do
|
233
|
+
before(:each) do
|
234
|
+
@event = RiCal.Event
|
235
|
+
end
|
236
|
+
|
237
|
+
context "with a datetime only string" do
|
238
|
+
before(:each) do
|
239
|
+
@event.dtstart = "20090514T202400"
|
240
|
+
@it = @event.dtstart
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should interpret it as the correct date-time" do
|
244
|
+
@it.should == DateTime.civil(2009, 5, 14, 20, 24, 00, Rational(0,24))
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should interpret it as a floating date" do
|
248
|
+
@it.tzid.should == :floating
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
context "with a TZID and datetime string" do
|
253
|
+
before(:each) do
|
254
|
+
@event.dtstart = "TZID=America/New_York:20090514T202400"
|
255
|
+
@it = @event.dtstart
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should interpret it as the correct date-time" do
|
259
|
+
@it.should == result_time_in_zone(2009, 5, 14, 20, 24, 00, "America/New_York")
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should set the tzid to America/New_York" do
|
263
|
+
@it.tzid.should == "America/New_York"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context "with a zulu datetime only string" do
|
268
|
+
before(:each) do
|
269
|
+
@event.dtstart = "20090514T202400Z"
|
270
|
+
@it = @event.dtstart
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should interpret it as the correct date-time" do
|
274
|
+
@it.should == DateTime.civil(2009, 5, 14, 20, 24, 00, Rational(0,24))
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should set the tzid to UTC" do
|
278
|
+
@it.tzid.should == "UTC"
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "with a date string" do
|
283
|
+
before(:each) do
|
284
|
+
@event.dtstart = "20090514"
|
285
|
+
@it = @event.dtstart
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should interpret it as the correct date-time" do
|
289
|
+
@it.should == Date.parse("14 May 2009")
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context ".entity_name" do
|
295
|
+
it "should be VEVENT" do
|
296
|
+
RiCal::Component::Event.entity_name.should == "VEVENT"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context "with an rrule" do
|
301
|
+
before(:each) do
|
302
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nRRULE:FREQ=DAILY\nEND:VEVENT").first
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should have an array of rrules" do
|
306
|
+
@it.rrule.should be_kind_of(Array)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
context ".start_time" do
|
311
|
+
|
312
|
+
it "should be nil if there is no dtstart property" do
|
313
|
+
RiCal.Event.start_time.should be_nil
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should be the same as dtstart for a date time" do
|
317
|
+
event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
|
318
|
+
event.start_time.should == DateTime.civil(2009,05,25,15,19,0,0)
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should be the start of the day of dtstart for a date" do
|
322
|
+
event = RiCal.Event {|e| e.dtstart = "20090525"}
|
323
|
+
event.start_time.should == DateTime.civil(2009,05,25,0,0,0,0)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
context ".finish_time" do
|
328
|
+
before(:each) do
|
329
|
+
@event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
|
330
|
+
end
|
331
|
+
|
332
|
+
context "with a given dtend" do
|
333
|
+
it "should be the same as dtend for a date time" do
|
334
|
+
@event.dtend = "20090525T161900"
|
335
|
+
@event.finish_time.should == DateTime.civil(2009,05,25,16,19,0,0)
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
end
|
340
|
+
|
341
|
+
context "with no dtend" do
|
342
|
+
context "and a duration" do
|
343
|
+
it "should be the dtstart plus the duration" do
|
344
|
+
@event.duration = "+PT1H"
|
345
|
+
@event.finish_time.should == DateTime.civil(2009,5,25,16,19,0,0)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context "and no duration" do
|
350
|
+
context "when the dtstart is not set" do
|
351
|
+
before(:each) do
|
352
|
+
@event.dtstart_property = nil
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should be nil" do
|
356
|
+
@event.finish_time.should be_nil
|
357
|
+
end
|
358
|
+
end
|
359
|
+
context "when the dstart is a datetime" do
|
360
|
+
# For cases where a "VEVENT" calendar component
|
361
|
+
# specifies a "DTSTART" property with a DATE-TIME data type but no
|
362
|
+
# "DTEND" property, the event ends on the same calendar date and time
|
363
|
+
# of day specified by the "DTSTART" property. RFC 2445 p 53
|
364
|
+
it "should be the same as start_time" do
|
365
|
+
@event.finish_time.should == @event.start_time
|
366
|
+
end
|
367
|
+
end
|
368
|
+
context "when the dtstart is a date" do
|
369
|
+
# For cases where a "VEVENT" calendar component specifies a "DTSTART" property with a DATE data type
|
370
|
+
# but no "DTEND" property, the events non-inclusive end is the end of the calendar date specified by
|
371
|
+
# the "DTSTART" property. RFC 2445 p 53
|
372
|
+
|
373
|
+
it "should be the end of the same day as start_time" do
|
374
|
+
@event.dtstart = "20090525"
|
375
|
+
@event.finish_time.should == DateTime.civil(2009,5,25,23,59,59,0)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
end
|
382
|
+
|
383
|
+
context ".zulu_occurrence_range_start_time" do
|
384
|
+
|
385
|
+
it "should be nil if there is no dtstart property" do
|
386
|
+
RiCal.Event.zulu_occurrence_range_start_time.should be_nil
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should be the utc equivalent of dtstart for a date time" do
|
390
|
+
event = RiCal.Event {|e| e.dtstart = "TZID=America/New_York:20090525T151900"}
|
391
|
+
event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,25,19,19,0,0)
|
392
|
+
end
|
393
|
+
|
394
|
+
it "should be the utc time of the start of the day of dtstart in the earliest timezone for a date" do
|
395
|
+
event = RiCal.Event {|e| e.dtstart = "20090525"}
|
396
|
+
result = event.zulu_occurrence_range_start_time
|
397
|
+
result.should == DateTime.civil(2009,05,24,12,0,0,0)
|
398
|
+
end
|
399
|
+
|
400
|
+
it "should be the utc time of the dtstart in the earliest timezone if dtstart is a floating datetime" do
|
401
|
+
event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
|
402
|
+
event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,25,3,19,0,0)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context ".zulu_occurrence_range_finish_time" do
|
407
|
+
before(:each) do
|
408
|
+
@event = RiCal.Event {|e| e.dtstart = "TZID=America/New_York:20090525T151900"}
|
409
|
+
end
|
410
|
+
|
411
|
+
context "with a given dtend" do
|
412
|
+
it "should be the utc equivalent of dtend if dtend is a date time" do
|
413
|
+
@event.dtend = "TZID=America/New_York:20090525T161900"
|
414
|
+
@event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,05,25, 20,19,0,0)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
context "with no dtend" do
|
419
|
+
context "and a duration" do
|
420
|
+
it "should be the dtstart plus the duration" do
|
421
|
+
@event.duration = "+PT1H"
|
422
|
+
@event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,5,25,20 ,19,0,0)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
context "and no duration" do
|
427
|
+
context "when the dtstart is not set" do
|
428
|
+
before(:each) do
|
429
|
+
@event.dtstart_property = nil
|
430
|
+
end
|
431
|
+
|
432
|
+
it "should be nil" do
|
433
|
+
@event.zulu_occurrence_range_finish_time.should be_nil
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
context "when the dstart is a datetime" do
|
438
|
+
|
439
|
+
it "should be the same as start_time" do
|
440
|
+
@event.zulu_occurrence_range_finish_time.should == @event.zulu_occurrence_range_start_time
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
context "when the dtstart is a date" do
|
445
|
+
it "should be the utc of end of the same day as start_time in the westermost time zone" do
|
446
|
+
@event.dtstart = "20090525"
|
447
|
+
@event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,5,26,11,59,59,0)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
context "description property" do
|
455
|
+
before(:each) do
|
456
|
+
@ical_desc = "posted by Joyce per Zan\\nASheville\\, Rayan's Restauratn\\, Biltm\n ore Square"
|
457
|
+
@ruby_desc = "posted by Joyce per Zan\nASheville, Rayan's Restauratn, Biltmore Square"
|
458
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDESCRIPTION:#{@ical_desc}\nEND:VEVENT").first
|
459
|
+
end
|
460
|
+
|
461
|
+
it "should product the converted ruby value" do
|
462
|
+
@it.description.should == @ruby_desc
|
463
|
+
end
|
464
|
+
|
465
|
+
it "should produce escaped text for ical" do
|
466
|
+
@it.description = "This is a\nnew description, yes; it is"
|
467
|
+
@it.description_property.value.should == 'This is a\nnew description\, yes\; it is'
|
468
|
+
end
|
469
|
+
|
470
|
+
end
|
471
|
+
|
472
|
+
context "with both dtend and duration specified" do
|
473
|
+
before(:each) do
|
474
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nDURATION:H1\nEND:VEVENT").first
|
475
|
+
end
|
476
|
+
|
477
|
+
it "should be invalid" do
|
478
|
+
@it.should_not be_valid
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
context "with a duration property" do
|
483
|
+
before(:each) do
|
484
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDURATION:H1\nEND:VEVENT").first
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should have a duration property" do
|
488
|
+
@it.duration_property.should be
|
489
|
+
end
|
490
|
+
|
491
|
+
it "should have a duration of 1 Hour" do
|
492
|
+
@it.duration_property.value.should == "H1"
|
493
|
+
end
|
494
|
+
|
495
|
+
it "should reset the duration property if the dtend property is set" do
|
496
|
+
@it.dtend_property = "19970101T123456".to_ri_cal_date_time_value
|
497
|
+
@it.duration_property.should be_nil
|
498
|
+
end
|
499
|
+
|
500
|
+
it "should reset the duration property if the dtend ruby value is set" do
|
501
|
+
@it.dtend = "19970101"
|
502
|
+
@it.duration_property.should == nil
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
context "with a dtend property" do
|
507
|
+
before(:each) do
|
508
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nEND:VEVENT").first
|
509
|
+
end
|
510
|
+
|
511
|
+
it "should have a duration property" do
|
512
|
+
@it.dtend_property.should be
|
513
|
+
end
|
514
|
+
|
515
|
+
it "should reset the dtend property if the duration property is set" do
|
516
|
+
@it.duration_property = "PT1H".to_ri_cal_duration_value
|
517
|
+
@it.dtend_property.should be_nil
|
518
|
+
end
|
519
|
+
|
520
|
+
it "should reset the dtend property if the duration ruby value is set" do
|
521
|
+
@it.duration = "PT1H".to_ri_cal_duration_value
|
522
|
+
@it.dtend_property.should be_nil
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
context "with a nested alarm component" do
|
527
|
+
before(:each) do
|
528
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\n\nBEGIN:VALARM\nEND:VALARM\nEND:VEVENT").first
|
529
|
+
end
|
530
|
+
|
531
|
+
it "should have one alarm" do
|
532
|
+
@it.alarms.length.should == 1
|
533
|
+
end
|
534
|
+
|
535
|
+
it "which should be an Alarm component" do
|
536
|
+
@it.alarms.first.should be_kind_of(RiCal::Component::Alarm)
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
context ".export" do
|
541
|
+
require 'rubygems'
|
542
|
+
require 'tzinfo'
|
543
|
+
|
544
|
+
def date_time_with_tzinfo_zone(date_time, timezone="America/New_York")
|
545
|
+
date_time.dup.set_tzid(timezone)
|
546
|
+
end
|
547
|
+
|
548
|
+
# Undo the effects of RFC2445 line folding
|
549
|
+
def unfold(string)
|
550
|
+
string.gsub("\n ", "")
|
551
|
+
end
|
552
|
+
|
553
|
+
before(:each) do
|
554
|
+
cal = RiCal.Calendar
|
555
|
+
@it = RiCal::Component::Event.new(cal)
|
556
|
+
end
|
557
|
+
|
558
|
+
it "should cause a VTIMEZONE to be included for a dtstart with a local timezone" do
|
559
|
+
@it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
|
560
|
+
unfold(@it.export).should match(/BEGIN:VTIMEZONE\nTZID;X-RICAL-TZSOURCE=TZINFO:America\/New_York\n/)
|
561
|
+
end
|
562
|
+
|
563
|
+
it "should properly format dtstart with a UTC date-time" do
|
564
|
+
@it.dtstart = DateTime.parse("April 22, 2009 1:23:45").set_tzid("UTC")
|
565
|
+
unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345Z$/)
|
566
|
+
end
|
567
|
+
|
568
|
+
it "should properly format dtstart with a floating date-time" do
|
569
|
+
@it.dtstart = DateTime.parse("April 22, 2009 1:23:45").with_floating_timezone
|
570
|
+
unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345$/)
|
571
|
+
end
|
572
|
+
|
573
|
+
it "should properly format dtstart with a local time zone" do
|
574
|
+
@it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
|
575
|
+
unfold(@it.export).should match(/^DTSTART;TZID=America\/New_York;VALUE=DATE-TIME:20090422T175500$/)
|
576
|
+
end
|
577
|
+
|
578
|
+
it "should properly format dtstart with a date" do
|
579
|
+
@it.dtstart = Date.parse("April 22, 2009")
|
580
|
+
unfold(@it.export).should match(/^DTSTART;VALUE=DATE:20090422$/)
|
581
|
+
end
|
582
|
+
|
583
|
+
it "should properly fold on export when the description contains a carriage return" do
|
584
|
+
@it.description = "Weather report looks nice, 80 degrees and partly cloudy, so following Michael's suggestion, let's meet at the food court at Crossroads:\n\rhttp://www.shopcrossroadsplaza.c...\n"
|
585
|
+
export_string = @it.export
|
586
|
+
export_string.should match(%r(^DESCRIPTION:Weather report looks nice\\, 80 degrees and partly cloudy\\, so$))
|
587
|
+
export_string.should match(%r(^ following Michael's suggestion\\, let's meet at the food court at Crossr$))
|
588
|
+
export_string.should match(%r(^ oads:\\nhttp://www\.shopcrossroadsplaza.c\.\.\.\\n$))
|
589
|
+
end
|
590
|
+
|
591
|
+
it "should properly fold on export when the description contains multi-byte UTF-8 Characters" do
|
592
|
+
@it.description = "Juin 2009 <<Alliance Francaise Reunion>> lieu Café périferôl"
|
593
|
+
export_string = @it.export
|
594
|
+
export_string.should match(%r(^DESCRIPTION:Juin 2009 <<Alliance Francaise Reunion>> lieu Café périfer$))
|
595
|
+
export_string.should match(%r(^ ôl$))
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
if RiCal::TimeWithZone
|
600
|
+
context "with ActiveSupport loaded" do
|
601
|
+
|
602
|
+
context "an event with an timezoned exdate" do
|
603
|
+
before(:each) do
|
604
|
+
@old_timezone = Time.zone
|
605
|
+
Time.zone = "America/New_York"
|
606
|
+
@exception_date_time = Time.zone.local(2009, 5, 19, 11, 13)
|
607
|
+
cal = RiCal.Calendar do |cal|
|
608
|
+
cal.event do |event|
|
609
|
+
event.add_exdate @exception_date_time
|
610
|
+
end
|
611
|
+
end
|
612
|
+
@event = cal.events.first
|
613
|
+
end
|
614
|
+
|
615
|
+
after(:each) do
|
616
|
+
Time.zone = @old_timezone
|
617
|
+
end
|
618
|
+
|
619
|
+
it "should pickup the timezone in the exdate property" do
|
620
|
+
@event.exdate.first.first.tzid.should == "America/New_York"
|
621
|
+
end
|
622
|
+
|
623
|
+
it "should have the timezone in the ical representation of the exdate property" do
|
624
|
+
@event.exdate_property.first.to_s.should match(%r{;TZID=America/New_York[:;]})
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
context "An event in a non-tzinfo source calendar" do
|
629
|
+
before(:each) do
|
630
|
+
cals = RiCal.parse_string <<ENDCAL
|
631
|
+
BEGIN:VCALENDAR
|
632
|
+
X-WR-TIMEZONE:America/New_York
|
633
|
+
PRODID:-//Apple Inc.//iCal 3.0//EN
|
634
|
+
CALSCALE:GREGORIAN
|
635
|
+
BEGIN:VTIMEZONE
|
636
|
+
TZID:US/Eastern
|
637
|
+
BEGIN:DAYLIGHT
|
638
|
+
TZOFFSETFROM:-0500
|
639
|
+
TZOFFSETTO:-0400
|
640
|
+
DTSTART:20070311T020000
|
641
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
642
|
+
TZNAME:EDT
|
643
|
+
END:DAYLIGHT
|
644
|
+
BEGIN:STANDARD
|
645
|
+
TZOFFSETFROM:-0400
|
646
|
+
TZOFFSETTO:-0500
|
647
|
+
DTSTART:20071104T020000
|
648
|
+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
649
|
+
TZNAME:EST
|
650
|
+
END:STANDARD
|
651
|
+
END:VTIMEZONE
|
652
|
+
BEGIN:VEVENT
|
653
|
+
SEQUENCE:5
|
654
|
+
TRANSP:OPAQUE
|
655
|
+
UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
|
656
|
+
DTSTART;TZID=US/Eastern:20090224T090000
|
657
|
+
DTSTAMP:20090225T000908Z
|
658
|
+
SUMMARY:Test Event
|
659
|
+
CREATED:20090225T000839Z
|
660
|
+
DTEND;TZID=US/Eastern:20090224T100000
|
661
|
+
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
|
662
|
+
END:VEVENT
|
663
|
+
END:VCALENDAR
|
664
|
+
ENDCAL
|
665
|
+
@event = cals.first.events.first
|
666
|
+
end
|
667
|
+
|
668
|
+
it "should produce a DateTime for dtstart" do
|
669
|
+
@event.dtstart.should be_instance_of(DateTime)
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
context "An event starting in Paris and ending in New York" do
|
674
|
+
|
675
|
+
before(:each) do
|
676
|
+
@start = Time.now.utc.in_time_zone("Europe/Paris")
|
677
|
+
@finish = Time.now.utc.in_time_zone("America/New_York")
|
678
|
+
cal = RiCal.Calendar do |ical|
|
679
|
+
ical.event do |ievent|
|
680
|
+
ievent.dtstart @start
|
681
|
+
ievent.dtend @finish
|
682
|
+
end
|
683
|
+
end
|
684
|
+
@event = cal.events.first
|
685
|
+
end
|
686
|
+
|
687
|
+
it "should have the right time zone for dtstart" do
|
688
|
+
@event.dtstart.tzid.should == "Europe/Paris"
|
689
|
+
end
|
690
|
+
|
691
|
+
it "should produce a TimeWithZone for dtstart" do
|
692
|
+
@event.dtstart.should be_instance_of(RiCal::TimeWithZone)
|
693
|
+
end
|
694
|
+
|
695
|
+
# ActiveRecord::TimeWithZone doesn't implement == as expected
|
696
|
+
it "should produce a dtstart which looks like the provided value" do
|
697
|
+
@event.dtstart.to_s.should == @start.to_s
|
698
|
+
end
|
699
|
+
|
700
|
+
it "should have the right time zone for dtend" do
|
701
|
+
@event.dtend.tzid.should == "America/New_York"
|
702
|
+
end
|
703
|
+
|
704
|
+
it "should produce a TimeWithZone for dtend" do
|
705
|
+
@event.dtend.should be_instance_of(RiCal::TimeWithZone)
|
706
|
+
end
|
707
|
+
|
708
|
+
# ActiveRecord::TimeWithZone doesn't implement == as expected
|
709
|
+
it "should produce a dtend which looks like the provided value" do
|
710
|
+
@event.dtend.to_s.should == @finish.to_s
|
711
|
+
end
|
712
|
+
end
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
context "An event with a floating start" do
|
717
|
+
|
718
|
+
before(:each) do
|
719
|
+
cal = RiCal.Calendar do |ical|
|
720
|
+
ical.event do |ievent|
|
721
|
+
ievent.dtstart "20090530T120000"
|
722
|
+
end
|
723
|
+
end
|
724
|
+
@event = cal.events.first
|
725
|
+
end
|
726
|
+
|
727
|
+
it "should produce a DateTime for dtstart" do
|
728
|
+
@event.dtstart.should be_instance_of(DateTime)
|
729
|
+
end
|
730
|
+
|
731
|
+
it "should have a floating dtstart" do
|
732
|
+
@event.dtstart.should have_floating_timezone
|
733
|
+
end
|
734
|
+
end
|
735
|
+
end
|