icalendar 2.9.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f083428b61c781e197d459b5ba375139056f75e95b1b99e596169106a57ed20
4
- data.tar.gz: acb3cdb07b0dc052664fc67619fa6301951daf70ac83a0430a839a0bdd3a5923
3
+ metadata.gz: 7b9f7e30ef6614ad4175a9d282d1b03b57f140f98a2962b4e0268aa015f8f942
4
+ data.tar.gz: 7ebabfddd0f3d8e8e05e1ef82d2389007c1419c727c5404d2ec2c1c09565a8bb
5
5
  SHA512:
6
- metadata.gz: 595032415b8465be6f662f136a56dd6f4dd8af27e888c7a7b27ad1c688b3963466e34a949daa0111a65ea89037b33ea01d8f2ea24991f5d9a3869647521b6c7c
7
- data.tar.gz: ac464077d0c421d27b39270f1d12af23b59383e3e8351b68ec41a8385cc26670ca31b2f8dba72212e8db0996ea4a9e7c4a1b7b6a9b1b34d632169fae5a715725
6
+ metadata.gz: 8d3221e4e5bd2120014ae11fe80a8e0a3b36af37b10aadd18f3bc6022e296efa47ea27d09572900bb6d6419fff64054caa6709e6b14e5182d32a188d0130b7f0
7
+ data.tar.gz: 5d7d996d53a12543de0830fdb8214e2ae39df4c19c649e81cd95ceb8d30d61f1f178b7a9a4f4e37adb591609eeac7e89d930cf5ffc24951c9cbfcb0b815c2a03
@@ -17,13 +17,12 @@ jobs:
17
17
  strategy:
18
18
  matrix:
19
19
  ruby:
20
- - 2.7.6
21
- - 3.0.4
22
- - 3.1.2
20
+ - 3.0.6
21
+ - 3.1.4
23
22
  - 3.2.2
24
23
 
25
24
  steps:
26
- - uses: actions/checkout@v2
25
+ - uses: actions/checkout@v4
27
26
  - name: Set up Ruby
28
27
  uses: ruby/setup-ruby@v1
29
28
  with:
data/History.txt CHANGED
@@ -1,5 +1,13 @@
1
1
  === Unreleased
2
2
 
3
+ === 2.10.1 2023-12-01
4
+ * Parsing now handles VTIMEZONE blocks defined after their TZID is used in events and other components
5
+
6
+ === 2.10.0 2023-11-01
7
+ * Add changelog metadata to gemspec - Juri Hahn
8
+ * Attempt to rescue timezone info when given a nonstandard tzid with no VTIMEZONE
9
+ * Move Values classes that shouldn't be directly used into Helpers module
10
+
3
11
  === 2.9.0 2023-08-11
4
12
  * Always include the VALUE of Event URLs for improved compatibility - Sean Kelley
5
13
  * Improved parse performance - Thomas Cannon
data/icalendar.gemspec CHANGED
@@ -20,6 +20,10 @@ variety of calendaring applications.
20
20
  ActiveSupport is required for TimeWithZone support, but not required for general use.
21
21
  EOM
22
22
 
23
+ s.metadata = {
24
+ 'changelog_uri' => 'https://github.com/icalendar/icalendar/blob/main/History.txt'
25
+ }
26
+
23
27
  s.files = `git ls-files`.split "\n"
24
28
  s.test_files = `git ls-files -- {test,spec,features}/*`.split "\n"
25
29
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename f }
@@ -34,13 +38,13 @@ ActiveSupport is required for TimeWithZone support, but not required for general
34
38
 
35
39
  # test with all groups of tzinfo dependencies
36
40
  # tzinfo 2.x
37
- # s.add_development_dependency 'tzinfo', '~> 2.0'
38
- # s.add_development_dependency 'tzinfo-data', '~> 1.2020'
39
- # tzinfo 1.x
40
- s.add_development_dependency 'activesupport', '~> 6.0'
41
- s.add_development_dependency 'i18n', '~> 1.8'
42
- s.add_development_dependency 'tzinfo', '~> 1.2'
41
+ s.add_development_dependency 'activesupport', '~> 7.1'
42
+ s.add_development_dependency 'tzinfo', '~> 2.0'
43
43
  s.add_development_dependency 'tzinfo-data', '~> 1.2020'
