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 +4 -4
- data/.github/workflows/main.yml +1 -0
- data/CHANGELOG.md +5 -0
- data/icalendar.gemspec +2 -0
- data/lib/icalendar/offset/active_support_exact.rb +23 -0
- data/lib/icalendar/offset/active_support_partial.rb +27 -0
- data/lib/icalendar/offset/null.rb +17 -0
- data/lib/icalendar/offset/time_zone_store.rb +29 -0
- data/lib/icalendar/offset.rb +42 -0
- data/lib/icalendar/values/helpers/time_with_zone.rb +12 -34
- data/lib/icalendar/version.rb +1 -1
- metadata +35 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a3ae780c56015cbd4ff657ce042c086038f2f922069fa40eaaeaeedd3b7144c
|
4
|
+
data.tar.gz: 88d669f06da7a9b91c3c8a92dd08e11e70b8712a2c4b05a752427abc1ed56435
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 250a5156dbb7f7ec7cd7f9fddd51982676d81b5a41ae2815c85b41f3f114e3b3c812c07794463d3563f85a93d8097075a19bb7d37b2ca4694682cc8804ff9be7
|
7
|
+
data.tar.gz: 11c71867043fd1fd94cc6199e470b9ff4ce55c7c5e2455d0435b46676b4017743cec130de8f5383faf66eee4e28a400b6b807bf76eb1c781fd47604b7276a4c5
|
data/.github/workflows/main.yml
CHANGED
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
|
-
|
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
|
-
|
33
|
-
__setobj__(
|
34
|
-
|
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
|
data/lib/icalendar/version.rb
CHANGED
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.
|
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:
|
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
|