icalendar 2.0.0.beta.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/History.txt +4 -0
- data/README.md +7 -3
- data/icalendar.gemspec +11 -1
- data/lib/icalendar.rb +11 -1
- data/lib/icalendar/logger.rb +16 -0
- data/lib/icalendar/parser.rb +16 -7
- data/lib/icalendar/tzinfo.rb +50 -22
- data/lib/icalendar/version.rb +1 -1
- data/spec/fixtures/nonstandard.ics +25 -0
- data/spec/roundtrip_spec.rb +17 -0
- data/spec/tzinfo_spec.rb +1 -1
- metadata +24 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bec860be74d825a4185f664e5faf729a7dab764
|
4
|
+
data.tar.gz: 5b4f8aa6e13794637bd35e1094df96426a8622c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2097431525222e84223153f4e1288363600c9635fa29ce951de03ddcb8f400b327d55561861f14032df344db8acc1157c44395cd5a42f1f95eef312555f7cb6
|
7
|
+
data.tar.gz: 7b26558a56b5a5e40ab08c4841288122810151de6f701deeb76da0785af4ae57cc0fc2a335354e587a7e2e433f9708640aa3db7108a722bbe48cd370a9d6f0e2
|
data/.gitignore
CHANGED
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -64,20 +64,22 @@ EXAMPLES
|
|
64
64
|
|
65
65
|
params = {"altrep" => "http://my.language.net", "language" => "SPANISH"}
|
66
66
|
|
67
|
-
cal.event do |e|
|
67
|
+
event = cal.event do |e|
|
68
68
|
e.dtstart = Icalendar::Values::Date.new('20050428')
|
69
69
|
e.dtend = Icalendar::Values::Date.new('20050429')
|
70
70
|
e.summary = Icalendar::Values::Text.new "This is a summary with params.", params
|
71
71
|
end
|
72
|
+
event.summary.ical_params #=> {'altrep' => 'http://my.language.net', 'language' => 'SPANISH'}
|
72
73
|
|
73
74
|
# or
|
74
75
|
|
75
|
-
cal.event do |e|
|
76
|
+
event = cal.event do |e|
|
76
77
|
e.dtstart = Icalendar::Values::Date.new('20050428')
|
77
78
|
e.dtend = Icalendar::Values::Date.new('20050429')
|
78
79
|
e.summary = "This is a summary with params."
|
79
80
|
e.summary.ical_params = params
|
80
81
|
end
|
82
|
+
event.summary.ical_params #=> {'altrep' => 'http://my.language.net', 'language' => 'SPANISH'}
|
81
83
|
|
82
84
|
#### We can output the calendar as a string ####
|
83
85
|
|
@@ -184,7 +186,9 @@ TIMEZONES
|
|
184
186
|
# END:VTIMEZONE
|
185
187
|
|
186
188
|
iCalendar has some basic support for creating VTIMEZONE blocks from timezone information pulled from `tzinfo`.
|
187
|
-
You must require `tzinfo` support manually to take advantage
|
189
|
+
You must require `tzinfo` support manually to take advantage.
|
190
|
+
|
191
|
+
iCalendar has been tested and works with `tzinfo` versions 0.3 and 1.1
|
188
192
|
|
189
193
|
#### Example ####
|
190
194
|
|
data/icalendar.gemspec
CHANGED
@@ -22,9 +22,19 @@ variety of calendaring applications.
|
|
22
22
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename f }
|
23
23
|
s.require_paths = ['lib']
|
24
24
|
|
25
|
+
s.required_ruby_version = '>= 1.9.3'
|
26
|
+
|
25
27
|
s.add_development_dependency 'rake', '~> 10.0'
|
26
28
|
s.add_development_dependency 'bundler', '~> 1.3'
|
27
|
-
|
29
|
+
|
30
|
+
# test with both groups of tzinfo dependencies
|
31
|
+
# tzinfo 1.x
|
32
|
+
s.add_development_dependency 'tzinfo', '~> 1.1'
|
33
|
+
s.add_development_dependency 'tzinfo-data', '~> 1.2014'
|
34
|
+
# tzinfo 0.x
|
35
|
+
# s.add_development_dependency 'tzinfo', '~> 0.3'
|
36
|
+
# end tzinfo
|
37
|
+
|
28
38
|
s.add_development_dependency 'activesupport', '~> 3.2'
|
29
39
|
s.add_development_dependency 'timecop', '~> 0.7.0'
|
30
40
|
s.add_development_dependency 'rspec', '~> 2.14'
|
data/lib/icalendar.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
|
+
require 'icalendar/logger'
|
2
|
+
|
1
3
|
module Icalendar
|
2
4
|
|
3
5
|
MAX_LINE_LENGTH = 75
|
4
6
|
|
7
|
+
def self.logger
|
8
|
+
@logger ||= Icalendar::Logger.new(STDERR)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger=(logger)
|
12
|
+
@logger = logger
|
13
|
+
end
|
14
|
+
|
5
15
|
def self.parse(source, single = false)
|
6
16
|
calendars = Parser.new(source).parse
|
7
17
|
single ? calendars.first : calendars
|
@@ -20,4 +30,4 @@ require 'icalendar/journal'
|
|
20
30
|
require 'icalendar/freebusy'
|
21
31
|
require 'icalendar/timezone'
|
22
32
|
require 'icalendar/calendar'
|
23
|
-
require 'icalendar/parser'
|
33
|
+
require 'icalendar/parser'
|
data/lib/icalendar/parser.rb
CHANGED
@@ -10,7 +10,9 @@ module Icalendar
|
|
10
10
|
elsif source.respond_to? :to_s
|
11
11
|
@source = StringIO.new source.to_s, 'r'
|
12
12
|
else
|
13
|
-
|
13
|
+
msg = 'Icalendar::Parser.new must be called with a String or IO object'
|
14
|
+
Icalendar.fatal msg
|
15
|
+
fail ArgumentError, msg
|
14
16
|
end
|
15
17
|
read_in_data
|
16
18
|
@strict = strict
|
@@ -49,13 +51,19 @@ module Icalendar
|
|
49
51
|
end
|
50
52
|
prop_name = %w(class method).include?(fields[:name]) ? "ip_#{fields[:name]}" : fields[:name]
|
51
53
|
begin
|
52
|
-
if component.class.multiple_properties.include? prop_name
|
53
|
-
|
54
|
+
method_name = if component.class.multiple_properties.include? prop_name
|
55
|
+
"append_#{prop_name}"
|
54
56
|
else
|
55
|
-
|
57
|
+
"#{prop_name}="
|
56
58
|
end
|
59
|
+
component.send method_name, prop_value
|
57
60
|
rescue NoMethodError => nme
|
58
|
-
|
61
|
+
if strict?
|
62
|
+
Icalendar.logger.error "No method \"#{method_name}\" for component #{component}"
|
63
|
+
raise nme
|
64
|
+
else
|
65
|
+
Icalendar.logger.warn "No method \"#{method_name}\" for component #{component}. Skipping."
|
66
|
+
end
|
59
67
|
end
|
60
68
|
end
|
61
69
|
|
@@ -71,6 +79,7 @@ module Icalendar
|
|
71
79
|
break
|
72
80
|
elsif fields[:name] == 'begin'
|
73
81
|
klass_name = fields[:value].gsub(/\AV/, '').downcase.capitalize
|
82
|
+
Icalendar.logger.debug "Adding component #{klass_name}"
|
74
83
|
if Icalendar.const_defined? klass_name
|
75
84
|
component.add_component parse_component(Icalendar.const_get(klass_name).new)
|
76
85
|
elsif Icalendar::Timezone.const_defined? klass_name
|
@@ -79,7 +88,6 @@ module Icalendar
|
|
79
88
|
component.add_component parse_component(Component.new klass_name.downcase, fields[:value])
|
80
89
|
end
|
81
90
|
else
|
82
|
-
# new property
|
83
91
|
parse_property component, fields
|
84
92
|
end
|
85
93
|
end
|
@@ -112,7 +120,7 @@ module Icalendar
|
|
112
120
|
LINE = "(?<name>#{NAME})(?<params>(?:;#{PARAM})*):(?<value>#{VALUE})"
|
113
121
|
|
114
122
|
def parse_fields(input)
|
115
|
-
parts = %r{#{LINE}}.match(input) or
|
123
|
+
parts = %r{#{LINE}}.match(input) or fail "Invalid iCalendar input line: #{input}"
|
116
124
|
params = {}
|
117
125
|
parts[:params].scan %r{#{PARAM}} do |match|
|
118
126
|
param_name = match[0].downcase
|
@@ -121,6 +129,7 @@ module Icalendar
|
|
121
129
|
params[param_name] << param_value.gsub(/\A"|"\z/, '') if param_value.size > 0
|
122
130
|
end
|
123
131
|
end
|
132
|
+
Icalendar.logger.debug "Found fields: #{parts.inspect} with params: #{params.inspect}"
|
124
133
|
{
|
125
134
|
name: parts[:name].downcase.gsub('-', '_'),
|
126
135
|
params: params,
|
data/lib/icalendar/tzinfo.rb
CHANGED
@@ -21,7 +21,7 @@
|
|
21
21
|
# # the mixins now generate all the timezone info for the date in question
|
22
22
|
# timezone = tz.ical_timezone(estart)
|
23
23
|
# cal.add(timezone)
|
24
|
-
#
|
24
|
+
#
|
25
25
|
# cal.event do
|
26
26
|
# dtstart estart
|
27
27
|
# dtend eend
|
@@ -40,26 +40,14 @@
|
|
40
40
|
|
41
41
|
|
42
42
|
require 'tzinfo'
|
43
|
+
begin
|
44
|
+
require 'tzinfo/data'
|
45
|
+
rescue LoadError
|
46
|
+
Icalendar.logger.info "Could not load tzinfo/data, hopefully tzinfo is accurate (ignore for tzinfo 0.x)"
|
47
|
+
end
|
43
48
|
|
44
|
-
module
|
45
|
-
|
46
|
-
def ical_timezone(date, dst = Timezone.default_dst)
|
47
|
-
period = period_for_local(date, dst)
|
48
|
-
timezone = Icalendar::Timezone.new
|
49
|
-
timezone.tzid = identifier
|
50
|
-
if period.start_transition.nil?
|
51
|
-
timezone.add_component period.single
|
52
|
-
elsif period.end_transition.nil?
|
53
|
-
timezone.add_component period.dst? ? period.daylight : period.standard
|
54
|
-
else
|
55
|
-
timezone.add_component period.daylight
|
56
|
-
timezone.add_component period.standard
|
57
|
-
end
|
58
|
-
timezone
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class TimezoneTransitionInfo
|
49
|
+
module Icalendar
|
50
|
+
module TimezoneTransition
|
63
51
|
def offset_from
|
64
52
|
previous_offset.ical_offset
|
65
53
|
end
|
@@ -68,7 +56,7 @@ module TZInfo
|
|
68
56
|
offset.ical_offset
|
69
57
|
end
|
70
58
|
|
71
|
-
def rrule
|
59
|
+
def rrule
|
72
60
|
start = local_start.to_datetime
|
73
61
|
# this is somewhat of a hack, but seems to work ok
|
74
62
|
[sprintf(
|
@@ -84,12 +72,52 @@ module TZInfo
|
|
84
72
|
end
|
85
73
|
end
|
86
74
|
|
87
|
-
|
75
|
+
module TimezoneOffset
|
88
76
|
def ical_offset
|
89
77
|
o = utc_total_offset
|
90
78
|
sprintf '%+-2.2d%2.2d', (o / 3600).to_i, ((o / 60) % 60).to_i
|
91
79
|
end
|
92
80
|
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
module TZInfo
|
85
|
+
class Timezone
|
86
|
+
def ical_timezone(date, dst = Timezone.default_dst)
|
87
|
+
period = period_for_local(date, dst)
|
88
|
+
timezone = Icalendar::Timezone.new
|
89
|
+
timezone.tzid = identifier
|
90
|
+
if period.start_transition.nil?
|
91
|
+
timezone.add_component period.single
|
92
|
+
elsif period.end_transition.nil?
|
93
|
+
timezone.add_component period.dst? ? period.daylight : period.standard
|
94
|
+
else
|
95
|
+
timezone.add_component period.daylight
|
96
|
+
timezone.add_component period.standard
|
97
|
+
end
|
98
|
+
timezone
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
if defined? TimezoneTransitionInfo
|
103
|
+
class TimezoneTransitionInfo
|
104
|
+
include Icalendar::TimezoneTransition
|
105
|
+
end
|
106
|
+
else
|
107
|
+
class TimezoneTransition
|
108
|
+
include Icalendar::TimezoneTransition
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
if defined? TimezoneOffsetInfo
|
113
|
+
class TimezoneOffsetInfo
|
114
|
+
include Icalendar::TimezoneOffset
|
115
|
+
end
|
116
|
+
else
|
117
|
+
class TimezoneOffset
|
118
|
+
include Icalendar::TimezoneOffset
|
119
|
+
end
|
120
|
+
end
|
93
121
|
|
94
122
|
class TimezonePeriod
|
95
123
|
def daylight
|
data/lib/icalendar/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
BEGIN:VCALENDAR
|
2
|
+
VERSION:2.0
|
3
|
+
PRODID:bsprodidfortestabc123
|
4
|
+
BEGIN:VEVENT
|
5
|
+
UID:bsuidfortestabc123
|
6
|
+
ORGANIZER:mailto:joebob@random.net
|
7
|
+
ATTACH:http://bush.sucks.org/impeach/him.rhtml
|
8
|
+
ATTACH:http://corporations-dominate.existence.net/why.rhtml
|
9
|
+
SUMMARY:This is a really long summary
|
10
|
+
to test the method of unfolding lines\,
|
11
|
+
so I'm just going to ma
|
12
|
+
ke it
|
13
|
+
a whol
|
14
|
+
e
|
15
|
+
bunch of lines.
|
16
|
+
CLASS:PRIVATE
|
17
|
+
PRIORITY:2
|
18
|
+
CUSTOMFIELD:Not properly noted as custom with X- prefix.
|
19
|
+
GEO:37.386013;-122.0829322
|
20
|
+
DTSTART;TZID=US-Mountain:20050120T170000
|
21
|
+
DTEND:20050120T184500
|
22
|
+
DTSTAMP:20050118T211523Z
|
23
|
+
NAME:SomeName
|
24
|
+
END:VEVENT
|
25
|
+
END:VCALENDAR
|
data/spec/roundtrip_spec.rb
CHANGED
@@ -37,4 +37,21 @@ describe Icalendar do
|
|
37
37
|
expect(subject.dtend.to_ical(subject.class.default_property_types['dtend'])).to match /^;VALUE=DATE:20061215$/
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
describe 'non-standard values' do
|
42
|
+
before(:all) { Icalendar.logger = Icalendar::Logger.new File::NULL }
|
43
|
+
after(:all) { Icalendar.logger = nil }
|
44
|
+
let(:source) { File.read File.join(File.dirname(__FILE__), 'fixtures', 'nonstandard.ics') }
|
45
|
+
subject { Icalendar::Parser.new(source, strict) }
|
46
|
+
|
47
|
+
context 'strict parser' do
|
48
|
+
let(:strict) { true }
|
49
|
+
specify { expect { subject.parse }.to raise_error }
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'lenient parser' do
|
53
|
+
let(:strict) { false }
|
54
|
+
specify { expect { subject.parse}.to_not raise_error }
|
55
|
+
end
|
56
|
+
end
|
40
57
|
end
|
data/spec/tzinfo_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icalendar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Ahearn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -44,14 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '1.1'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '1.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tzinfo-data
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.2014'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.2014'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: activesupport
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +150,7 @@ files:
|
|
136
150
|
- lib/icalendar/has_components.rb
|
137
151
|
- lib/icalendar/has_properties.rb
|
138
152
|
- lib/icalendar/journal.rb
|
153
|
+
- lib/icalendar/logger.rb
|
139
154
|
- lib/icalendar/parser.rb
|
140
155
|
- lib/icalendar/timezone.rb
|
141
156
|
- lib/icalendar/todo.rb
|
@@ -162,6 +177,7 @@ files:
|
|
162
177
|
- spec/calendar_spec.rb
|
163
178
|
- spec/event_spec.rb
|
164
179
|
- spec/fixtures/nondefault_values.ics
|
180
|
+
- spec/fixtures/nonstandard.ics
|
165
181
|
- spec/fixtures/single_event.ics
|
166
182
|
- spec/fixtures/timezone.ics
|
167
183
|
- spec/freebusy_spec.rb
|
@@ -192,12 +208,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
208
|
requirements:
|
193
209
|
- - '>='
|
194
210
|
- !ruby/object:Gem::Version
|
195
|
-
version:
|
211
|
+
version: 1.9.3
|
196
212
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
213
|
requirements:
|
198
|
-
- - '
|
214
|
+
- - '>='
|
199
215
|
- !ruby/object:Gem::Version
|
200
|
-
version:
|
216
|
+
version: '0'
|
201
217
|
requirements: []
|
202
218
|
rubyforge_project:
|
203
219
|
rubygems_version: 2.0.14
|
@@ -209,6 +225,7 @@ test_files:
|
|
209
225
|
- spec/calendar_spec.rb
|
210
226
|
- spec/event_spec.rb
|
211
227
|
- spec/fixtures/nondefault_values.ics
|
228
|
+
- spec/fixtures/nonstandard.ics
|
212
229
|
- spec/fixtures/single_event.ics
|
213
230
|
- spec/fixtures/timezone.ics
|
214
231
|
- spec/freebusy_spec.rb
|