44
+ # tzinfo 1.x
45
+ # s.add_development_dependency 'activesupport', '~> 6.0'
46
+ # s.add_development_dependency 'tzinfo', '~> 1.2'
47
+ # s.add_development_dependency 'tzinfo-data', '~> 1.2020'
44
48
  # tzinfo 0.x
45
49
  # s.add_development_dependency 'tzinfo', '~> 0.3'
46
50
  # end tzinfo
@@ -48,4 +52,5 @@ ActiveSupport is required for TimeWithZone support, but not required for general
48
52
  s.add_development_dependency 'timecop', '~> 0.9'
49
53
  s.add_development_dependency 'rspec', '~> 3.8'
50
54
  s.add_development_dependency 'simplecov', '~> 0.16'
55
+ s.add_development_dependency 'byebug'
51
56
  end
@@ -148,7 +148,7 @@ module Icalendar
148
148
 
149
149
  define_method "#{prop}=" do |value|
150
150
  mapped = map_property_value value, klass, true, new_property
151
- if mapped.is_a? Icalendar::Values::Array
151
+ if mapped.is_a? Icalendar::Values::Helpers::Array
152
152
  instance_variable_set property_var, mapped.to_a.compact
153
153
  else
154
154
  instance_variable_set property_var, [mapped].compact
@@ -179,7 +179,7 @@ module Icalendar
179
179
  if value.nil? || value.is_a?(Icalendar::Value)
180
180
  value
181
181
  elsif value.is_a? ::Array
182
- Icalendar::Values::Array.new value, klass, params, {delimiter: (multi_valued ? ',' : ';')}
182
+ Icalendar::Values::Helpers::Array.new value, klass, params, {delimiter: (multi_valued ? ',' : ';')}
183
183
  else
184
184
  klass.new value, params
185
185
  end
@@ -84,7 +84,7 @@ module Icalendar
84
84
  klass = get_wrapper_class component, fields
85
85
  if wrap_in_array? klass, fields[:value], multi_property
86
86
  delimiter = fields[:value].match(WRAP_PROPERTY_VALUE_DELIMETER_REGEX)[1]
87
- Icalendar::Values::Array.new fields[:value].split(WRAP_PROPERTY_VALUE_SPLIT_REGEX),
87
+ Icalendar::Values::Helpers::Array.new fields[:value].split(WRAP_PROPERTY_VALUE_SPLIT_REGEX),
88
88
  klass,
89
89
  fields[:params],
90
90
  delimiter: delimiter
@@ -211,7 +211,7 @@ module Icalendar
211
211
  param_value = param_value.gsub(PVALUE_GSUB_REGEX, '')
212
212
  params[param_name] << param_value
213
213
  if param_name == 'tzid'
214
- params['x-tz-info'] = timezone_store.retrieve param_value
214
+ params['x-tz-store'] = timezone_store
215
215
  end
216
216
  end
217
217
  end
@@ -108,15 +108,17 @@ module Icalendar
108
108
 
109
109
  def standard_for(local)
110
110
  possible = standards.map do |std|
111
- [std.previous_occurrence(local.to_time), std]
112
- end
111
+ prev = std.previous_occurrence(local.to_time)
112
+ [prev, std] unless prev.nil?
113
+ end.compact
113
114
  possible.sort_by(&:first).last
114
115
  end
115
116
 
116
117
  def daylight_for(local)
117
118
  possible = daylights.map do |day|
118
- [day.previous_occurrence(local.to_time), day]
119
- end
119
+ prev = day.previous_occurrence(local.to_time)
120
+ [prev, day] unless prev.nil?
121
+ end.compact
120
122
  possible.sort_by(&:first).last
121
123
  end
122
124
  end
