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.
- checksums.yaml +7 -0
- data/History.txt +5 -0
- data/README.rdoc +6 -1
- data/icalendar.gemspec +1 -0
- data/lib/icalendar/base.rb +1 -1
- data/lib/icalendar/parser.rb +13 -5
- data/lib/icalendar/tzinfo.rb +72 -72
- data/test/test_parser.rb +15 -0
- data/test/test_tzinfo.rb +27 -0
- metadata +14 -22
checksums.yaml
ADDED
@@ -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
|
data/History.txt
CHANGED
@@ -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
|
data/README.rdoc
CHANGED
@@ -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
|
data/icalendar.gemspec
CHANGED
data/lib/icalendar/base.rb
CHANGED
data/lib/icalendar/parser.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/icalendar/tzinfo.rb
CHANGED
@@ -42,80 +42,80 @@
|
|
42
42
|
# require "tzinfo"
|
43
43
|
|
44
44
|
module TZInfo
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
data/test/test_parser.rb
CHANGED
@@ -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.
|
data/test/test_tzinfo.rb
ADDED
@@ -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.
|
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-
|
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:
|
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:
|
179
|
+
rubygems_version: 2.0.3
|
189
180
|
signing_key:
|
190
|
-
specification_version:
|
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
|