icalendar 2.5.3 → 2.6.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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +0 -4
- data/History.txt +6 -0
- data/icalendar.gemspec +1 -1
- data/lib/icalendar.rb +1 -0
- data/lib/icalendar/has_components.rb +2 -2
- data/lib/icalendar/has_properties.rb +4 -4
- data/lib/icalendar/marshable.rb +34 -0
- data/lib/icalendar/timezone.rb +33 -18
- data/lib/icalendar/values/utc_offset.rb +1 -2
- data/lib/icalendar/version.rb +1 -1
- data/spec/calendar_spec.rb +6 -0
- data/spec/event_spec.rb +7 -0
- data/spec/timezone_spec.rb +48 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 165b0d4192335c7fb36354195666ea4d386d63029190d7c1248ab3d4fe1554ec
|
4
|
+
data.tar.gz: 3781a361f70f099aff7e891e7f3bc26eaaac059c615a40d377634d41d4905d3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 682932f688906567e95fc58b4952b05664e9eeece75708bd83c1ebc42362e927a252f77a8124bf028500359e23aa1d7b071b9af5ccf1032d92074c29cecd6f3f
|
7
|
+
data.tar.gz: 38a5153c80c3b170c2d973104f565d3e0ff5a3c74b8573870331cc842e23e2918de712b6a0046cecb758a1aa3450c72f4aedaa2f22bb302a7343332f2c0a017a
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 2.6.0 2019-11-26
|
2
|
+
* Improve performance for calculating timezone offsets - Justin Howard
|
3
|
+
* Make it possible to de/serialize with Marshal - Pawel Niewiadomski
|
4
|
+
* Avoid FrozenError when running with frozen_string_literal
|
5
|
+
* Update minimum Ruby version to supported versions
|
6
|
+
|
1
7
|
=== 2.5.3 2019-03-04
|
2
8
|
* Improve parsing performance - nehresma
|
3
9
|
* Support tzinfo 2.0 - Misty De Meo
|
data/icalendar.gemspec
CHANGED
@@ -24,7 +24,7 @@ ActiveSupport is required for TimeWithZone support, but not required for general
|
|
24
24
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename f }
|
25
25
|
s.require_paths = ['lib']
|
26
26
|
|
27
|
-
s.required_ruby_version = '>= 2.
|
27
|
+
s.required_ruby_version = '>= 2.4.0'
|
28
28
|
|
29
29
|
s.add_dependency 'ice_cube', '~> 0.16'
|
30
30
|
|
data/lib/icalendar.rb
CHANGED
@@ -10,7 +10,7 @@ module Icalendar
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
|
-
@custom_components = Hash.new
|
13
|
+
@custom_components = Hash.new
|
14
14
|
super
|
15
15
|
end
|
16
16
|
|
@@ -26,7 +26,7 @@ module Icalendar
|
|
26
26
|
if method_name =~ /^add_(x_\w+)$/
|
27
27
|
component_name = $1
|
28
28
|
custom = args.first || Component.new(component_name, component_name.upcase)
|
29
|
-
custom_components[component_name] << custom
|
29
|
+
(custom_components[component_name] ||= []) << custom
|
30
30
|
yield custom if block_given?
|
31
31
|
custom
|
32
32
|
else
|
@@ -10,7 +10,7 @@ module Icalendar
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
|
-
@custom_properties = Hash.new
|
13
|
+
@custom_properties = Hash.new
|
14
14
|
super
|
15
15
|
end
|
16
16
|
|
@@ -39,7 +39,7 @@ module Icalendar
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def custom_property(property_name)
|
42
|
-
custom_properties[property_name.downcase]
|
42
|
+
custom_properties[property_name.downcase] || []
|
43
43
|
end
|
44
44
|
|
45
45
|
def append_custom_property(property_name, value)
|
@@ -49,9 +49,9 @@ module Icalendar
|
|
49
49
|
elsif self.class.multiple_properties.include? property_name
|
50
50
|
send "append_#{property_name}", value
|
51
51
|
elsif value.is_a? Icalendar::Value
|
52
|
-
custom_properties[property_name] << value
|
52
|
+
(custom_properties[property_name] ||= []) << value
|
53
53
|
else
|
54
|
-
custom_properties[property_name] << Icalendar::Values::Text.new(value)
|
54
|
+
(custom_properties[property_name] ||= []) << Icalendar::Values::Text.new(value)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Icalendar
|
2
|
+
module Marshable
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
def marshal_dump
|
8
|
+
instance_variables
|
9
|
+
.reject { |ivar| self.class.transient_variables.include?(ivar) }
|
10
|
+
.each_with_object({}) do |ivar, serialized|
|
11
|
+
|
12
|
+
serialized[ivar] = instance_variable_get(ivar)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def marshal_load(serialized)
|
17
|
+
serialized.each do |ivar, value|
|
18
|
+
unless self.class.transient_variables.include?(ivar)
|
19
|
+
instance_variable_set(ivar, value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def transient_variables
|
26
|
+
@transient_variables ||= [:@transient_variables]
|
27
|
+
end
|
28
|
+
|
29
|
+
def transient_variable(name)
|
30
|
+
transient_variables.push(name.to_sym)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/icalendar/timezone.rb
CHANGED
@@ -14,10 +14,40 @@ module Icalendar
|
|
14
14
|
optional_property :comment
|
15
15
|
optional_property :rdate, Icalendar::Values::DateTime
|
16
16
|
optional_property :tzname
|
17
|
+
|
18
|
+
transient_variable :@cached_occurrences
|
19
|
+
transient_variable :@occurrences
|
17
20
|
end
|
18
21
|
end
|
22
|
+
|
23
|
+
def occurrences
|
24
|
+
@occurrences ||= IceCube::Schedule.new(dtstart.to_time) do |s|
|
25
|
+
rrule.each do |rule|
|
26
|
+
s.add_recurrence_rule IceCube::Rule.from_ical(rule.value_ical)
|
27
|
+
end
|
28
|
+
rdate.each do |date|
|
29
|
+
s.add_recurrence_time date.to_time
|
30
|
+
end
|
31
|
+
end.all_occurrences_enumerator
|
32
|
+
end
|
33
|
+
|
34
|
+
def previous_occurrence(from)
|
35
|
+
from = IceCube::TimeUtil.match_zone(from, dtstart.to_time)
|
36
|
+
|
37
|
+
@cached_occurrences ||= []
|
38
|
+
while @cached_occurrences.empty? || @cached_occurrences.last <= from
|
39
|
+
begin
|
40
|
+
@cached_occurrences << occurrences.next
|
41
|
+
rescue StopIteration
|
42
|
+
break
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@cached_occurrences.reverse_each.find { |occurrence| occurrence < from }
|
47
|
+
end
|
19
48
|
end
|
20
49
|
class Daylight < Component
|
50
|
+
include Marshable
|
21
51
|
include TzProperties
|
22
52
|
|
23
53
|
def initialize
|
@@ -25,6 +55,7 @@ module Icalendar
|
|
25
55
|
end
|
26
56
|
end
|
27
57
|
class Standard < Component
|
58
|
+
include Marshable
|
28
59
|
include TzProperties
|
29
60
|
|
30
61
|
def initialize
|
@@ -75,30 +106,14 @@ module Icalendar
|
|
75
106
|
|
76
107
|
def standard_for(local)
|
77
108
|
possible = standards.map do |std|
|
78
|
-
|
79
|
-
std.rrule.each do |rule|
|
80
|
-
s.add_recurrence_rule IceCube::Rule.from_ical(rule.value_ical)
|
81
|
-
end
|
82
|
-
std.rdate.each do |date|
|
83
|
-
s.add_recurrence_time date.to_time
|
84
|
-
end
|
85
|
-
end
|
86
|
-
[schedule.previous_occurrence(local.to_time), std]
|
109
|
+
[std.previous_occurrence(local.to_time), std]
|
87
110
|
end
|
88
111
|
possible.sort_by(&:first).last
|
89
112
|
end
|
90
113
|
|
91
114
|
def daylight_for(local)
|
92
115
|
possible = daylights.map do |day|
|
93
|
-
|
94
|
-
day.rrule.each do |rule|
|
95
|
-
s.add_recurrence_rule IceCube::Rule.from_ical(rule.value_ical)
|
96
|
-
end
|
97
|
-
day.rdate.each do |date|
|
98
|
-
s.add_recurrence_time date.to_time
|
99
|
-
end
|
100
|
-
end
|
101
|
-
[schedule.previous_occurrence(local.to_time), day]
|
116
|
+
[day.previous_occurrence(local.to_time), day]
|
102
117
|
end
|
103
118
|
possible.sort_by(&:first).last
|
104
119
|
end
|
@@ -37,8 +37,7 @@ module Icalendar
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def parse_fields(value)
|
40
|
-
value.gsub
|
41
|
-
md = /\A(?<behind>[+-])(?<hours>\d{2})(?<minutes>\d{2})(?<seconds>\d{2})?\z/.match value
|
40
|
+
md = /\A(?<behind>[+-])(?<hours>\d{2})(?<minutes>\d{2})(?<seconds>\d{2})?\z/.match value.gsub(/\s+/, '')
|
42
41
|
{
|
43
42
|
behind: (md[:behind] == '-'),
|
44
43
|
hours: md[:hours].to_i,
|
data/lib/icalendar/version.rb
CHANGED
data/spec/calendar_spec.rb
CHANGED
data/spec/event_spec.rb
CHANGED
@@ -113,6 +113,13 @@ describe Icalendar::Event do
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
describe "#custom_property" do
|
117
|
+
it "returns a default for missing properties" do
|
118
|
+
expect(subject.x_doesnt_exist).to eq([])
|
119
|
+
expect(subject.custom_property "x_doesnt_exist").to eq([])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
116
123
|
describe '.parse' do
|
117
124
|
let(:source) { File.read File.join(File.dirname(__FILE__), 'fixtures', fn) }
|
118
125
|
let(:fn) { 'event.ics' }
|
data/spec/timezone_spec.rb
CHANGED
@@ -28,4 +28,52 @@ describe Icalendar::Timezone do
|
|
28
28
|
it { should_not be_valid }
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
context 'marshalling' do
|
33
|
+
context 'with standard/daylight components' do
|
34
|
+
before do
|
35
|
+
subject.standard do |standard|
|
36
|
+
standard.rrule = Icalendar::Values::Recur.new("FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10")
|
37
|
+
standard.dtstart = Icalendar::Values::DateTime.new("16010101T030000")
|
38
|
+
standard.tzoffsetfrom = Icalendar::Values::UtcOffset.new("+0200")
|
39
|
+
standard.tzoffsetto = Icalendar::Values::UtcOffset.new("+0100")
|
40
|
+
end
|
41
|
+
|
42
|
+
subject.daylight do |daylight|
|
43
|
+
daylight.rrule = Icalendar::Values::Recur.new("FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3")
|
44
|
+
daylight.dtstart = Icalendar::Values::DateTime.new("16010101T020000")
|
45
|
+
daylight.tzoffsetfrom = Icalendar::Values::UtcOffset.new("+0100")
|
46
|
+
daylight.tzoffsetto = Icalendar::Values::UtcOffset.new("+0200")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can be de/serialized' do
|
51
|
+
first_standard = subject.standards.first
|
52
|
+
first_daylight = subject.daylights.first
|
53
|
+
|
54
|
+
expect(first_standard.valid?).to be_truthy
|
55
|
+
expect(first_daylight.valid?).to be_truthy
|
56
|
+
|
57
|
+
# calling previous_occurrence intializes @cached_occurrences with a time that's not handled by ruby marshaller
|
58
|
+
first_occurence_for = Time.new(1601, 10, 31)
|
59
|
+
|
60
|
+
standard_previous_occurrence = first_standard.previous_occurrence(first_occurence_for)
|
61
|
+
expect(standard_previous_occurrence).not_to be_nil
|
62
|
+
|
63
|
+
daylight_previous_occurrence = first_daylight.previous_occurrence(first_occurence_for)
|
64
|
+
expect(daylight_previous_occurrence).not_to be_nil
|
65
|
+
|
66
|
+
deserialized = nil
|
67
|
+
|
68
|
+
expect { deserialized = Marshal.load(Marshal.dump(subject)) }.not_to raise_exception
|
69
|
+
|
70
|
+
expect(deserialized.standards.first.previous_occurrence(first_occurence_for)).to eq(standard_previous_occurrence)
|
71
|
+
expect(deserialized.daylights.first.previous_occurrence(first_occurence_for)).to eq(daylight_previous_occurrence)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'can be de/serialized' do
|
76
|
+
expect { Marshal.load(Marshal.dump(subject)) }.not_to raise_exception
|
77
|
+
end
|
78
|
+
end
|
31
79
|
end
|
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.
|
4
|
+
version: 2.6.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: 2019-
|
11
|
+
date: 2019-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ice_cube
|
@@ -180,6 +180,7 @@ files:
|
|
180
180
|
- lib/icalendar/has_properties.rb
|
181
181
|
- lib/icalendar/journal.rb
|
182
182
|
- lib/icalendar/logger.rb
|
183
|
+
- lib/icalendar/marshable.rb
|
183
184
|
- lib/icalendar/parser.rb
|
184
185
|
- lib/icalendar/timezone.rb
|
185
186
|
- lib/icalendar/timezone_store.rb
|
@@ -253,14 +254,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
253
254
|
requirements:
|
254
255
|
- - ">="
|
255
256
|
- !ruby/object:Gem::Version
|
256
|
-
version: 2.
|
257
|
+
version: 2.4.0
|
257
258
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
258
259
|
requirements:
|
259
260
|
- - ">="
|
260
261
|
- !ruby/object:Gem::Version
|
261
262
|
version: '0'
|
262
263
|
requirements: []
|
263
|
-
rubygems_version: 3.0.
|
264
|
+
rubygems_version: 3.0.3
|
264
265
|
signing_key:
|
265
266
|
specification_version: 4
|
266
267
|
summary: A ruby implementation of the iCalendar specification (RFC-5545).
|