@@ -72,7 +72,7 @@ module Icalendar
72
72
  end
73
73
 
74
74
  # helpers; not actual iCalendar value type
75
- require_relative 'values/array'
75
+ require_relative 'values/helpers/array'
76
76
  require_relative 'values/date_or_date_time'
77
77
 
78
78
  # iCalendar value types
@@ -10,7 +10,7 @@ module Icalendar
10
10
 
11
11
  def initialize(value, params = {})
12
12
  params.delete 'tzid'
13
- params.delete 'x-tz-info'
13
+ params.delete 'x-tz-store'
14
14
  if value.is_a? String
15
15
  begin
16
16
  parsed_date = ::Date.strptime(value, FORMAT)
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'date'
4
- require_relative 'time_with_zone'
4
+ require_relative 'helpers/time_with_zone'
5
5
 
6
6
  module Icalendar
7
7
  module Values
8
8
 
9
9
  class DateTime < Value
10
- include TimeWithZone
10
+ include Helpers::TimeWithZone
11
11
 
12
12
  FORMAT = '%Y%m%dT%H%M%S'
13
13
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ module Values
5
+ module Helpers
6
+ class ActiveSupportTimeWithZoneAdapter < ActiveSupport::TimeWithZone
7
+ # ActiveSupport::TimeWithZone implements a #to_a method that will cause
8
+ # unexpected behavior in components with multi_property DateTime
9
+ # properties when the setters for those properties are invoked with an
10
+ # Icalendar::Values::DateTime that is delegating for an
11
+ # ActiveSupport::TimeWithZone. To avoid this behavior, undefine #to_a.
12
+ undef_method :to_a
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ module Values
5
+ module Helpers
6
+
7
+ class Array < Value
8
+
9
+ attr_reader :value_delimiter
10
+
11
+ def initialize(value, klass, params = {}, options = {})
12
+ @value_delimiter = options[:delimiter] || ','
13
+ mapped = if value.is_a? ::Array
14
+ value.map do |v|
15
+ if v.is_a? Icalendar::Values::Helpers::Array
16
+ Icalendar::Values::Helpers::Array.new v.value, klass, v.ical_params, delimiter: v.value_delimiter
17
+ elsif v.is_a? ::Array
18
+ Icalendar::Values::Helpers::Array.new v, klass, params, delimiter: value_delimiter
19
+ elsif v.is_a? Icalendar::Value
20
+ v
21
+ else
22
+ klass.new v, params
23
+ end
24
+ end
25
+ else
26
+ [klass.new(value, params)]
27
+ end
28
+ super mapped
29
+ end
30
+
31
+ def params_ical
32
+ value.each do |v|
33
+ ical_params.merge! v.ical_params
34
+ end
35
+ super
36
+ end
37
+
38
+ def value_ical
39
+ value.map do |v|
40
+ v.value_ical
41
+ end.join value_delimiter
42
+ end
43
+
44
+ def valid?
45
+ klass = value.first.class
46
+ !value.all? { |v| v.class == klass }
47
+ end
48
+
49
+ def value_type
50
+ value.first.value_type
51
+ end
52
+
53
+ private
54
+
55
+ def needs_value_type?(default_type)
56
+ value.first.class != default_type
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'active_support/time'
5
+
6
+ if defined?(ActiveSupport::TimeWithZone)
7
+ require_relative 'active_support_time_with_zone_adapter'
8
+ end
9
+ rescue NameError
10
+ # ActiveSupport v7+ needs the base require to be run first before loading
11
+ # specific parts of it.
12
+ # https://guides.rubyonrails.org/active_support_core_extensions.html#stand-alone-active-support
13
+ require 'active_support'
14
+ retry
15
+ rescue LoadError
16
+ # tis ok, just a bit less fancy
17
+ end
18
+
19
+ module Icalendar
20
+ module Values
21
+ module Helpers
22
+ module TimeWithZone
23
+ attr_reader :tz_utc, :timezone_store
24
+
25
+ def initialize(value, params = {})
26
+ params = Icalendar::DowncasedHash(params)
27
+ @tz_utc = params['tzid'] == 'UTC'
28
+ @timezone_store = params.delete 'x-tz-store'
29
+ super (offset_value(value, params) || value), params
30
+ end
31
+
32
+ def __getobj__
33
+ orig_value = super
34
+ if set_offset?
35
+ orig_value
36
+ else
37
+ offset = offset_value(orig_value, ical_params)
38
+ __setobj__(offset) unless offset.nil?
39
+ offset || orig_value
40
+ end
41
+ end
42
+
43
+ def params_ical
44
+ ical_params.delete 'tzid' if tz_utc
45
+ super
46
+ end
47
+
48
+ private
49
+
50
+ def offset_value(value, params)
51
+ @offset_value = unless params.nil? || params['tzid'].nil?
52
+ tzid = params['tzid'].is_a?(::Array) ? params['tzid'].first : params['tzid']
53
+ support_classes_defined = defined?(ActiveSupport::TimeZone) && defined?(ActiveSupportTimeWithZoneAdapter)
54
+ if support_classes_defined && (tz = ActiveSupport::TimeZone[tzid])
55
+ Icalendar.logger.debug("Plan a - parsing #{value}/#{tzid} as ActiveSupport::TimeWithZone")
56
+ # plan a - use ActiveSupport::TimeWithZone
57
+ ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
58
+ elsif !timezone_store.nil? && !(x_tz_info = timezone_store.retrieve(tzid)).nil?
59
+ # plan b - use definition from provided `VTIMEZONE`
60
+ offset = x_tz_info.offset_for_local(value).to_s
61
+ Icalendar.logger.debug("Plan b - parsing #{value} with offset: #{offset}")
62
+ if value.respond_to?(:change)
63
+ value.change offset: offset
64
+ else
65
+ ::Time.new value.year, value.month, value.day, value.hour, value.min, value.sec, offset
66
+ end
67
+ elsif support_classes_defined && (tz = ActiveSupport::TimeZone[tzid.split.first])
68
+ # plan c - try to find an ActiveSupport::TimeWithZone based on the first word of the tzid
69
+ Icalendar.logger.debug("Plan c - parsing #{value}/#{tz.tzinfo.name} as ActiveSupport::TimeWithZone")
70
+ params['tzid'] = [tz.tzinfo.name]
71
+ ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
72
+ else
73
+ # plan d - just ignore the tzid
74
+ Icalendar.logger.info("Ignoring timezone #{tzid} for time #{value}")
75
+ nil
76
+ end
77
+ end
78
+ end
79
+
80
+ def set_offset?
81
+ !!@offset_value
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'date'
4
- require_relative 'time_with_zone'
4
+ require_relative 'helpers/time_with_zone'
5
5
 
