ri_cal 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/History.txt +45 -0
  2. data/Manifest.txt +129 -0
  3. data/README.txt +394 -0
  4. data/Rakefile +31 -0
  5. data/bin/ri_cal +8 -0
  6. data/component_attributes/alarm.yml +10 -0
  7. data/component_attributes/calendar.yml +4 -0
  8. data/component_attributes/component_property_defs.yml +180 -0
  9. data/component_attributes/event.yml +45 -0
  10. data/component_attributes/freebusy.yml +16 -0
  11. data/component_attributes/journal.yml +35 -0
  12. data/component_attributes/timezone.yml +3 -0
  13. data/component_attributes/timezone_period.yml +11 -0
  14. data/component_attributes/todo.yml +46 -0
  15. data/copyrights.txt +1 -0
  16. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  17. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  18. data/docs/incrementers.txt +7 -0
  19. data/docs/rfc2445.pdf +0 -0
  20. data/lib/ri_cal.rb +144 -0
  21. data/lib/ri_cal/component.rb +247 -0
  22. data/lib/ri_cal/component/alarm.rb +21 -0
  23. data/lib/ri_cal/component/calendar.rb +219 -0
  24. data/lib/ri_cal/component/event.rb +60 -0
  25. data/lib/ri_cal/component/freebusy.rb +18 -0
  26. data/lib/ri_cal/component/journal.rb +30 -0
  27. data/lib/ri_cal/component/t_z_info_timezone.rb +123 -0
  28. data/lib/ri_cal/component/timezone.rb +196 -0
  29. data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
  30. data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
  31. data/lib/ri_cal/component/timezone/timezone_period.rb +53 -0
  32. data/lib/ri_cal/component/todo.rb +43 -0
  33. data/lib/ri_cal/core_extensions.rb +6 -0
  34. data/lib/ri_cal/core_extensions/array.rb +7 -0
  35. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  36. data/lib/ri_cal/core_extensions/date.rb +13 -0
  37. data/lib/ri_cal/core_extensions/date/conversions.rb +61 -0
  38. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  39. data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
  40. data/lib/ri_cal/core_extensions/object.rb +8 -0
  41. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  42. data/lib/ri_cal/core_extensions/string.rb +8 -0
  43. data/lib/ri_cal/core_extensions/string/conversions.rb +63 -0
  44. data/lib/ri_cal/core_extensions/time.rb +13 -0
  45. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  46. data/lib/ri_cal/core_extensions/time/conversions.rb +61 -0
  47. data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
  48. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
  49. data/lib/ri_cal/floating_timezone.rb +32 -0
  50. data/lib/ri_cal/invalid_property_value.rb +8 -0
  51. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  52. data/lib/ri_cal/occurrence_enumerator.rb +206 -0
  53. data/lib/ri_cal/occurrence_period.rb +17 -0
  54. data/lib/ri_cal/parser.rb +138 -0
  55. data/lib/ri_cal/properties/alarm.rb +390 -0
  56. data/lib/ri_cal/properties/calendar.rb +164 -0
  57. data/lib/ri_cal/properties/event.rb +1526 -0
  58. data/lib/ri_cal/properties/freebusy.rb +594 -0
  59. data/lib/ri_cal/properties/journal.rb +1240 -0
  60. data/lib/ri_cal/properties/timezone.rb +151 -0
  61. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  62. data/lib/ri_cal/properties/todo.rb +1562 -0
  63. data/lib/ri_cal/property_value.rb +149 -0
  64. data/lib/ri_cal/property_value/array.rb +27 -0
  65. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  66. data/lib/ri_cal/property_value/date.rb +175 -0
  67. data/lib/ri_cal/property_value/date_time.rb +335 -0
  68. data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
  69. data/lib/ri_cal/property_value/date_time/time_machine.rb +181 -0
  70. data/lib/ri_cal/property_value/date_time/timezone_support.rb +96 -0
  71. data/lib/ri_cal/property_value/duration.rb +110 -0
  72. data/lib/ri_cal/property_value/geo.rb +11 -0
  73. data/lib/ri_cal/property_value/integer.rb +12 -0
  74. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  75. data/lib/ri_cal/property_value/period.rb +82 -0
  76. data/lib/ri_cal/property_value/recurrence_rule.rb +145 -0
  77. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +97 -0
  78. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
  81. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
  82. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +793 -0
  83. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  84. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +60 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +49 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  88. data/lib/ri_cal/property_value/text.rb +40 -0
  89. data/lib/ri_cal/property_value/uri.rb +11 -0
  90. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  91. data/lib/ri_cal/required_timezones.rb +55 -0
  92. data/ri_cal.gemspec +49 -0
  93. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  94. data/script/console +10 -0
  95. data/script/destroy +14 -0
  96. data/script/generate +14 -0
  97. data/script/txt2html +71 -0
  98. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  99. data/spec/ri_cal/component/calendar_spec.rb +54 -0
  100. data/spec/ri_cal/component/event_spec.rb +601 -0
  101. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  102. data/spec/ri_cal/component/journal_spec.rb +37 -0
  103. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +36 -0
  104. data/spec/ri_cal/component/timezone_spec.rb +218 -0
  105. data/spec/ri_cal/component/todo_spec.rb +112 -0
  106. data/spec/ri_cal/component_spec.rb +224 -0
  107. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  108. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  109. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  110. data/spec/ri_cal/occurrence_enumerator_spec.rb +573 -0
  111. data/spec/ri_cal/parser_spec.rb +303 -0
  112. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  113. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  114. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  115. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  116. data/spec/ri_cal/property_value/period_spec.rb +49 -0
  117. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  118. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  119. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  120. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  121. data/spec/ri_cal/property_value_spec.rb +125 -0
  122. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  123. data/spec/ri_cal_spec.rb +53 -0
  124. data/spec/spec.opts +4 -0
  125. data/spec/spec_helper.rb +46 -0
  126. data/tasks/gem_loader/load_active_support.rb +3 -0
  127. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  128. data/tasks/ri_cal.rake +410 -0
  129. data/tasks/spec.rake +50 -0
  130. metadata +221 -0
