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,12 @@
|
|
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::Component::Freebusy do
|
6
|
+
|
7
|
+
describe ".entity_name" do
|
8
|
+
it "should be VFREEBUSY" do
|
9
|
+
RiCal::Component::Freebusy.entity_name.should == "VFREEBUSY"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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::Component::Journal do
|
6
|
+
|
7
|
+
describe ".entity_name" do
|
8
|
+
it "should be VJOURNAL" do
|
9
|
+
RiCal::Component::Journal.entity_name.should == "VJOURNAL"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context ".start_time" do
|
14
|
+
it "should be the same as dtstart for a date time" do
|
15
|
+
event = RiCal.Journal {|e| e.dtstart = "20090525T151900"}
|
16
|
+
event.start_time.should == DateTime.civil(2009,05,25,15,19,0,0)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be the start of the day of dtstart for a date" do
|
20
|
+
event = RiCal.Journal {|e| e.dtstart = "20090525"}
|
21
|
+
event.start_time.should == DateTime.civil(2009,05,25,0,0,0,0)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context ".finish_time" do
|
26
|
+
it "should be the same as dtstart for a date time" do
|
27
|
+
event = RiCal.Journal {|e| e.dtstart = "20090525T151900"}
|
28
|
+
event.finish_time.should == DateTime.civil(2009,05,25,15,19,0,0)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be the start of the day of dtstart for a date" do
|
32
|
+
event = RiCal.Journal {|e| e.dtstart = "20090525"}
|
33
|
+
event.finish_time.should == DateTime.civil(2009,05,25,0,0,0,0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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
|
+
# Uncomment the next two lines to run this spec in textmate
|
5
|
+
# require 'rubygems'
|
6
|
+
# require 'tzinfo'
|
7
|
+
|
8
|
+
describe RiCal::Component::TZInfoTimezone do
|
9
|
+
|
10
|
+
it "should produce an rfc representation" do
|
11
|
+
tz = RiCal::Component::TZInfoTimezone.new(TZInfo::Timezone.get("America/New_York"))
|
12
|
+
local_first = DateTime.parse("Apr 10, 2007")
|
13
|
+
local_last = DateTime.parse("Apr 6, 2008")
|
14
|
+
utc_first = tz.local_to_utc(local_first)
|
15
|
+
utc_last = tz.local_to_utc(local_last)
|
16
|
+
rez = tz.to_rfc2445_string(utc_first, utc_last)
|
17
|
+
rez.should == <<-ENDDATA
|
18
|
+
BEGIN:VTIMEZONE
|
19
|
+
TZID;X-RICAL-TZSOURCE=TZINFO:America/New_York
|
20
|
+
BEGIN:DAYLIGHT
|
21
|
+
DTSTART:20070311T020000
|
22
|
+
RDATE:20070311T020000
|
23
|
+
RDATE:20080309T020000
|
24
|
+
TZOFFSETFROM:-0500
|
25
|
+
TZOFFSETTO:-0400
|
26
|
+
TZNAME:EDT
|
27
|
+
END:DAYLIGHT
|
28
|
+
BEGIN:STANDARD
|
29
|
+
DTSTART:20071104T020000
|
30
|
+
RDATE:20071104T020000
|
31
|
+
TZOFFSETFROM:-0400
|
32
|
+
TZOFFSETTO:-0500
|
33
|
+
TZNAME:EST
|
34
|
+
END:STANDARD
|
35
|
+
END:VTIMEZONE
|
36
|
+
ENDDATA
|
37
|
+
end
|
38
|
+
|
39
|
+
TZInfo::Timezone.all_identifiers.each do |tz|
|
40
|
+
context "TZInfo timezone #{tz}" do
|
41
|
+
before(:each) do
|
42
|
+
@calendar = RiCal.Calendar do |cal|
|
43
|
+
cal.event do |event|
|
44
|
+
event.description = "test"
|
45
|
+
event.dtstart = "TZID=#{tz}:20090530T123000"
|
46
|
+
event.dtend = "TZID=#{tz}:20090530T123001"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
it "should be allowed as a tzid" do
|
51
|
+
lambda {@calendar.export}.should_not raise_error
|
52
|
+
end
|
53
|
+
unless tz == "UTC"
|
54
|
+
it "should produce at least one period in the VTIMEZONE" do
|
55
|
+
@calendar.export.should match(/BEGIN:(STANDARD|DAYLIGHT)/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,236 @@
|
|
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 'tzinfo'
|
5
|
+
|
6
|
+
describe RiCal::Component::Timezone do
|
7
|
+
|
8
|
+
context ".entity_name" do
|
9
|
+
it "should be VTIMEZONE" do
|
10
|
+
RiCal::Component::Timezone.entity_name.should == "VTIMEZONE"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "for a Timezone with no DST periods" do
|
15
|
+
before(:each) do
|
16
|
+
@it = RiCal.parse_string rectify_ical(<<-'ENDCAL')
|
17
|
+
BEGIN:VTIMEZONE
|
18
|
+
TZID:Australia/Brisbane
|
19
|
+
X-LIC-LOCATION:Australia/Brisbane
|
20
|
+
BEGIN:STANDARD
|
21
|
+
TZOFFSETFROM:+1000
|
22
|
+
TZOFFSETTO:+1000
|
23
|
+
TZNAME:EST
|
24
|
+
DTSTART:19700101T000000
|
25
|
+
END:STANDARD
|
26
|
+
END:VTIMEZONE
|
27
|
+
ENDCAL
|
28
|
+
@it = @it.first
|
29
|
+
end
|
30
|
+
|
31
|
+
context ".periods_for_local" do
|
32
|
+
it "should return a single period" do
|
33
|
+
@it.periods_for_local(DateTime.parse("20090530T100000")).length.should == 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "from an iCal.app calendar for America/New_York starting March 11 2007" do
|
39
|
+
before(:each) do
|
40
|
+
@it = RiCal.parse_string rectify_ical(<<-'ENDCAL')
|
41
|
+
BEGIN:VTIMEZONE
|
42
|
+
TZID:US/Eastern
|
43
|
+
BEGIN:DAYLIGHT
|
44
|
+
TZOFFSETFROM:-0500
|
45
|
+
TZOFFSETTO:-0400
|
46
|
+
DTSTART:20070311T020000
|
47
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
48
|
+
TZNAME:EDT
|
49
|
+
END:DAYLIGHT
|
50
|
+
BEGIN:STANDARD
|
51
|
+
TZOFFSETFROM:-0400
|
52
|
+
TZOFFSETTO:-0500
|
53
|
+
DTSTART:20071104T020000
|
54
|
+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
55
|
+
TZNAME:EST
|
56
|
+
END:STANDARD
|
57
|
+
END:VTIMEZONE
|
58
|
+
ENDCAL
|
59
|
+
@it = @it.first
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be a Timezone" do
|
63
|
+
@it.should be_kind_of(RiCal::Component::Timezone)
|
64
|
+
end
|
65
|
+
|
66
|
+
context ".local_to_utc" do
|
67
|
+
it "should produce 2/27/2009 18:00 UTC for 2/27/2009 13:00" do
|
68
|
+
expected = RiCal::PropertyValue::DateTime.new(nil, :value => "20090227T1800Z" )
|
69
|
+
@it.local_to_utc(DateTime.parse("Feb 27, 2009 13:00")).should == expected
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context ".utc_to_local" do
|
74
|
+
it "should produce 2/27/2009 13:00 EST for 2/27/2009 18:00 UTC" do
|
75
|
+
expected = RiCal::PropertyValue::DateTime.new(nil, :params => {'TZID' => 'US/Eastern'}, :value => "20090227T1300" )
|
76
|
+
@it.utc_to_local(DateTime.parse("Feb 27, 2009 18:00")).should == expected
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context ".period_for_local" do
|
81
|
+
it "should raise TZInfo::PeriodNotFound for an invalid local time, e.g. Mar 8, 2009 2:30" do
|
82
|
+
lambda {@it.period_for_local(DateTime.parse("Mar 8, 2009 2:30"))}.should raise_error(TZInfo::PeriodNotFound)
|
83
|
+
end
|
84
|
+
|
85
|
+
context "for an ambiguous local time , e.g. Nov 1, 2009 2:00" do
|
86
|
+
context "lacking a dst parameter or block" do
|
87
|
+
it "should raise TZInfo::AmbiguousTime" do
|
88
|
+
lambda {@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"))}.should raise_error(TZInfo::AmbiguousTime)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with a dst parameter" do
|
93
|
+
it "should return a dst period if the dst parameter is true" do
|
94
|
+
@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"), true).should be_dst
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should return a std period if the dst parameter is false" do
|
98
|
+
@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"), false).should_not be_dst
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "with a block" do
|
103
|
+
it "should return a period if the block returns a TimezonePeriod" do
|
104
|
+
mock_period = ::RiCal::Component::Timezone::TimezonePeriod.new(nil)
|
105
|
+
@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results| mock_period}.should == mock_period
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should return a period if the block returns a single element array" do
|
109
|
+
mock_period = :foo
|
110
|
+
@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results| [ mock_period]}.should == mock_period
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should raise TZInfo::PeriodNotFound if the block returns a multi-element array" do
|
114
|
+
lambda {
|
115
|
+
@it.period_for_local(DateTime.parse("Mar 8, 2009 2:30")) {|results| [1,2]}}.should raise_error(TZInfo::PeriodNotFound)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context ".periods_for_local" do
|
122
|
+
context "for the date on which DST begins springing ahead e.g. Mar 8, 2009" do
|
123
|
+
it "should return a 1 element array for 1 second before the transition time" do
|
124
|
+
@it.periods_for_local(DateTime.parse("Mar 8, 2009 1:59:59")).length.should == 1
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should return an empty array for the transition time" do
|
128
|
+
@it.periods_for_local(DateTime.parse("Mar 8, 2009 2:00:00")).should == []
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should return an empty array for 1 second after the transition time" do
|
132
|
+
@it.periods_for_local(DateTime.parse("Mar 8, 2009 2:00:01")).should == []
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should return an empty array for 1 second before the spring ahead time" do
|
136
|
+
@it.periods_for_local(DateTime.parse("Mar 8, 2009 2:59:59")).should == []
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should return a 1 element array for the spring ahead time" do
|
140
|
+
@it.periods_for_local(DateTime.parse("Mar 8, 2009 3:00:00")).length.should == 1
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "for the date on which DST ends falling back e.g. Nov 11, 2009" do
|
145
|
+
it "should return a 1 element array for 1 second before the transition time" do
|
146
|
+
@it.periods_for_local(DateTime.parse("Nov 1, 2009 1:59:59")).length.should == 1
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should return a 2 element array for the transition time" do
|
150
|
+
@it.periods_for_local(DateTime.parse("Nov 1, 2009 2:00:00")).length.should == 2
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should return a 2 element array for 1 second after the transition time" do
|
154
|
+
@it.periods_for_local(DateTime.parse("Nov 1, 2009 2:00:01")).length.should == 2
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should return a 2 element array for 59 minutes and 59 seconds after the transition time" do
|
158
|
+
@it.periods_for_local(DateTime.parse("Nov 1, 2009 2:59:59")).length.should == 2
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should return a 2 element array for 1 hour after the transition time" do
|
162
|
+
@it.periods_for_local(DateTime.parse("Nov 1, 2009 3:00:00")).length.should == 2
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should return a 2 element array for 1 hour and 1 second after the transition time" do
|
166
|
+
@it.periods_for_local(DateTime.parse("Nov 1, 2009 3:00:01")).length.should == 2
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "Bug report from paulsm" do
|
173
|
+
before(:each) do
|
174
|
+
cals = RiCal.parse_string rectify_ical(<<-'ENDCAL')
|
175
|
+
BEGIN:VCALENDAR
|
176
|
+
X-WR-TIMEZONE:America/New_York
|
177
|
+
PRODID:-//Apple Inc.//iCal 3.0//EN
|
178
|
+
CALSCALE:GREGORIAN
|
179
|
+
X-WR-CALNAME:test
|
180
|
+
VERSION:2.0
|
181
|
+
X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
|
182
|
+
X-APPLE-CALENDAR-COLOR:#2CA10B
|
183
|
+
BEGIN:VTIMEZONE
|
184
|
+
TZID:US/Eastern
|
185
|
+
BEGIN:DAYLIGHT
|
186
|
+
TZOFFSETFROM:-0500
|
187
|
+
TZOFFSETTO:-0400
|
188
|
+
DTSTART:20070311T020000
|
189
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
190
|
+
TZNAME:EDT
|
191
|
+
END:DAYLIGHT
|
192
|
+
BEGIN:STANDARD
|
193
|
+
TZOFFSETFROM:-0400
|
194
|
+
TZOFFSETTO:-0500
|
195
|
+
DTSTART:20071104T020000
|
196
|
+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
197
|
+
TZNAME:EST
|
198
|
+
END:STANDARD
|
199
|
+
END:VTIMEZONE
|
200
|
+
BEGIN:VEVENT
|
201
|
+
SEQUENCE:5
|
202
|
+
TRANSP:OPAQUE
|
203
|
+
UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
|
204
|
+
DTSTART;TZID=US/Eastern:20090224T090000
|
205
|
+
DTSTAMP:20090225T000908Z
|
206
|
+
SUMMARY:Test Event
|
207
|
+
CREATED:20090225T000839Z
|
208
|
+
DTEND;TZID=US/Eastern:20090224T100000
|
209
|
+
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
|
210
|
+
END:VEVENT
|
211
|
+
END:VCALENDAR
|
212
|
+
ENDCAL
|
213
|
+
@event = cals.first.events.first
|
214
|
+
end
|
215
|
+
|
216
|
+
context "the events dtstart" do
|
217
|
+
it "should be the right DateTime" do
|
218
|
+
@event.dtstart.should == DateTime.civil(2009, 2, 24, 9, 0, 0, Rational(-5, 24))
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should have the right tzid" do
|
222
|
+
@event.dtstart.tzid.should == "US/Eastern"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context "the events dtend" do
|
227
|
+
it "should be the right DateTime" do
|
228
|
+
@event.dtend.should == DateTime.civil(2009, 2, 24, 10, 0, 0, Rational(-5, 24))
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should have the right tzid" do
|
232
|
+
@event.dtend.tzid.should == "US/Eastern"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,112 @@
|
|
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::Component::Todo do
|
6
|
+
|
7
|
+
context ".start_time" do
|
8
|
+
it "should be the same as dtstart for a date time" do
|
9
|
+
todo = RiCal.Todo {|e| e.dtstart = "20090525T151900"}
|
10
|
+
todo.start_time.should == DateTime.civil(2009,05,25,15,19,0,0)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be the start of the day of dtstart for a date" do
|
14
|
+
todo = RiCal.Todo {|e| e.dtstart = "20090525"}
|
15
|
+
todo.start_time.should == DateTime.civil(2009,05,25,0,0,0,0)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be nil if the dtstart property is not set" do
|
19
|
+
RiCal.Todo.start_time.should be_nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context ".finish_time" do
|
24
|
+
before(:each) do
|
25
|
+
@todo = RiCal.Todo {|t| t.dtstart = "20090525T151900"}
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with a given due" do
|
29
|
+
it "should be the same as due for a date time" do
|
30
|
+
@todo.due = "20090525T161900"
|
31
|
+
@todo.finish_time.should == DateTime.civil(2009,05,25,16,19,0,0)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with no due" do
|
36
|
+
context "and a duration" do
|
37
|
+
before(:each) do
|
38
|
+
@todo.duration = "+PT1H"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be the dtstart plus the duration" do
|
42
|
+
@todo.finish_time.should == DateTime.civil(2009,5,25,16,19,0,0)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be nil if the dtstart property is not set" do
|
46
|
+
@todo.dtstart_property = nil
|
47
|
+
@todo.finish_time.should be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "and no duration" do
|
52
|
+
it "should be nil" do
|
53
|
+
@todo.finish_time.should be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "with both due and duration specified" do
|
60
|
+
before(:each) do
|
61
|
+
@it = RiCal::Component::Todo.parse_string("BEGIN:VTODO\nDUE:19970903T190000Z\nDURATION:H1\nEND:VTODO").first
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be invalid" do
|
65
|
+
@it.should_not be_valid
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "with a duration property" do
|
70
|
+
before(:each) do
|
71
|
+
@it = RiCal::Component::Todo.parse_string("BEGIN:VTODO\nDURATION:H1\nEND:VTODO").first
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should have a duration property" do
|
75
|
+
@it.duration_property.should be
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should have a duration of 1 Hour" do
|
79
|
+
@it.duration_property.value.should == "H1"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should reset the duration property if the due property is set" do
|
83
|
+
@it.due_property = "19970101T012345".to_ri_cal_date_time_value
|
84
|
+
@it.duration_property.should be_nil
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should reset the duration property if the dtend ruby value is set" do
|
88
|
+
@it.due = "19970101"
|
89
|
+
@it.duration_property.should == nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "with a due property" do
|
94
|
+
before(:each) do
|
95
|
+
@it = RiCal::Component::Todo.parse_string("BEGIN:VTODO\nDUE:19970903T190000Z\nEND:VTODO").first
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should have a due property" do
|
99
|
+
@it.due_property.should be
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should reset the due property if the duration property is set" do
|
103
|
+
@it.duration_property = "PT1H".to_ri_cal_duration_value
|
104
|
+
@it.due_property.should be_nil
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should reset the duration property if the dtend ruby value is set" do
|
108
|
+
@it.duration = "PT1H"
|
109
|
+
@it.due_property.should == nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,224 @@
|
|
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 'tzinfo'
|
5
|
+
|
6
|
+
describe RiCal::Component do
|
7
|
+
|
8
|
+
context "building blocks" do
|
9
|
+
|
10
|
+
context "building an empty calendar" do
|
11
|
+
before(:each) do
|
12
|
+
@it = RiCal.Calendar.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have the default prodid" do
|
16
|
+
@it.should match(%r{^PRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN$})
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have the default calscale" do
|
20
|
+
@it.should match(%r{^CALSCALE:GREGORIAN$})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have the default icalendar version" do
|
24
|
+
@it.should match(%r{^VERSION:2\.0$})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "building a calendar with time zones" do
|
29
|
+
it 'should allow specifying the time zone identifier' do
|
30
|
+
event = RiCal.Event do
|
31
|
+
dtstart DateTime.parse("Feb 20, 1962 14:47:39").set_tzid('US/Pacific')
|
32
|
+
end
|
33
|
+
event.dtstart_property.should == dt_prop(DateTime.parse("Feb 20, 1962 14:47:39"), tzid = 'US/Pacific')
|
34
|
+
end
|
35
|
+
|
36
|
+
context "adding an exception date" do
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
@cal = RiCal.Calendar do
|
40
|
+
event do
|
41
|
+
add_exdate 'US/Eastern', "19620220T144739"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
@event = @cal.events.first
|
45
|
+
@prop = @event.exdate_property.first
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should produce an OccurrenceList for the property" do
|
49
|
+
@prop.should be_instance_of(RiCal::PropertyValue::OccurrenceList)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have a property with the right ical representation" do
|
53
|
+
@prop.to_s.should == ";TZID=US/Eastern:19620220T144739"
|
54
|
+
end
|
55
|
+
|
56
|
+
context "its ruby_value" do
|
57
|
+
it "should have the right value" do
|
58
|
+
@prop.ruby_value.should == [DateTime.civil(1962, 2, 20, 14, 47, 39, Rational(-5, 24))]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should have the right tzid" do
|
62
|
+
@prop.ruby_value.first.tzid.should == "US/Eastern"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "with a block with 1 parameter" do
|
69
|
+
before(:each) do
|
70
|
+
@it = RiCal.Event do |event|
|
71
|
+
event.description = "MA-6 First US Manned Spaceflight"
|
72
|
+
event.dtstart = DateTime.parse("Feb 20, 1962 14:47:39")
|
73
|
+
event.dtend = DateTime.parse("Feb 20, 1962 19:43:02")
|
74
|
+
event.location = "Cape Canaveral"
|
75
|
+
event.add_attendee "john.glenn@nasa.gov"
|
76
|
+
event.alarm do
|
77
|
+
description "Segment 51"
|
78
|
+
end
|
79
|
+
event.alarm do |alarm|
|
80
|
+
alarm.description = "Second alarm"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should have the right description" do
|
86
|
+
@it.description.should == "MA-6 First US Manned Spaceflight"
|
87
|
+
end
|
88
|
+
it "should have the right dtstart" do
|
89
|
+
@it.dtstart.should == DateTime.parse("Feb 20, 1962 14:47:39")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should have a zulu time dtstart property" do
|
93
|
+
@it.dtstart_property.tzid.should == "UTC"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should have the right dtend" do
|
97
|
+
@it.dtend.should == DateTime.parse("Feb 20, 1962 19:43:02")
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should have a zulu time dtend property" do
|
101
|
+
@it.dtend_property.tzid.should == "UTC"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should have the right location" do
|
105
|
+
@it.location.should == "Cape Canaveral"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should have the right attendee" do
|
109
|
+
@it.attendee.should include("john.glenn@nasa.gov")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should have 2 alarms" do
|
113
|
+
@it.alarms.length.should == 2
|
114
|
+
end
|
115
|
+
|
116
|
+
it ".the alarms should have the right description" do
|
117
|
+
@it.alarms.first.description.should == "Segment 51"
|
118
|
+
@it.alarms.last.description.should == "Second alarm"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "building an event for MA-6" do
|
123
|
+
before(:each) do
|
124
|
+
@it = RiCal.Event do
|
125
|
+
description "MA-6 First US Manned Spaceflight"
|
126
|
+
dtstart DateTime.parse("Feb 20, 1962 14:47:39")
|
127
|
+
dtend DateTime.parse("Feb 20, 1962 19:43:02")
|
128
|
+
location "Cape Canaveral"
|
129
|
+
add_attendee "john.glenn@nasa.gov"
|
130
|
+
alarm do
|
131
|
+
description "Segment 51"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should have the right description" do
|
137
|
+
@it.description.should == "MA-6 First US Manned Spaceflight"
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should have the right dtstart" do
|
141
|
+
@it.dtstart.should == DateTime.parse("Feb 20, 1962 14:47:39")
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should have a zulu time dtstart property" do
|
145
|
+
@it.dtstart_property.tzid.should == "UTC"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should have the right dtend" do
|
149
|
+
@it.dtend.should == DateTime.parse("Feb 20, 1962 19:43:02")
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should have a zulu time dtend property" do
|
153
|
+
@it.dtend_property.tzid.should == "UTC"
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should have the right location" do
|
157
|
+
@it.location.should == "Cape Canaveral"
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should have the right attendee" do
|
161
|
+
@it.attendee.should include("john.glenn@nasa.gov")
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should have 1 alarm" do
|
165
|
+
@it.alarms.length.should == 1
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should have an alarm with the right description" do
|
169
|
+
@it.alarms.first.description.should == "Segment 51"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context "building a complex calendar" do
|
174
|
+
|
175
|
+
before(:each) do
|
176
|
+
@it = RiCal.Calendar do
|
177
|
+
add_x_property 'x_wr_calname', 'My Personal Calendar', true
|
178
|
+
event do
|
179
|
+
summary 'A Recurring Event'
|
180
|
+
description "This is some really long note content. It should be appropriately folded in the generated file.\nCarriage returns should work, too."
|
181
|
+
dtstart DateTime.parse('Feb 20, 2009 20:30:00')
|
182
|
+
dtend DateTime.parse('Feb 20, 2009 21:30:00')
|
183
|
+
location 'North Carolina'
|
184
|
+
dtstamp Time.now
|
185
|
+
rrule :freq => 'daily', :interval => 1
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should have an x_wr_calname property with the value "My Personal Calendar"' do
|
191
|
+
@it.x_wr_calname.first.should == "My Personal Calendar"
|
192
|
+
end
|
193
|
+
|
194
|
+
context "event with a long description and a dsl built recurence rule" do
|
195
|
+
before(:each) do
|
196
|
+
@cal = @it
|
197
|
+
@it = @cal.events.first
|
198
|
+
end
|
199
|
+
|
200
|
+
context "its description" do
|
201
|
+
it "should pass through correctly" do
|
202
|
+
@it.description.should == "This is some really long note content. It should be appropriately folded in the generated file.\nCarriage returns should work, too."
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
context "its rrule" do
|
207
|
+
|
208
|
+
it "should have a 1 rrule" do
|
209
|
+
@it.rrule.length.should == 1
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should have the right rrule" do
|
213
|
+
@it.rrule.first.should == "FREQ=DAILY"
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should have the right rrule hash" do
|
217
|
+
@it.rrule_property.first.to_options_hash.should == {:freq => 'DAILY', :interval => 1}
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|