6
6
  module Icalendar
7
7
  module Values
8
8
 
9
9
  class Time < Value
10
- include TimeWithZone
10
+ include Helpers::TimeWithZone
11
11
 
12
12
  FORMAT = '%H%M%S'
13
13
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Icalendar
4
4
 
5
- VERSION = '2.9.0'
5
+ VERSION = '2.10.1'
6
6
 
7
7
  end
@@ -0,0 +1,143 @@
1
+ BEGIN:VCALENDAR
2
+ VERSION:2.0
3
+ X-WR-CALNAME:My Calendar
4
+ X-APPLE-CALENDAR-COLOR:#44A703
5
+ BEGIN:VEVENT
6
+ CREATED:20231026T211915Z
7
+ DTEND;TZID=NONSTANDARDTZ:20231025T180000
8
+ DTSTAMP:20231026T211916Z
9
+ DTSTART;TZID=NONSTANDARDTZ:20231025T163000
10
+ LAST-MODIFIED:20231026T211915Z
11
+ LOCATION:Somewhere
12
+ SEQUENCE:0
13
+ SUMMARY:Summary summary summary
14
+ UID:some-unique-uid
15
+ END:VEVENT
16
+ BEGIN:VTIMEZONE
17
+ TZID:NONSTANDARDTZ
18
+ X-LIC-LOCATION:NONSTANDARDTZ
19
+ BEGIN:STANDARD
20
+ DTSTART:18831118T120702
21
+ RDATE:18831118T120702
22
+ TZNAME:PST
23
+ TZOFFSETFROM:-075258
24
+ TZOFFSETTO:-0800
25
+ END:STANDARD
26
+ BEGIN:DAYLIGHT
27
+ DTSTART:19180331T020000
28
+ RRULE:FREQ=YEARLY;UNTIL=19190330T100000Z;BYMONTH=3;BYDAY=-1SU
29
+ TZNAME:PDT
30
+ TZOFFSETFROM:-0800
31
+ TZOFFSETTO:-0700
32
+ END:DAYLIGHT
33
+ BEGIN:STANDARD
34
+ DTSTART:19181027T020000
35
+ RRULE:FREQ=YEARLY;UNTIL=19191026T090000Z;BYMONTH=10;BYDAY=-1SU
36
+ TZNAME:PST
37
+ TZOFFSETFROM:-0700
38
+ TZOFFSETTO:-0800
39
+ END:STANDARD
40
+ BEGIN:DAYLIGHT
41
+ DTSTART:19420209T020000
42
+ RDATE:19420209T020000
43
+ TZNAME:PWT
44
+ TZOFFSETFROM:-0800
45
+ TZOFFSETTO:-0700
46
+ END:DAYLIGHT
47
+ BEGIN:DAYLIGHT
48
+ DTSTART:19450814T160000
49
+ RDATE:19450814T160000
50
+ TZNAME:PPT
51
+ TZOFFSETFROM:-0700
52
+ TZOFFSETTO:-0700
53
+ END:DAYLIGHT
54
+ BEGIN:STANDARD
55
+ DTSTART:19450930T020000
56
+ RDATE:19450930T020000
57
+ RDATE:19490101T020000
58
+ TZNAME:PST
59
+ TZOFFSETFROM:-0700
60
+ TZOFFSETTO:-0800
61
+ END:STANDARD
62
+ BEGIN:STANDARD
63
+ DTSTART:19460101T000000
64
+ RDATE:19460101T000000
65
+ RDATE:19670101T000000
66
+ TZNAME:PST
67
+ TZOFFSETFROM:-0800
68
+ TZOFFSETTO:-0800
69
+ END:STANDARD
70
+ BEGIN:DAYLIGHT
71
+ DTSTART:19480314T020100
72
+ RDATE:19480314T020100
73
+ RDATE:19740106T020000
74
+ RDATE:19750223T020000
75
+ TZNAME:PDT
76
+ TZOFFSETFROM:-0800
77
+ TZOFFSETTO:-0700
78
+ END:DAYLIGHT
79
+ BEGIN:DAYLIGHT
80
+ DTSTART:19500430T010000
81
+ RRULE:FREQ=YEARLY;UNTIL=19660424T090000Z;BYMONTH=4;BYDAY=-1SU
82
+ TZNAME:PDT
83
+ TZOFFSETFROM:-0800
84
+ TZOFFSETTO:-0700
85
+ END:DAYLIGHT
86
+ BEGIN:STANDARD
87
+ DTSTART:19500924T020000
88
+ RRULE:FREQ=YEARLY;UNTIL=19610924T090000Z;BYMONTH=9;BYDAY=-1SU
89
+ TZNAME:PST
90
+ TZOFFSETFROM:-0700
91
+ TZOFFSETTO:-0800
92
+ END:STANDARD
93
+ BEGIN:STANDARD
94
+ DTSTART:19621028T020000
95
+ RRULE:FREQ=YEARLY;UNTIL=19661030T090000Z;BYMONTH=10;BYDAY=-1SU
96
+ TZNAME:PST
97
+ TZOFFSETFROM:-0700
98
+ TZOFFSETTO:-0800
99
+ END:STANDARD
100
+ BEGIN:DAYLIGHT
101
+ DTSTART:19670430T020000
102
+ RRULE:FREQ=YEARLY;UNTIL=19730429T100000Z;BYMONTH=4;BYDAY=-1SU
103
+ TZNAME:PDT
104
+ TZOFFSETFROM:-0800
105
+ TZOFFSETTO:-0700
106
+ END:DAYLIGHT
107
+ BEGIN:STANDARD
108
+ DTSTART:19671029T020000
109
+ RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYMONTH=10;BYDAY=-1SU
110
+ TZNAME:PST
111
+ TZOFFSETFROM:-0700
112
+ TZOFFSETTO:-0800
113
+ END:STANDARD
114
+ BEGIN:DAYLIGHT
115
+ DTSTART:19760425T020000
116
+ RRULE:FREQ=YEARLY;UNTIL=19860427T100000Z;BYMONTH=4;BYDAY=-1SU
117
+ TZNAME:PDT
118
+ TZOFFSETFROM:-0800
119
+ TZOFFSETTO:-0700
120
+ END:DAYLIGHT
121
+ BEGIN:DAYLIGHT
122
+ DTSTART:19870405T020000
123
+ RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYMONTH=4;BYDAY=1SU
124
+ TZNAME:PDT
125
+ TZOFFSETFROM:-0800
126
+ TZOFFSETTO:-0700
127
+ END:DAYLIGHT
128
+ BEGIN:DAYLIGHT
129
+ DTSTART:20070311T020000
130
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
131
+ TZNAME:PDT
132
+ TZOFFSETFROM:-0800
133
+ TZOFFSETTO:-0700
134
+ END:DAYLIGHT
135
+ BEGIN:STANDARD
136
+ DTSTART:20071104T020000
137
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
138
+ TZNAME:PST
139
+ TZOFFSETFROM:-0700
140
+ TZOFFSETTO:-0800
141
+ END:STANDARD
142
+ END:VTIMEZONE
143
+ END:VCALENDAR
data/spec/parser_spec.rb CHANGED
@@ -5,6 +5,15 @@ describe Icalendar::Parser do
5
5
  let(:source) { File.read File.join(File.dirname(__FILE__), 'fixtures', fn) }
