icalendar 2.10.3 → 2.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '091658a5c785f876d990794ef88444d4ea39e047aaf533ca3e93bfc8549c2495'
4
- data.tar.gz: 1292b5e139aae74264694245d9a722bc42e501abe6620b341b12d4922ac3cac8
3
+ metadata.gz: 8a3ae780c56015cbd4ff657ce042c086038f2f922069fa40eaaeaeedd3b7144c
4
+ data.tar.gz: 88d669f06da7a9b91c3c8a92dd08e11e70b8712a2c4b05a752427abc1ed56435
5
5
  SHA512:
6
- metadata.gz: 698656b8f89e982eb58c80cce76c4a8512df6ebdbcc37779eeeb2c57daaf3f180fe0226c3a8bdb66155438e2f71afa6df76b537d8a4cb528646211c850a1e70d
7
- data.tar.gz: acd49ceb561f8f5a61be057c3ea00b938a6907a4af9826afd27fe2f484e256d1ff97869d5777ac58e79e55834ed97cc7c56136fb38d6b54f500959dc054c8d22
6
+ metadata.gz: 250a5156dbb7f7ec7cd7f9fddd51982676d81b5a41ae2815c85b41f3f114e3b3c812c07794463d3563f85a93d8097075a19bb7d37b2ca4694682cc8804ff9be7
7
+ data.tar.gz: 11c71867043fd1fd94cc6199e470b9ff4ce55c7c5e2455d0435b46676b4017743cec130de8f5383faf66eee4e28a400b6b807bf76eb1c781fd47604b7276a4c5
@@ -21,6 +21,7 @@ jobs:
21
21
  - 3.1
22
22
  - 3.2
23
23
  - 3.3
24
+ - 3.4
24
25
 
25
26
  steps:
26
27
  - uses: actions/checkout@v4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 2.11.0 - 2025-04-12
4
+ - Require gems for ruby 3.4 that used to be in stdlib - Go Sueyoshi
5
+ - Refactor how timezone offsets are calculated - Pat Allan
6
+ - 'tzid' param is always returned as an array when accessing `ical_params` directly, rather than matching whatever the input parsed. ICS output remains unchanged
7
+
3
8
  ## 2.10.3 - 2024-09-21
4
9
  - Override Icalendar::Value.== so that value objects can be compared to each other.
5
10
  - Correctly load activesupport before activesupport/time
data/icalendar.gemspec CHANGED
@@ -31,7 +31,9 @@ ActiveSupport is required for TimeWithZone support, but not required for general
31
31
 
32
32
  s.required_ruby_version = '>= 2.4.0'
33
33
 
34
+ s.add_dependency 'base64'
34
35
  s.add_dependency 'ice_cube', '~> 0.16'
36
+ s.add_dependency 'logger'
35
37
  s.add_dependency 'ostruct'
36
38
 
37
39
  s.add_development_dependency 'rake', '~> 13.0'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ class Offset
5
+ class ActiveSupportExact < Icalendar::Offset
6
+ def valid?
7
+ support_classes_defined? && tz
8
+ end
9
+
10
+ def normalized_value
11
+ Icalendar.logger.debug("Plan a - parsing #{value}/#{tzid} as ActiveSupport::TimeWithZone")
12
+ # plan a - use ActiveSupport::TimeWithZone
13
+ Icalendar::Values::Helpers::ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
14
+ end
15
+
16
+ private
17
+
18
+ def tz
19
+ @tz ||= ActiveSupport::TimeZone[tzid]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ class Offset
5
+ class ActiveSupportPartial < Offset
6
+ def valid?
7
+ support_classes_defined? && tz
8
+ end
9
+
10
+ def normalized_value
11
+ # plan c - try to find an ActiveSupport::TimeWithZone based on the first word of the tzid
12
+ Icalendar.logger.debug("Plan c - parsing #{value}/#{tz.tzinfo.name} as ActiveSupport::TimeWithZone")
13
+ Icalendar::Values::Helpers::ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
14
+ end
15
+
16
+ def normalized_tzid
17
+ [tz.tzinfo.name]
18
+ end
19
+
20
+ private
21
+
22
+ def tz
23
+ @tz ||= ActiveSupport::TimeZone[tzid.split.first]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ class Offset
5
+ class Null < Offset
6
+ def valid?
7
+ true
8
+ end
9
+
10
+ def normalized_value
11
+ # plan d - just ignore the tzid
12
+ Icalendar.logger.info("Ignoring timezone #{tzid} for time #{value}")
13
+ nil
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ class Offset
5
+ class TimeZoneStore < Offset
6
+ def valid?
7
+ timezone_store && tz_info
8
+ end
9
+
10
+ def normalized_value
11
+ # plan b - use definition from provided `VTIMEZONE`
12
+ offset = tz_info.offset_for_local(value).to_s
13
+
14
+ Icalendar.logger.debug("Plan b - parsing #{value} with offset: #{offset}")
15
+ if value.respond_to?(:change)
16
+ value.change offset: offset
17
+ else
18
+ ::Time.new value.year, value.month, value.day, value.hour, value.min, value.sec, offset
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def tz_info
25
+ @tz_info ||= timezone_store.retrieve(tzid)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Icalendar
4
+ class Offset
5
+ def self.build(value, params, timezone_store)
6
+ return nil if params.nil? || params['tzid'].nil?
7
+
8
+ tzid = Array(params['tzid']).first
9
+
10
+ [
11
+ Icalendar::Offset::ActiveSupportExact,
12
+ Icalendar::Offset::TimeZoneStore,
13
+ Icalendar::Offset::ActiveSupportPartial,
14
+ Icalendar::Offset::Null
15
+ ].lazy.map { |klass| klass.new(tzid, value, timezone_store) }.detect(&:valid?)
16
+ end
17
+
18
+ def initialize(tzid, value, timezone_store)
19
+ @tzid = tzid
20
+ @value = value
21
+ @timezone_store = timezone_store
22
+ end
23
+
24
+ def normalized_tzid
25
+ Array(tzid)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :tzid, :value, :timezone_store
31
+
32
+ def support_classes_defined?
33
+ defined?(ActiveSupport::TimeZone) &&
34
+ defined?(Icalendar::Values::Helpers::ActiveSupportTimeWithZoneAdapter)
35
+ end
36
+ end
37
+ end
38
+
39
+ require_relative "offset/active_support_exact"
40
+ require_relative "offset/active_support_partial"
41
+ require_relative "offset/null"
42
+ require_relative "offset/time_zone_store"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "icalendar/offset"
4
+
3
5
  begin