@@ -0,0 +1,33 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ class UtcOffset < PropertyValue # :nodoc:
6
+ attr_accessor :sign, :hours, :minutes, :seconds
7
+
8
+ def value=(string)
9
+ @value = string
10
+ parse_match = /([+-])(\d\d)(\d\d)(\d\d)?/.match(string)
11
+ if parse_match
12
+ @sign = parse_match[1] == "+" ? 1 : -1
13
+ @hours = parse_match[2].to_i
14
+ @minutes = parse_match[3].to_i
15
+ @seconds = parse_match[4].to_i || 0
16
+ end
17
+ end
18
+
19
+ def to_seconds
20
+ @sign * ((((hours*60) + minutes) * 60) + seconds)
21
+ end
22
+
23
+ def add_to_date_time_value(date_time_value)
24
+ date_time_value.advance(:hours => sign * hours, :minutes => sign * minutes, :seconds => sign * minutes)
25
+ end
26
+
27
+ def subtract_from_date_time_value(date_time_value)
28
+ signum = -1 * sign
29
+ date_time_value.advance(:hours => signum * hours, :minutes => signum * minutes, :seconds => signum * minutes)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ module RiCal
2
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
3
+ #
4
+ # RequireTimezones collects the timezones used by a given calendar component or set of calendar components
5
+ # For each timezone we collect it's id, and the earliest and latest times which reference the zone
6
+ class RequiredTimezones #:nodoc:
7
+
8
+
9
+ # A required timezone represents a single timezone and the earliest and latest times which reference it.
10
+ class RequiredTimezone #:nodoc:
11
+
12
+ attr_reader :first_time, :last_time, :timezone
13
+
14
+ def initialize(tzid)
15
+ @timezone = RiCal::Component::TZInfoTimezone.new(TZInfo::Timezone.get(tzid))
16
+ end
17
+
18
+ def tzid
19
+ @timezone.identifier
20
+ end
21
+
22
+ def add_datetime(date_time)
23
+ if @first_time
24
+ @first_time = date_time if date_time < @first_time
25
+ else
26
+ @first_time = date_time
27
+ end
28
+ if @last_time
29
+ @last_time = date_time if date_time > @last_time
30
+ else
31
+ @last_time = date_time
32
+ end
33
+ end
34
+ end
35
+
36
+ def required_timezones
37
+ @required_zones ||= {}
38
+ end
39
+
40
+ def required_zones
41
+ required_timezones.values
42
+ end
43
+
44
+ def export_to(export_stream)
45
+ required_zones.each do |z|
46
+ tzinfo_timezone =z.timezone
47
+ tzinfo_timezone.export_local_to(export_stream, z.first_time, z.last_time)
48
+ end
49
+ end
50
+
51
+ def add_datetime(date_time, tzid)
52
+ (required_timezones[tzid] ||= RequiredTimezone.new(tzid)).add_datetime(date_time)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ri_cal}
5
+ s.version = "0.5.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["author=Rick DeNatale"]
9
+ s.date = %q{2009-05-26}
10
+ s.default_executable = %q{ri_cal}
11
+ s.description = %q{This is an UNOFFICIAL version. The public official version will be released on RubyForge. Github will be used
12
+ for interim versions. USE THIS VERSION AT YOUR OWN RISK.
13
+
14
+ A new Ruby implementation of RFC2445 iCalendar.
15
+
16
+ The existing Ruby iCalendar libraries (e.g. icalendar, vpim) provide for parsing and generating icalendar files,
17
+ but do not support important things like enumerating occurrences of repeating events.
18
+
19
+ This is a clean-slate implementation of RFC2445.
20
+
21
+ A Google group for discussion of this library has been set up http://groups.google.com/group/rical_gem}
22
+ s.email = ["rick.denatale@gmail.com"]
23
+ s.executables = ["ri_cal"]
24
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt", "copyrights.txt", "docs/draft-ietf-calsify-2446bis-08.txt", "docs/draft-ietf-calsify-rfc2445bis-09.txt", "docs/incrementers.txt"]
25
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/ri_cal", "component_attributes/alarm.yml", "component_attributes/calendar.yml", "component_attributes/component_property_defs.yml", "component_attributes/event.yml", "component_attributes/freebusy.yml", "component_attributes/journal.yml", "component_attributes/timezone.yml", "component_attributes/timezone_period.yml", "component_attributes/todo.yml", "copyrights.txt", "docs/draft-ietf-calsify-2446bis-08.txt", "docs/draft-ietf-calsify-rfc2445bis-09.txt", "docs/incrementers.txt", "docs/rfc2445.pdf", "lib/ri_cal.rb", "lib/ri_cal/component.rb", "lib/ri_cal/component/alarm.rb", "lib/ri_cal/component/calendar.rb", "lib/ri_cal/component/event.rb", "lib/ri_cal/component/freebusy.rb", "lib/ri_cal/component/journal.rb", "lib/ri_cal/component/t_z_info_timezone.rb", "lib/ri_cal/component/timezone.rb", "lib/ri_cal/component/timezone/daylight_period.rb", "lib/ri_cal/component/timezone/standard_period.rb", "lib/ri_cal/component/timezone/timezone_period.rb", "lib/ri_cal/component/todo.rb", "lib/ri_cal/core_extensions.rb", "lib/ri_cal/core_extensions/array.rb", "lib/ri_cal/core_extensions/array/conversions.rb", "lib/ri_cal/core_extensions/date.rb", "lib/ri_cal/core_extensions/date/conversions.rb", "lib/ri_cal/core_extensions/date_time.rb", "lib/ri_cal/core_extensions/date_time/conversions.rb", "lib/ri_cal/core_extensions/object.rb", "lib/ri_cal/core_extensions/object/conversions.rb", "lib/ri_cal/core_extensions/string.rb", "lib/ri_cal/core_extensions/string/conversions.rb", "lib/ri_cal/core_extensions/time.rb", "lib/ri_cal/core_extensions/time/calculations.rb", "lib/ri_cal/core_extensions/time/conversions.rb", "lib/ri_cal/core_extensions/time/tzid_access.rb", "lib/ri_cal/core_extensions/time/week_day_predicates.rb", "lib/ri_cal/floating_timezone.rb", "lib/ri_cal/invalid_property_value.rb", "lib/ri_cal/invalid_timezone_identifer.rb", "lib/ri_cal/occurrence_enumerator.rb", "lib/ri_cal/occurrence_period.rb", "lib/ri_cal/parser.rb", "lib/ri_cal/properties/alarm.rb", "lib/ri_cal/properties/calendar.rb", "lib/ri_cal/properties/event.rb", "lib/ri_cal/properties/freebusy.rb", "lib/ri_cal/properties/journal.rb", "lib/ri_cal/properties/timezone.rb", "lib/ri_cal/properties/timezone_period.rb", "lib/ri_cal/properties/todo.rb", "lib/ri_cal/property_value.rb", "lib/ri_cal/property_value/array.rb", "lib/ri_cal/property_value/cal_address.rb", "lib/ri_cal/property_value/date.rb", "lib/ri_cal/property_value/date_time.rb", "lib/ri_cal/property_value/date_time/additive_methods.rb", "lib/ri_cal/property_value/date_time/time_machine.rb", "lib/ri_cal/property_value/date_time/timezone_support.rb", "lib/ri_cal/property_value/duration.rb", "lib/ri_cal/property_value/geo.rb", "lib/ri_cal/property_value/integer.rb", "lib/ri_cal/property_value/occurrence_list.rb", "lib/ri_cal/property_value/period.rb", "lib/ri_cal/property_value/recurrence_rule.rb", "lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb", "lib/ri_cal/property_value/recurrence_rule/enumerator.rb", "lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb", "lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb", "lib/ri_cal/property_value/recurrence_rule/numbered_span.rb", "lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb", "lib/ri_cal/property_value/recurrence_rule/recurring_day.rb", "lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb", "lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb", "lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb", "lib/ri_cal/property_value/recurrence_rule/validations.rb", "lib/ri_cal/property_value/text.rb", "lib/ri_cal/property_value/uri.rb", "lib/ri_cal/property_value/utc_offset.rb", "lib/ri_cal/required_timezones.rb", "ri_cal.gemspec", "sample_ical_files/from_ical_dot_app/test1.ics", "script/console", "script/destroy", "script/generate", "script/txt2html", "spec/ri_cal/component/alarm_spec.rb", "spec/ri_cal/component/calendar_spec.rb", "spec/ri_cal/component/event_spec.rb", "spec/ri_cal/component/freebusy_spec.rb", "spec/ri_cal/component/journal_spec.rb", "spec/ri_cal/component/t_z_info_timezone_spec.rb", "spec/ri_cal/component/timezone_spec.rb", "spec/ri_cal/component/todo_spec.rb", "spec/ri_cal/component_spec.rb", "spec/ri_cal/core_extensions/string/conversions_spec.rb", "spec/ri_cal/core_extensions/time/calculations_spec.rb", "spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb", "spec/ri_cal/occurrence_enumerator_spec.rb", "spec/ri_cal/parser_spec.rb", "spec/ri_cal/property_value/date_spec.rb", "spec/ri_cal/property_value/date_time_spec.rb", "spec/ri_cal/property_value/duration_spec.rb", "spec/ri_cal/property_value/occurrence_list_spec.rb", "spec/ri_cal/property_value/period_spec.rb", "spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb", "spec/ri_cal/property_value/recurrence_rule_spec.rb", "spec/ri_cal/property_value/text_spec.rb", "spec/ri_cal/property_value/utc_offset_spec.rb", "spec/ri_cal/property_value_spec.rb", "spec/ri_cal/required_timezones_spec.rb", "spec/ri_cal_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/gem_loader/load_active_support.rb", "tasks/gem_loader/load_tzinfo_gem.rb", "tasks/ri_cal.rake", "tasks/spec.rake"]
26
+ s.has_rdoc = true
27
+ s.homepage = %q{http://rical.rubyforge.org/}
28
+ s.rdoc_options = ["--main", "README.txt"]
29
+ s.require_paths = ["lib"]
30
+ s.rubyforge_project = %q{rical}
31
+ s.rubygems_version = %q{1.3.2}
32
+ s.summary = %q{This is an UNOFFICIAL version}
33
+
34
+ if s.respond_to? :specification_version then
35
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
39
+ s.add_development_dependency(%q<newgem>, [">= 1.3.0"])
40
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
41
+ else
42
+ s.add_dependency(%q<newgem>, [">= 1.3.0"])
43
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
44
+ end
45
+ else
46
+ s.add_dependency(%q<newgem>, [">= 1.3.0"])
47
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
48
+ end
49
+ end
@@ -0,0 +1,38 @@
1
+ BEGIN:VCALENDAR
2
+ METHOD:PUBLISH
3
+ X-WR-TIMEZONE:America/New_York
4
+ PRODID:-//Apple Inc.//iCal 3.0//EN
5
+ CALSCALE:GREGORIAN
6
+ X-WR-CALNAME:test
7
+ VERSION:2.0
8
+ X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
9
+ X-APPLE-CALENDAR-COLOR:#2CA10B
10
+ BEGIN:VTIMEZONE
11
+ TZID:US/Eastern
12
+ BEGIN:DAYLIGHT
13
+ TZOFFSETFROM:-0500
14
+ TZOFFSETTO:-0400
15
+ DTSTART:20070311T020000
16
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
17
+ TZNAME:EDT
18
+ END:DAYLIGHT
19
+ BEGIN:STANDARD
20
+ TZOFFSETFROM:-0400
21
+ TZOFFSETTO:-0500
22
+ DTSTART:20071104T020000
23
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
24
+ TZNAME:EST
25
+ END:STANDARD
26
+ END:VTIMEZONE
27
+ BEGIN:VEVENT
28
+ SEQUENCE:5
29
+ TRANSP:OPAQUE
30
+ UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
31
+ DTSTART;TZID=US/Eastern:20090224T090000
32
+ DTSTAMP:20090225T000908Z
33
+ SUMMARY:Test Event
34
+ CREATED:20090225T000839Z
35
+ DTEND;TZID=US/Eastern:20090224T100000
36
+ RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
37
+ END:VEVENT
38
+ END:VCALENDAR
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/ri_cal_newgem.rb'}"
9
+ puts "Loading ri_cal_newgem gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ load File.dirname(__FILE__) + "/../Rakefile"
4
+ require 'rubyforge'
5
+ require 'redcloth'
6
+ require 'syntax/convertors/html'
7
+ require 'erb'
8
+
9
+ download = "http://rubyforge.org/projects/#{$hoe.rubyforge_name}"
10
+ version = $hoe.version
11
+
12
+ def rubyforge_project_id
13
+ RubyForge.new.configure.autoconfig["group_ids"][$hoe.rubyforge_name]
14
+ end
15
+
16
+ class Fixnum #:nodoc:
17
+ def ordinal
18
+ # teens
19
+ return 'th' if (10..19).include?(self % 100)
20
+ # others
21
+ case self % 10
22
+ when 1: return 'st'
23
+ when 2: return 'nd'
24
+ when 3: return 'rd'
25
+ else return 'th'
26
+ end
27
+ end
28
+ end
29
+
30
+ class Time
31
+ def pretty
32
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
33
+ end
34
+ end
35
+
36
+ def convert_syntax(syntax, source)
37
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
38
+ end
39
+
40
+ if ARGV.length >= 1
41
+ src, template = ARGV
42
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
43
+ else
44
+ puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
45
+ exit!
46
+ end
47
+
48
+ template = ERB.new(File.open(template).read)
49
+
50
+ title = nil
51
+ body = nil
52
+ File.open(src) do |fsrc|
53
+ title_text = fsrc.readline
54
+ body_text_template = fsrc.read
55
+ body_text = ERB.new(body_text_template).result(binding)
56
+ syntax_items = []
57
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
58
+ ident = syntax_items.length
59
+ element, syntax, source = $1, $2, $3
60
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
61
+ "syntax-temp-#{ident}"
62
+ }
63
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
64
+ body = RedCloth.new(body_text).to_html
65
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
66
+ end
67
+ stat = File.stat(src)
68
+ created = stat.ctime
69
+ modified = stat.mtime
70
+
71
+ $stdout << template.result(binding)
@@ -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::Alarm do
6
+
7
+ describe ".entity_name" do
8
+ it "should be VALARM" do
9
+ RiCal::Component::Alarm.entity_name.should == "VALARM"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,54 @@
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::Calendar do
6
+
7
+ context ".entity_name" do
8
+ it "should be VCALENDAR" do
9
+ RiCal::Component::Calendar.entity_name.should == "VCALENDAR"
10
+ end
11
+ end
12
+
13
+ context "a new instance" do
14
+ before(:each) do
15
+ @it = RiCal.Calendar
16
+ end
17
+
18
+ it "should have a tz_source of 'TZ_INFO" do
19
+ @it.tz_source.should == "TZINFO"
20
+ end
21
+
22
+ it "should export a product id with an X-RICAL-TZSOURCE parameter of TZINFO" do
23
+ @it.export.should match(%r{\nPRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN\n})
24
+ end
25
+ end
26
+
27
+ context "an imported instance with a tzinfo source" do
28
+ before(:each) do
29
+ @it = RiCal.parse_string("BEGIN:VCALENDAR\nPRODID;X-RICAL-TZSOURCE=TZINFO:-\/\/com.denhaven2\/NONSGML ri_cal gem\/\/EN\nCALSCALE:GREGORIAN\nVERSION:2.0\nEND:VCALENDAR\n").first
30
+ end
31
+
32
+ it "should have a tz_source of 'TZ_INFO" do
33
+ @it.tz_source.should == "TZINFO"
34
+ end
35
+
36
+ it "should export a product id with an X-RICAL-TZSOURCE parameter of TZINFO" do
37
+ @it.export.should match(%r{\nPRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN\n})
38
+ end
39
+ end
40
+
41
+ context "an imported instance without a tzinfo source" do
42
+ before(:each) do
43
+ @it = RiCal.parse_string("BEGIN:VCALENDAR\nPRODID:-//Apple Inc.//iCal 3.0//EN\nEND:VCALENDAR\n").first
44
+ end
45
+
46
+ it "should have a tz_source of nil" do
47
+ @it.tz_source.should be_nil
48
+ end
49
+
50
+ it "should export not export a product id with an X-RICAL-TZSOURCE parameter of TZINFO" do
51
+ @it.export.should_not match(%r{X-RICAL-TZSOURCE=TZINFO:})
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,601 @@
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::Event do
6
+
7
+ context "rdate property methods" do
8
+ before(:each) do
9
+ @event = RiCal.Event do
10
+ rdate "20090101"
11
+ end
12
+ end
13
+
14
+ context "#rdate=" do
15
+
16
+ it "should accept a single Date and replace the existing rdate" do
17
+ @event.rdate = Date.parse("20090102")
18
+ @event.rdate.should == [[Date.parse("20090102")]]
19
+ end
20
+
21
+ it "should accept a single rfc2445 date format string and replace the existing rdate" do
22
+ @event.rdate = "20090102"
23
+ @event.rdate.should == [[Date.parse("20090102")]]
24
+ end
25
+
26
+ it "should accept a single DateTime and replace the existing rdate" do
27
+ @event.rdate = DateTime.parse("20090102T012345")
28
+ @event.rdate.should == [[DateTime.parse("20090102T012345")]]
29
+ end
30
+
31
+ it "should accept a single Time and replace the existing rdate" do
32
+ ::RiCal::PropertyValue::DateTime.default_tzid = 'UTC'
33
+ @event.rdate = Time.local(2009, 1, 2, 1, 23, 45)
34
+ @event.rdate.should == [[result_time_in_zone(2009, 1, 2, 1, 23, 45, "UTC")]]
35
+ end
36
+
37
+ it "should accept a single rfc2445 date-time format string and replace the existing rdate" do
38
+ @event.rdate = "20090102T012345"
39
+ @event.rdate.should == [[DateTime.parse("20090102T012345")]]
40
+ end
41
+
42
+ it "should accept a tzid prefixed rfc2445 date-time format string and replace the existing rdate" do
43
+ @event.rdate = "TZID=America/New_York:20090102T012345"
44
+ @event.rdate.should == [[result_time_in_zone(2009, 1, 2, 1, 23, 45, "America/New_York")]]
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ context "comment property methods" do
52
+ before(:each) do
53
+ @event = RiCal.Event
54
+ @event.comment = "Comment"
55
+ end
56
+
57
+ context "#comment=" do
58
+ it "should result in a single comment for the event" do
59
+ @event.comment.should == ["Comment"]
60
+ end
61
+
62
+ it "should replace existing comments" do
63
+ @event.comment = "Replacement"
64
+ @event.comment.should == ["Replacement"]
65
+ end
66
+ end
67
+
68
+ context "#comments=" do
69
+ it "should result in a multiple comments for the event replacing existing comments" do
70
+ @event.comments = "New1", "New2"
71
+ @event.comment.should == ["New1", "New2"]
72
+ end
73
+ end
74
+
75
+ context "#add_comment" do
76
+ it "should add a single comment" do
77
+ @event.add_comment "New1"
78
+ @event.comment.should == ["Comment", "New1"]
79
+ end
80
+ end
81
+
82
+ context "#add_comments" do
83
+ it "should add multiple comments" do
84
+ @event.add_comments "New1", "New2"
85
+ @event.comment.should == ["Comment", "New1", "New2"]
86
+ end
87
+ end
88
+
89
+ context "#remove_comment" do
90
+ it "should remove a single comment" do
91
+ @event.add_comment "New1"
92
+ @event.remove_comment "Comment"
93
+ @event.comment.should == ["New1"]
94
+ end
95
+ end
96
+
97
+ context "#remove_comments" do
98
+ it "should remove multiple comments" do
99
+ @event.add_comments "New1", "New2", "New3"
100
+ @event.remove_comments "New2", "Comment"
101
+ @event.comment.should == ["New1", "New3"]
102
+ end
103
+ end
104
+ end
105
+
106
+ context ".dtstart=" do
107
+ before(:each) do
108
+ @event = RiCal.Event
109
+ end
110
+
111
+ context "with a datetime only string" do
112
+ before(:each) do
113
+ @event.dtstart = "20090514T202400"
114
+ @it = @event.dtstart
115
+ end
116
+
117
+ it "should interpret it as the correct date-time" do
118
+ @it.should == DateTime.civil(2009, 5, 14, 20, 24, 00, Rational(0,24))
119
+ end
120
+
121
+ it "should interpret it as a floating date" do
122
+ @it.tzid.should == :floating
123
+ end
124
+ end
125
+
126
+ context "with a TZID and datetime string" do
127
+ before(:each) do
128
+ @event.dtstart = "TZID=America/New_York:20090514T202400"
129
+ @it = @event.dtstart
130
+ end
131
+
132
+ it "should interpret it as the correct date-time" do
133
+ @it.should == result_time_in_zone(2009, 5, 14, 20, 24, 00, "America/New_York")
134
+ end
135
+
136
+ it "should set the tzid to America/New_York" do
137
+ @it.tzid.should == "America/New_York"
138
+ end
139
+ end
140
+
141
+ context "with a zulu datetime only string" do
142
+ before(:each) do
143
+ @event.dtstart = "20090514T202400Z"
144
+ @it = @event.dtstart
145
+ end
146
+
147
+ it "should interpret it as the correct date-time" do
148
+ @it.should == DateTime.civil(2009, 5, 14, 20, 24, 00, Rational(0,24))
149
+ end
150
+
151
+ it "should set the tzid to UTC" do
152
+ @it.tzid.should == "UTC"
153
+ end
154
+ end
155
+
156
+ context "with a date string" do
157
+ before(:each) do
158
+ @event.dtstart = "20090514"
159
+ @it = @event.dtstart
160
+ end
161
+
162
+ it "should interpret it as the correct date-time" do
163
+ @it.should == Date.parse("14 May 2009")
164
+ end
165
+ end
166
+ end
167
+
168
+ context ".entity_name" do
169
+ it "should be VEVENT" do
170
+ RiCal::Component::Event.entity_name.should == "VEVENT"
171
+ end
172
+ end
173
+
174
+ context "with an rrule" do
175
+ before(:each) do
176
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nRRULE:FREQ=DAILY\nEND:VEVENT").first
177
+ end
178
+
179
+ it "should have an array of rrules" do
180
+ @it.rrule.should be_kind_of(Array)
181
+ end
182
+ end
183
+
184
+ context ".start_time" do
185
+
186
+ it "should be nil if there is no dtstart property" do
187
+ RiCal.Event.start_time.should be_nil
188
+ end
189
+
190
+ it "should be the same as dtstart for a date time" do
191
+ event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
192
+ event.start_time.should == DateTime.civil(2009,05,25,15,19,0,0)
193
+ end
194
+
195
+ it "should be the start of the day of dtstart for a date" do
196
+ event = RiCal.Event {|e| e.dtstart = "20090525"}
197
+ event.start_time.should == DateTime.civil(2009,05,25,0,0,0,0)
198
+ end
199
+ end
200
+
201
+ context ".finish_time" do
202
+ before(:each) do
203
+ @event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
204
+ end
205
+
206
+ context "with a given dtend" do
207
+ it "should be the same as dtend for a date time" do
208
+ @event.dtend = "20090525T161900"
209
+ @event.finish_time.should == DateTime.civil(2009,05,25,16,19,0,0)
210
+ end
211
+
212
+
213
+ end
214
+
215
+ context "with no dtend" do
216
+ context "and a duration" do
217
+ it "should be the dtstart plus the duration" do
218
+ @event.duration = "+P1H"
219
+ @event.finish_time.should == DateTime.civil(2009,5,25,16,19,0,0)
220
+ end
221
+ end
222
+
223
+ context "and no duration" do
224
+ context "when the dtstart is not set" do
225
+ before(:each) do
226
+ @event.dtstart_property = nil
227
+ end
228
+
229
+ it "should be nil" do
230
+ @event.finish_time.should be_nil
231
+ end
232
+ end
233
+ context "when the dstart is a datetime" do
234
+ # For cases where a "VEVENT" calendar component
235
+ # specifies a "DTSTART" property with a DATE-TIME data type but no
236
+ # "DTEND" property, the event ends on the same calendar date and time
237
+ # of day specified by the "DTSTART" property. RFC 2445 p 53
238
+ it "should be the same as start_time" do
239
+ @event.finish_time.should == @event.start_time
240
+ end
241
+ end
242
+ context "when the dtstart is a date" do
243
+ # For cases where a "VEVENT" calendar component specifies a "DTSTART" property with a DATE data type
244
+ # but no "DTEND" property, the events non-inclusive end is the end of the calendar date specified by
245
+ # the "DTSTART" property. RFC 2445 p 53
246
+
247
+ it "should be the end of the same day as start_time" do
248
+ @event.dtstart = "20090525"
249
+ @event.finish_time.should == DateTime.civil(2009,5,25,23,59,59,0)
250
+ end
251
+ end
252
+ end
253
+ end
254
+
255
+ end
256
+
257
+ context ".zulu_occurrence_range_start_time" do
258
+
259
+ it "should be nil if there is no dtstart property" do
260
+ RiCal.Event.zulu_occurrence_range_start_time.should be_nil
261
+ end
262
+
263
+ it "should be the utc equivalent of dtstart for a date time" do
264
+ event = RiCal.Event {|e| e.dtstart = "TZID=America/New_York:20090525T151900"}
265
+ event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,25,19,19,0,0)
266
+ end
267
+
268
+ it "should be the utc time of the start of the day of dtstart in the earliest timezone for a date" do
269
+ event = RiCal.Event {|e| e.dtstart = "20090525"}
270
+ event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,24,12,0,0,0)
271
+ end
272
+
273
+ it "should be the utc time of the dtstart in the earliest timezone if dtstart is a floating datetime" do
274
+ event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
275
+ event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,25,3,19,0,0)
276
+ end
277
+ end
278
+
279
+ context ".zulu_occurrence_range_finish_time" do
280
+ before(:each) do
281
+ @event = RiCal.Event {|e| e.dtstart = "TZID=America/New_York:20090525T151900"}
282
+ end
283
+
284
+ context "with a given dtend" do
285
+ it "should be the utc equivalent of dtend if dtend is a date time" do
286
+ @event.dtend = "TZID=America/New_York:20090525T161900"
287
+ @event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,05,25, 20,19,0,0)
288
+ end
289
+ end
290
+
291
+ context "with no dtend" do
292
+ context "and a duration" do
293
+ it "should be the dtstart plus the duration" do
294
+ @event.duration = "+P1H"
295
+ @event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,5,25,20 ,19,0,0)
296
+ end
297
+ end
298
+
299
+ context "and no duration" do
300
+ context "when the dtstart is not set" do
301
+ before(:each) do
302
+ @event.dtstart_property = nil
303
+ end
304
+
305
+ it "should be nil" do
306
+ @event.zulu_occurrence_range_finish_time.should be_nil
307
+ end
308
+ end
309
+
310
+ context "when the dstart is a datetime" do
311
+
312
+ it "should be the same as start_time" do
313
+ @event.zulu_occurrence_range_finish_time.should == @event.zulu_occurrence_range_start_time
314
+ end
315
+ end
316
+
317
+ context "when the dtstart is a date" do
318
+ it "should be the utc of end of the same day as start_time in the westermost time zone" do
319
+ @event.dtstart = "20090525"
320
+ @event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,5,26,11,59,59,0)
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+
327
+ context "description property" do
328
+ before(:each) do
329
+ @ical_desc = "posted by Joyce per Zan\\nASheville\\, Rayan's Restauratn\\, Biltm\n ore Square"
330
+ @ruby_desc = "posted by Joyce per Zan\nASheville, Rayan's Restauratn, Biltmore Square"
331
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDESCRIPTION:#{@ical_desc}\nEND:VEVENT").first
332
+ end
333
+
334
+ it "should product the converted ruby value" do
335
+ @it.description.should == @ruby_desc
336
+ end
337
+
338
+ it "should produce escaped text for ical" do
339
+ @it.description = "This is a\nnew description, yes; it is"
340
+ @it.description_property.value.should == 'This is a\nnew description\, yes\; it is'
341
+ end
342
+
343
+ end
344
+
345
+ context "with both dtend and duration specified" do
346
+ before(:each) do
347
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nDURATION:H1\nEND:VEVENT").first
348
+ end
349
+
350
+ it "should be invalid" do
351
+ @it.should_not be_valid
352
+ end
353
+ end
354
+
355
+ context "with a duration property" do
356
+ before(:each) do
357
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDURATION:H1\nEND:VEVENT").first
358
+ end
359
+
360
+ it "should have a duration property" do
361
+ @it.duration_property.should be
362
+ end
363
+
364
+ it "should have a duration of 1 Hour" do
365
+ @it.duration_property.value.should == "H1"
366
+ end
367
+
368
+ it "should reset the duration property if the dtend property is set" do
369
+ @it.dtend_property = "19970101T123456".to_ri_cal_date_time_value
370
+ @it.duration_property.should be_nil
371
+ end
372
+
373
+ it "should reset the duration property if the dtend ruby value is set" do
374
+ @it.dtend = "19970101"
375
+ @it.duration_property.should == nil
376
+ end
377
+ end
378
+
379
+ context "with a dtend property" do
380
+ before(:each) do
381
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nEND:VEVENT").first
382
+ end
383
+
384
+ it "should have a duration property" do
385
+ @it.dtend_property.should be
386
+ end
387
+
388
+ it "should reset the dtend property if the duration property is set" do
389
+ @it.duration_property = "P1H".to_ri_cal_duration_value
390
+ @it.dtend_property.should be_nil
391
+ end
392
+
393
+ it "should reset the dtend property if the duration ruby value is set" do
394
+ @it.duration = "P1H".to_ri_cal_duration_value
395
+ @it.dtend_property.should be_nil
396
+ end
397
+ end
398
+
399
+ context "with a nested alarm component" do
400
+ before(:each) do
401
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\n\nBEGIN:VALARM\nEND:VALARM\nEND:VEVENT").first
402
+ end
403
+
404
+ it "should have one alarm" do
405
+ @it.alarms.length.should == 1
406
+ end
407
+
408
+ it "which should be an Alarm component" do
409
+ @it.alarms.first.should be_kind_of(RiCal::Component::Alarm)
410
+ end
411
+ end
412
+
413
+ context ".export" do
414
+ require 'rubygems'
415
+ require 'tzinfo'
416
+
417
+ def date_time_with_tzinfo_zone(date_time, timezone="America/New_York")
418
+ date_time.dup.set_tzid(timezone)
419
+ end
420
+
421
+ # Undo the effects of RFC2445 line folding
422
+ def unfold(string)
423
+ string.gsub("\n ", "")
424
+ end
425
+
426
+ before(:each) do
427
+ cal = RiCal.Calendar
428
+ @it = RiCal::Component::Event.new(cal)
429
+ end
430
+
431
+ it "should cause a VTIMEZONE to be included for a dtstart with a local timezone" do
432
+ @it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
433
+ unfold(@it.export).should match(/BEGIN:VTIMEZONE\nTZID;X-RICAL-TZSOURCE=TZINFO:America\/New_York\n/)
434
+ end
435
+
436
+ it "should properly format dtstart with a UTC date-time" do
437
+ @it.dtstart = DateTime.parse("April 22, 2009 1:23:45").set_tzid("UTC")
438
+ unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345Z$/)
439
+ end
440
+
441
+ it "should properly format dtstart with a floating date-time" do
442
+ @it.dtstart = DateTime.parse("April 22, 2009 1:23:45").with_floating_timezone
443
+ unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345$/)
444
+ end
445
+
446
+ it "should properly format dtstart with a local time zone" do
447
+ @it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
448
+ unfold(@it.export).should match(/^DTSTART;TZID=America\/New_York;VALUE=DATE-TIME:20090422T175500$/)
449
+ end
450
+
451
+ it "should properly format dtstart with a date" do
452
+ @it.dtstart = Date.parse("April 22, 2009")
453
+ unfold(@it.export).should match(/^DTSTART;VALUE=DATE:20090422$/)
454
+ end
455
+
456
+ it "should properly fold on export when the description contains a carriage return" do
457
+ @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"
458
+ export_string = @it.export
459
+ export_string.should match(%r(^DESCRIPTION:Weather report looks nice\\, 80 degrees and partly cloudy\\, so$))
460
+ export_string.should match(%r(^ following Michael's suggestion\\, let's meet at the food court at Crossr$))
461
+ export_string.should match(%r(^ oads:\\nhttp://www\.shopcrossroadsplaza.c\.\.\.\\n$))
462
+ end
463
+ end
464
+
465
+ if RiCal::TimeWithZone
466
+ context "with ActiveSupport loaded" do
467
+
468
+ context "an event with an timezoned exdate" do
469
+ before(:each) do
470
+ @old_timezone = Time.zone
471
+ Time.zone = "America/New_York"
472
+ @exception_date_time = Time.zone.local(2009, 5, 19, 11, 13)
473
+ cal = RiCal.Calendar do |cal|
474
+ cal.event do |event|
475
+ event.add_exdate @exception_date_time
476
+ end
477
+ end
478
+ @event = cal.events.first
479
+ end
480
+
481
+ after(:each) do
482
+ Time.zone = @old_timezone
483
+ end
484
+
485
+ it "should pickup the timezone in the exdate property" do
486
+ @event.exdate.first.first.tzid.should == "America/New_York"
487
+ end
488
+
489
+ it "should have the timezone in the ical representation of the exdate property" do
490
+ @event.exdate_property.to_s.should match(%r{;TZID=America/New_York[:;]})
491
+ end
492
+ end
493
+
494
+ context "An event in a non-tzinfo source calendar" do
495
+ before(:each) do
496
+ cals = RiCal.parse_string <<ENDCAL
497
+ BEGIN:VCALENDAR
498
+ X-WR-TIMEZONE:America/New_York
499
+ PRODID:-//Apple Inc.//iCal 3.0//EN
500
+ CALSCALE:GREGORIAN
501
+ BEGIN:VTIMEZONE
502
+ TZID:US/Eastern
503
+ BEGIN:DAYLIGHT
504
+ TZOFFSETFROM:-0500
505
+ TZOFFSETTO:-0400
506
+ DTSTART:20070311T020000
507
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
508
+ TZNAME:EDT
509
+ END:DAYLIGHT
510
+ BEGIN:STANDARD
511
+ TZOFFSETFROM:-0400
512
+ TZOFFSETTO:-0500
513
+ DTSTART:20071104T020000
514
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
515
+ TZNAME:EST
516
+ END:STANDARD
517
+ END:VTIMEZONE
518
+ BEGIN:VEVENT
519
+ SEQUENCE:5
520
+ TRANSP:OPAQUE
521
+ UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
522
+ DTSTART;TZID=US/Eastern:20090224T090000
523
+ DTSTAMP:20090225T000908Z
524
+ SUMMARY:Test Event
525
+ CREATED:20090225T000839Z
526
+ DTEND;TZID=US/Eastern:20090224T100000
527
+ RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
528
+ END:VEVENT
529
+ END:VCALENDAR
530
+ ENDCAL
531
+ @event = cals.first.events.first
532
+ end
533
+
534
+ it "should produce a DateTime for dtstart" do
535
+ @event.dtstart.should be_instance_of(DateTime)
536
+ end
537
+ end
538
+
539
+ context "An event starting in Paris and ending in New York" do
540
+
541
+ before(:each) do
542
+ @start = Time.now.utc.in_time_zone("Europe/Paris")
543
+ @finish = Time.now.utc.in_time_zone("America/New_York")
544
+ cal = RiCal.Calendar do |ical|
545
+ ical.event do |ievent|
546
+ ievent.dtstart @start
547
+ ievent.dtend @finish
548
+ end
549
+ end
550
+ @event = cal.events.first
551
+ end
552
+
553
+ it "should have the right time zone for dtstart" do
554
+ @event.dtstart.tzid.should == "Europe/Paris"
555
+ end
556
+
557
+ it "should produce a TimeWithZone for dtstart" do
558
+ @event.dtstart.should be_instance_of(RiCal::TimeWithZone)
559
+ end
560
+
561
+ # ActiveRecord::TimeWithZone doesn't implement == as expected
562
+ it "should produce a dtstart which looks like the provided value" do
563
+ @event.dtstart.to_s.should == @start.to_s
564
+ end
565
+
566
+ it "should have the right time zone for dtend" do
567
+ @event.dtend.tzid.should == "America/New_York"
568
+ end
569
+
570
+ it "should produce a TimeWithZone for dtend" do
571
+ @event.dtend.should be_instance_of(RiCal::TimeWithZone)
572
+ end
573
+
574
+ # ActiveRecord::TimeWithZone doesn't implement == as expected
575
+ it "should produce a dtend which looks like the provided value" do
576
+ @event.dtend.to_s.should == @finish.to_s
577
+ end
578
+ end
579
+ end
580
+ end
581
+
582
+ context "An event with a floating start" do
583
+
584
+ before(:each) do
585
+ cal = RiCal.Calendar do |ical|
586
+ ical.event do |ievent|
587
+ ievent.dtstart "20090530T120000"
588
+ end
589
+ end
590
+ @event = cal.events.first
591
+ end
592
+
593
+ it "should produce a DateTime for dtstart" do
594
+ @event.dtstart.should be_instance_of(DateTime)
595
+ end
596
+
597
+ it "should have a floating dtstart" do
598
+ @event.dtstart.should have_floating_timezone
599
+ end
600
+ end
601
+ end