6
6
 
7
7
  describe '#parse' do
8
+ context 'reversed_timezone.ics' do
9
+ let(:fn) { 'reversed_timezone.ics' }
10
+
11
+ it 'correctly parses the event timezone' do
12
+ event = subject.parse.first.events.first
13
+ expect(event.dtstart.utc_offset).to eq -25200
14
+ end
15
+ end
16
+
8
17
  context 'single_event.ics' do
9
18
  let(:fn) { 'single_event.ics' }
10
19
 
@@ -14,7 +14,7 @@ describe Icalendar do
14
14
  event = Icalendar::Event.new
15
15
  parsed = Icalendar::Calendar.parse(source).first
16
16
  event.rdate = parsed.events.first.rdate
17
- expect(event.rdate.first).to be_kind_of Icalendar::Values::Array
17
+ expect(event.rdate.first).to be_kind_of Icalendar::Values::Helpers::Array
18
18
  expect(event.rdate.first.params_ical).to eq ";TZID=US-Mountain"
19
19
  end
20
20
  end
@@ -27,6 +27,22 @@ describe Icalendar::Values::DateTime do
27
27
  expect(subject.value.utc.hour).to eq 23
28
28
  end
29
29
  end
30
+
31
+ context 'nonstandard format tzid local time' do
32
+ let(:value) { '20230901T230404' }
33
+ let(:params) { {'tzid' => 'Singapore Standard Time'} }
34
+
35
+ it 'parses the value as local time' do
36
+ expect(subject.value.hour).to eq 23
37
+ expect(subject.value.utc_offset).to eq 28800
38
+ expect(subject.value.utc.hour).to eq 15
39
+ end
40
+
41
+ it 'updates the tzid' do
42
+ # use an array because that's how output from the parser will end up
43
+ expect(subject.ical_params['tzid']).to eq ['Asia/Singapore']
44
+ end
45
+ end
30
46
  end