4
6
  require 'active_support'
5
7
  require 'active_support/time'
@@ -21,7 +23,13 @@ module Icalendar
21
23
  params = Icalendar::DowncasedHash(params)
22
24
  @tz_utc = params['tzid'] == 'UTC'
23
25
  @timezone_store = params.delete 'x-tz-store'
24
- super (offset_value(value, params) || value), params
26
+
27
+ offset = Icalendar::Offset.build(value, params, timezone_store)
28
+
29
+ @offset_value = offset&.normalized_value
30
+ params['tzid'] = offset.normalized_tzid if offset
31
+
32
+ super (@offset_value || value), params
25
33
  end
26
34
 
27
35
  def __getobj__
@@ -29,9 +37,9 @@ module Icalendar
29
37
  if set_offset?
30
38
  orig_value
31
39
  else
32
- offset = offset_value(orig_value, ical_params)
33
- __setobj__(offset) unless offset.nil?
34
- offset || orig_value
40
+ new_value = Icalendar::Offset.build(orig_value, ical_params, timezone_store)&.normalized_value
41
+ __setobj__(new_value) unless new_value.nil?
42
+ new_value || orig_value
35
43
  end
36
44
  end
37
45
 
@@ -42,36 +50,6 @@ module Icalendar
42
50
 
43
51
  private
44
52
 
45
- def offset_value(value, params)
46
- @offset_value = unless params.nil? || params['tzid'].nil?
47
- tzid = params['tzid'].is_a?(::Array) ? params['tzid'].first : params['tzid']
48
- support_classes_defined = defined?(ActiveSupport::TimeZone) && defined?(ActiveSupportTimeWithZoneAdapter)
49
- if support_classes_defined && (tz = ActiveSupport::TimeZone[tzid])
50
- Icalendar.logger.debug("Plan a - parsing #{value}/#{tzid} as ActiveSupport::TimeWithZone")
51
- # plan a - use ActiveSupport::TimeWithZone
52
- ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
53
- elsif !timezone_store.nil? && !(x_tz_info = timezone_store.retrieve(tzid)).nil?
54
- # plan b - use definition from provided `VTIMEZONE`
55
- offset = x_tz_info.offset_for_local(value).to_s
56
- Icalendar.logger.debug("Plan b - parsing #{value} with offset: #{offset}")
57
- if value.respond_to?(:change)
58
- value.change offset: offset
59
- else
60
- ::Time.new value.year, value.month, value.day, value.hour, value.min, value.sec, offset
61
- end
62
- elsif support_classes_defined && (tz = ActiveSupport::TimeZone[tzid.split.first])
63
- # plan c - try to find an ActiveSupport::TimeWithZone based on the first word of the tzid
64
- Icalendar.logger.debug("Plan c - parsing #{value}/#{tz.tzinfo.name} as ActiveSupport::TimeWithZone")
65
- params['tzid'] = [tz.tzinfo.name]
66
- ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
67
- else
68
- # plan d - just ignore the tzid
69
- Icalendar.logger.info("Ignoring timezone #{tzid} for time #{value}")
70
- nil
71
- end
72
- end
73
- end
74
-
75
53
  def set_offset?
76
54
  !!@offset_value
77
55
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Icalendar
4
4
 
5
- VERSION = '2.10.3'
5
+ VERSION = '2.11.0'
6
6
 
7
7
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icalendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.3
4
+ version: 2.11.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: 2024-09-21 00:00:00.000000000 Z
11
+ date: 2025-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: base64
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: ice_cube
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +38,20 @@ dependencies:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: logger
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: ostruct
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -195,6 +223,11 @@ files:
195
223
  - lib/icalendar/journal.rb
196
224
  - lib/icalendar/logger.rb
197
225
  - lib/icalendar/marshable.rb
226
+ - lib/icalendar/offset.rb
227
+ - lib/icalendar/offset/active_support_exact.rb
228
+ - lib/icalendar/offset/active_support_partial.rb
229
+ - lib/icalendar/offset/null.rb
230
+ - lib/icalendar/offset/time_zone_store.rb
198
231
  - lib/icalendar/parser.rb
199
232
  - lib/icalendar/timezone.rb
200
233
  - lib/icalendar/timezone_store.rb