icalendar 1.2.4 → 1.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aee422660be821b5fa0060bd0344282e673db97f
4
+ data.tar.gz: 95df849c43f1868e9cf7a9f644fffc9384afce97
5
+ SHA512:
6
+ metadata.gz: a3108d6a9d6474c9210e083653fbfd1fc9e9979f8c5093ea1bab7f03c6263c687c261c5cab8d8fecd5ff6b80d539d877f33c7b15ac782e9b75cb4c5e9c255f1b
7
+ data.tar.gz: 9f6d142d8f346c422ed99d56b2f386419647f1a502f7c77787a0c730dcf4287a0fe9463abc174957808ba89413549b3082a17672f22da3e4d00adc2ff169bde0
@@ -1,3 +1,8 @@
1
+ === 1.3.0 2013-03-31
2
+ * Lenient parsing mode ignores unknown properties - David Grandinetti
3
+ * VTIMEZONE positive offsets properly have "+" prepended (Fixed issue
4
+ #18) - Benjamin Jorgensen (sorry for misspelling your last name)
5
+
1
6
  === 1.2.4 2013-03-26
2
7
  * Proxy component values now frozen in Ruby 2.0 (Fixed issue #17)
3
8
  * Clean up gemspec for cleaner installing via bundler/git
@@ -215,13 +215,18 @@ Add `$KCODE = 'u'` to make icalender work correctly with Utf8 texts
215
215
  # can have multiple calendars.
216
216
  cals = Icalendar.parse(cal_file)
217
217
  cal = cals.first
218
-
218
+
219
219
  # Now you can access the cal object in just the same way I created it
220
220
  event = cal.events.first
221
221
 
222
222
  puts "start date-time: " + event.dtstart
223
223
  puts "summary: " + event.summary
224
224
 
225
+ # Some calendars contain non-standard parameters (e.g. Apple iCloud
226
+ # calendars). You can pass in a `strict` value when creating a new parser.
227
+ unstrict_parser = Icalendar::Parser.new(cal_file, false)
228
+ cal = unstrict_parser.parse()
229
+
225
230
  == Finders:
226
231
 
227
232
  Often times in web apps and other interactive applications you'll need to
@@ -16,5 +16,6 @@ Gem::Specification.new do |s|
16
16
  s.add_development_dependency 'newgem', '~> 1.5'
17
17
  s.add_development_dependency 'rubyforge', '~> 2.0'
18
18
  s.add_development_dependency 'rdoc', '~> 4.0'
19
+ s.add_development_dependency 'tzinfo', '~> 0.3'
19
20
  end
20
21
 
@@ -11,7 +11,7 @@ require 'logger'
11
11
 
12
12
  module Icalendar #:nodoc:
13
13
 
14
- VERSION = '1.2.4'
14
+ VERSION = '1.3.0'
15
15
 
16
16
  # A simple error class to differentiate iCalendar library exceptions
17
17
  # from ruby language exceptions or others.
@@ -39,9 +39,17 @@ module Icalendar
39
39
  # time-numzome = sign time-hour [":"] time-minute
40
40
  TIME = '(\d\d):?(\d\d):?(\d\d)(\.\d+)?(Z|[-+]\d\d:?\d\d)?'
41
41
 
42
- def initialize(src)
42
+ # Defines if this is a strict parser.
43
+ attr_accessor :strict
44
+
45
+ def initialize(src, strict = true)
43
46
  # Setup the parser method hash table
44
- setup_parsers()
47
+ setup_parsers
48
+
49
+ # The default behavior is to raise an error when the parser
50
+ # finds an unknown property. Set this to false to discard
51
+ # unknown properties instead of raising an error.
52
+ @strict = strict
45
53
 
46
54
  if src.respond_to?(:gets)
47
55
  @file = src
@@ -99,7 +107,7 @@ module Icalendar
99
107
 
100
108
  # Just iterate through until we find the beginning of a calendar object
101
109
  if fields[:name] == "BEGIN" and fields[:value] == "VCALENDAR"
102
- cal = parse_component
110
+ cal = parse_component Calendar.new
103
111
  @@logger.debug "Added parsed calendar..."
104
112
  calendars << cal
105
113
  end
@@ -173,13 +181,13 @@ module Icalendar
173
181
  if component.respond_to?(adder)
174
182
  component.send(adder, value, params)
175
183
  else
176
- raise(UnknownPropertyMethod, "Unknown property type: #{adder}")
184
+ raise(UnknownPropertyMethod, "Unknown property type: #{adder}") if strict
177
185
  end
178
186
  else
179
187
  if component.respond_to?(name)
180
188
  component.send(name, value, params)
181
189
  else
182
- raise(UnknownPropertyMethod, "Unknown property type: #{name}")
190
+ raise(UnknownPropertyMethod, "Unknown property type: #{name}") if strict
183
191
  end
184
192
  end
185
193
  end
@@ -42,80 +42,80 @@
42
42
  # require "tzinfo"
43
43
 
44
44
  module TZInfo
45
- class Timezone
46
- def ical_timezone(date)
47
- period = period_for_local(date)
48
- timezone = Icalendar::Timezone.new
49
- timezone.timezone_id = identifier
50
- timezone.add(period.daylight)
51
- timezone.add(period.standard)
52
- return timezone
53
- end
45
+ class Timezone
46
+ def ical_timezone(date)
47
+ period = period_for_local(date)
48
+ timezone = Icalendar::Timezone.new
49
+ timezone.timezone_id = identifier
50
+ timezone.add(period.daylight)
51
+ timezone.add(period.standard)
52
+ return timezone
54
53
  end
55
-
56
- class TimezoneTransitionInfo
57
- def offset_from
58
- a = previous_offset.utc_total_offset
59
- sprintf("%2.2d%2.2d", (a / 3600).to_i, ((a / 60) % 60).to_i)
60
- end
61
-
62
- def offset_to
63
- a = offset.utc_total_offset
64
- sprintf("%2.2d%2.2d", (a / 3600).to_i, ((a / 60) % 60).to_i)
65
- end
66
-
67
- def rrule
68
- start = local_start.to_datetime
69
- # this is somewhat of a hack, but seems to work ok
70
- [sprintf(
71
- "FREQ=YEARLY;BYMONTH=%d;BYDAY=%d%s",
72
- start.month,
73
- ((start.day - 1)/ 7).to_i + 1,
74
- start.strftime("%a").upcase[0,2]
75
- )]
76
- end
77
-
78
- def dtstart
79
- local_start.to_datetime.strftime("%Y%m%dT%H%M%S")
80
- end
54
+ end
81
55
 
56
+ class TimezoneTransitionInfo
57
+ def offset_from
58
+ a = previous_offset.utc_total_offset
59
+ sprintf("%+-2.2d%2.2d", (a / 3600).to_i, ((a / 60) % 60).to_i)
82
60
  end
83
-
84
- class TimezonePeriod
85
- def daylight
86
- day = Icalendar::Daylight.new
87
- if dst?
88
- day.timezone_name = abbreviation.to_s
89
- day.timezone_offset_from = start_transition.offset_from
90
- day.timezone_offset_to = start_transition.offset_to
91
- day.dtstart = start_transition.dtstart
92
- day.recurrence_rules = start_transition.rrule
93
- else
94
- day.timezone_name = abbreviation.to_s.sub("ST","DT")
95
- day.timezone_offset_from = end_transition.offset_from
96
- day.timezone_offset_to = end_transition.offset_to
97
- day.dtstart = end_transition.dtstart
98
- day.recurrence_rules = end_transition.rrule
99
- end
100
- return day
101
- end
102
-
103
- def standard
104
- std = Icalendar::Standard.new
105
- if dst?
106
- std.timezone_name = abbreviation.to_s.sub("DT","ST")
107
- std.timezone_offset_from = end_transition.offset_from
108
- std.timezone_offset_to = end_transition.offset_to
109
- std.dtstart = end_transition.dtstart
110
- std.recurrence_rules = end_transition.rrule
111
- else
112
- std.timezone_name = abbreviation.to_s
113
- std.timezone_offset_from = start_transition.offset_from
114
- std.timezone_offset_to = start_transition.offset_to
115
- std.dtstart = start_transition.dtstart
116
- std.recurrence_rules = start_transition.rrule
117
- end
118
- return std
119
- end
61
+
62
+ def offset_to
63
+ a = offset.utc_total_offset
64
+ sprintf("%+-2.2d%2.2d", (a / 3600).to_i, ((a / 60) % 60).to_i)
65
+ end
66
+
67
+ def rrule
68
+ start = local_start.to_datetime
69
+ # this is somewhat of a hack, but seems to work ok
70
+ [sprintf(
71
+ "FREQ=YEARLY;BYMONTH=%d;BYDAY=%d%s",
72
+ start.month,
73
+ ((start.day - 1)/ 7).to_i + 1,
74
+ start.strftime("%a").upcase[0,2]
75
+ )]
76
+ end
77
+
78
+ def dtstart
79
+ local_start.to_datetime.strftime("%Y%m%dT%H%M%S")
80
+ end
81
+
82
+ end
83
+
84
+ class TimezonePeriod
85
+ def daylight
86
+ day = Icalendar::Daylight.new
87
+ if dst?
88
+ day.timezone_name = abbreviation.to_s
89
+ day.timezone_offset_from = start_transition.offset_from
90
+ day.timezone_offset_to = start_transition.offset_to
91
+ day.dtstart = start_transition.dtstart
92
+ day.recurrence_rules = start_transition.rrule
93
+ else
94
+ day.timezone_name = abbreviation.to_s.sub("ST","DT")
95
+ day.timezone_offset_from = end_transition.offset_from
96
+ day.timezone_offset_to = end_transition.offset_to
97
+ day.dtstart = end_transition.dtstart
98
+ day.recurrence_rules = end_transition.rrule
99
+ end
100
+ return day
101
+ end
102
+
103
+ def standard
104
+ std = Icalendar::Standard.new
105
+ if dst?
106
+ std.timezone_name = abbreviation.to_s.sub("DT","ST")
107
+ std.timezone_offset_from = end_transition.offset_from
108
+ std.timezone_offset_to = end_transition.offset_to
109
+ std.dtstart = end_transition.dtstart
110
+ std.recurrence_rules = end_transition.rrule
111
+ else
112
+ std.timezone_name = abbreviation.to_s
113
+ std.timezone_offset_from = start_transition.offset_from
114
+ std.timezone_offset_to = start_transition.offset_to
115
+ std.dtstart = start_transition.dtstart
116
+ std.recurrence_rules = start_transition.rrule
117
+ end
118
+ return std
120
119
  end
120
+ end
121
121
  end
@@ -7,6 +7,7 @@ require 'icalendar'
7
7
  class TestIcalendarParser < Test::Unit::TestCase
8
8
 
9
9
  TEST_CAL = File.join(File.dirname(__FILE__), 'fixtures', 'single_event.ics')
10
+ NONSTANDARD = File.join(File.dirname(__FILE__), 'fixtures', 'nonstandard.ics')
10
11
 
11
12
  # First make sure that we can run the parser and get back objects.
12
13
  def test_new
@@ -43,6 +44,20 @@ class TestIcalendarParser < Test::Unit::TestCase
43
44
  do_asserts(cals)
44
45
  end
45
46
 
47
+ def test_strict_parser
48
+ File.open(NONSTANDARD) do |cal_file|
49
+ assert_raise(Icalendar::UnknownPropertyMethod) do
50
+ Icalendar::Parser.new(cal_file).parse
51
+ end
52
+ end
53
+ end
54
+
55
+ def test_lenient_parser
56
+ File.open(NONSTANDARD) do |cal_file|
57
+ do_asserts Icalendar::Parser.new(cal_file, false).parse
58
+ end
59
+ end
60
+
46
61
  # Just a helper method so we don't have to repeat the same tests.
47
62
  def do_asserts(cals)
48
63
  # Should just get one calendar back.
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require 'test/unit'
4
+ require 'icalendar'
5
+ require 'tzinfo'
6
+ require 'icalendar/tzinfo'
7
+
8
+ class TestTZInfoExt < Test::Unit::TestCase
9
+ def setup
10
+ tz = TZInfo::Timezone.get("Europe/Copenhagen")
11
+ @timezone = tz.ical_timezone(DateTime.new(1970))
12
+ end
13
+
14
+ def test_daylight_offset
15
+ tz_offset_from = @timezone.instance_variable_get("@components")[:daylights][0].properties["tzoffsetfrom"]
16
+ tz_offset_to = @timezone.instance_variable_get("@components")[:daylights][0].properties["tzoffsetto"]
17
+ assert_equal "+0100", tz_offset_from
18
+ assert_equal "+0200", tz_offset_to
19
+ end
20
+
21
+ def test_standard_offset
22
+ tz_offset_from = @timezone.instance_variable_get("@components")[:standards][0].properties["tzoffsetfrom"]
23
+ tz_offset_to = @timezone.instance_variable_get("@components")[:standards][0].properties["tzoffsetto"]
24
+ assert_equal "+0200", tz_offset_from
25
+ assert_equal "+0100", tz_offset_to
26
+ end
27
+ end
metadata CHANGED
@@ -1,36 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icalendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
5
- prerelease:
4
+ version: 1.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ryan Ahearn
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-27 00:00:00.000000000 Z
11
+ date: 2013-04-01 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rubyforge
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 2.0.4
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 2.0.4
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rdoc
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,23 +41,20 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: newgem
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: 1.5.3
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: 1.5.3
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: hoe
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,12 +62,11 @@ dependencies:
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
77
68
  version: '3.5'
78
- description: ! "This is a Ruby library for dealing with iCalendar files. Rather than\nexplaining
69
+ description: "This is a Ruby library for dealing with iCalendar files. Rather than\nexplaining
79
70
  myself, here is the introduction from RFC-2445, which\ndefines the format:\n\nThe
80
71
  use of calendaring and scheduling has grown considerably in the\nlast decade. Enterprise
81
72
  and inter-enterprise business has become\ndependent on rapid scheduling of events
@@ -162,9 +153,11 @@ files:
162
153
  - website/javascripts/rounded_corners_lite.inc.js
163
154
  - website/stylesheets/screen.css
164
155
  - website/template.html.erb
156
+ - test/test_tzinfo.rb
165
157
  - .gemtest
166
158
  homepage: http://github.com/icalendar/icalendar
167
159
  licenses: []
160
+ metadata: {}
168
161
  post_install_message:
169
162
  rdoc_options:
170
163
  - --main
@@ -172,22 +165,20 @@ rdoc_options:
172
165
  require_paths:
173
166
  - lib
174
167
  required_ruby_version: !ruby/object:Gem::Requirement
175
- none: false
176
168
  requirements:
177
- - - ! '>='
169
+ - - '>='
178
170
  - !ruby/object:Gem::Version
179
171
  version: '0'
180
172
  required_rubygems_version: !ruby/object:Gem::Requirement
181
- none: false
182
173
  requirements:
183
- - - ! '>='
174
+ - - '>='
184
175
  - !ruby/object:Gem::Version
185
176
  version: '0'
186
177
  requirements: []
187
178
  rubyforge_project: icalendar
188
- rubygems_version: 1.8.25
179
+ rubygems_version: 2.0.3
189
180
  signing_key:
190
- specification_version: 3
181
+ specification_version: 4
191
182
  summary: This is a Ruby library for dealing with iCalendar files
192
183
  test_files:
193
184
  - test/component/test_event.rb
@@ -199,3 +190,4 @@ test_files:
199
190
  - test/test_helper.rb
200
191
  - test/test_parameter.rb
201
192
  - test/test_parser.rb
193
+ - test/test_tzinfo.rb