31
47
 
32
48
  else
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.9.0
4
+ version: 2.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Ahearn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-11 00:00:00.000000000 Z
11
+ date: 2023-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ice_cube
@@ -58,42 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '6.0'
61
+ version: '7.1'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '6.0'
69
- - !ruby/object:Gem::Dependency
70
- name: i18n
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.8'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.8'
68
+ version: '7.1'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: tzinfo
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: '1.2'
75
+ version: '2.0'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '1.2'
82
+ version: '2.0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: tzinfo-data
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +136,20 @@ dependencies:
150
136
  - - "~>"
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0.16'
139
+ - !ruby/object:Gem::Dependency
140
+ name: byebug
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
153
  description: |
154
154
  Implements the iCalendar specification (RFC-5545) in Ruby. This allows
155
155
  for the generation and parsing of .ics files, which are used by a
@@ -187,8 +187,6 @@ files:
187
187
  - lib/icalendar/todo.rb
188
188
  - lib/icalendar/tzinfo.rb
189
189
  - lib/icalendar/value.rb
190
- - lib/icalendar/values/active_support_time_with_zone_adapter.rb
191
- - lib/icalendar/values/array.rb
192
190
  - lib/icalendar/values/binary.rb
193
191
  - lib/icalendar/values/boolean.rb
194
192
  - lib/icalendar/values/cal_address.rb
@@ -197,12 +195,14 @@ files:
197
195
  - lib/icalendar/values/date_time.rb
198
196
  - lib/icalendar/values/duration.rb
199
197
  - lib/icalendar/values/float.rb
198
+ - lib/icalendar/values/helpers/active_support_time_with_zone_adapter.rb
199
+ - lib/icalendar/values/helpers/array.rb
200
+ - lib/icalendar/values/helpers/time_with_zone.rb
200
201
  - lib/icalendar/values/integer.rb
201
202
  - lib/icalendar/values/period.rb
202
203
  - lib/icalendar/values/recur.rb
203
204
  - lib/icalendar/values/text.rb
204
205
  - lib/icalendar/values/time.rb
205
- - lib/icalendar/values/time_with_zone.rb
206
206
  - lib/icalendar/values/uri.rb
207
207
  - lib/icalendar/values/utc_offset.rb
208
208
  - lib/icalendar/version.rb
@@ -216,6 +216,7 @@ files:
216
216
  - spec/fixtures/nondefault_values.ics
217
217
  - spec/fixtures/nonstandard.ics
218
218
  - spec/fixtures/recurrence.ics
219
+ - spec/fixtures/reversed_timezone.ics
219
220
  - spec/fixtures/single_event.ics
220
221
  - spec/fixtures/single_event_bad_dtstart.ics
221
222
  - spec/fixtures/single_event_bad_line.ics
@@ -247,7 +248,8 @@ licenses:
247
248
  - BSD-2-Clause
248
249
  - GPL-3.0-only
249
250
  - icalendar
250
- metadata: {}
251
+ metadata:
252
+ changelog_uri: https://github.com/icalendar/icalendar/blob/main/History.txt
251
253
  post_install_message: 'ActiveSupport is required for TimeWithZone support, but not
252
254
  required for general use.
253
255
 
@@ -266,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
268
  - !ruby/object:Gem::Version
267
269
  version: '0'
268
270
  requirements: []
269
- rubygems_version: 3.3.7
271
+ rubygems_version: 3.3.26
270
272
  signing_key:
271
273
  specification_version: 4
272
274
  summary: A ruby implementation of the iCalendar specification (RFC-5545).
@@ -281,6 +283,7 @@ test_files:
281
283
  - spec/fixtures/nondefault_values.ics
282
284
  - spec/fixtures/nonstandard.ics
283
285
  - spec/fixtures/recurrence.ics
286
+ - spec/fixtures/reversed_timezone.ics
284
287
  - spec/fixtures/single_event.ics
285
288
  - spec/fixtures/single_event_bad_dtstart.ics
286
289
  - spec/fixtures/single_event_bad_line.ics
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Icalendar
4
- module Values
5
- class ActiveSupportTimeWithZoneAdapter < ActiveSupport::TimeWithZone
6
- # ActiveSupport::TimeWithZone implements a #to_a method that will cause
7
- # unexpected behavior in components with multi_property DateTime
8
- # properties when the setters for those properties are invoked with an
9
- # Icalendar::Values::DateTime that is delegating for an
10
- # ActiveSupport::TimeWithZone. To avoid this behavior, undefine #to_a.
11
- undef_method :to_a
12
- end
13
- end
14
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Icalendar
4
- module Values
5
-
6
- class Array < Value
7
-
8
- attr_reader :value_delimiter
9
-
10
- def initialize(value, klass, params = {}, options = {})
11
- @value_delimiter = options[:delimiter] || ','
12
- mapped = if value.is_a? ::Array
13
- value.map do |v|
14
- if v.is_a? Icalendar::Values::Array
15
- Icalendar::Values::Array.new v.value, klass, v.ical_params, delimiter: v.value_delimiter
16
- elsif v.is_a? ::Array
17
- Icalendar::Values::Array.new v, klass, params, delimiter: value_delimiter
18
- elsif v.is_a? Icalendar::Value
19
- v
20
- else
21
- klass.new v, params
22
- end
23
- end
24
- else
25
- [klass.new(value, params)]
26
- end
27
- super mapped
28
- end
29
-
30
- def params_ical
31
- value.each do |v|
32
- ical_params.merge! v.ical_params
33
- end
34
- super
35
- end
36
-
37
- def value_ical
38
- value.map do |v|
39
- v.value_ical
40
- end.join value_delimiter
41
- end
42
-
43
- def valid?
44
- klass = value.first.class
45
- !value.all? { |v| v.class == klass }
46
- end
47
-
48
- def value_type
49
- value.first.value_type
50
- end
51
-
52
- private
53
-
54
- def needs_value_type?(default_type)
55
- value.first.class != default_type
56
- end
57
- end
58
-
59
- end
60
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'icalendar/timezone_store'
4
-
5
- begin
6
- require 'active_support/time'
7
-
8
- if defined?(ActiveSupport::TimeWithZone)
9
- require 'icalendar/values/active_support_time_with_zone_adapter'
10
- end
11
- rescue NameError
12
- # ActiveSupport v7+ needs the base require to be run first before loading
13
- # specific parts of it.
14
- # https://guides.rubyonrails.org/active_support_core_extensions.html#stand-alone-active-support
15
- require 'active_support'
16
- retry
17
- rescue LoadError
18
- # tis ok, just a bit less fancy
19
- end
20
-
21
- module Icalendar
22
- module Values
23
- module TimeWithZone
24
- attr_reader :tz_utc
25
-
26
- def initialize(value, params = {})
27
- params = Icalendar::DowncasedHash(params)
28
- @tz_utc = params['tzid'] == 'UTC'
29
- x_tz_info = params.delete 'x-tz-info'
30
-
31
- offset_value = unless params['tzid'].nil?
32
- tzid = params['tzid'].is_a?(::Array) ? params['tzid'].first : params['tzid']
33
- if defined?(ActiveSupport::TimeZone) &&
34
- defined?(ActiveSupportTimeWithZoneAdapter) &&
35
- (tz = ActiveSupport::TimeZone[tzid])
36
- ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
37
- elsif !x_tz_info.nil?
38
- offset = x_tz_info.offset_for_local(value).to_s
39
- if value.respond_to?(:change)
40
- value.change offset: offset
41
- else
42
- ::Time.new value.year, value.month, value.day, value.hour, value.min, value.sec, offset
43
- end
44
- end
45
- end
46
- super((offset_value || value), params)
47
- end
48
-
49
- def params_ical
50
- ical_params.delete 'tzid' if tz_utc
51
- super
52
- end
53
- end
54
- end
55
- end