icalendar 2.10.1 → 2.12.2

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +5 -3
  3. data/CHANGELOG.md +231 -0
  4. data/README.md +1 -1
  5. data/icalendar.gemspec +4 -1
  6. data/lib/icalendar/downcased_hash.rb +39 -6
  7. data/lib/icalendar/offset/active_support_exact.rb +23 -0
  8. data/lib/icalendar/offset/active_support_partial.rb +27 -0
  9. data/lib/icalendar/offset/null.rb +17 -0
  10. data/lib/icalendar/offset/time_zone_store.rb +29 -0
  11. data/lib/icalendar/offset/windows_to_iana.rb +144 -0
  12. data/lib/icalendar/offset.rb +44 -0
  13. data/lib/icalendar/parser.rb +14 -8
  14. data/lib/icalendar/value.rb +11 -2
  15. data/lib/icalendar/values/boolean.rb +3 -3
  16. data/lib/icalendar/values/date.rb +3 -4
  17. data/lib/icalendar/values/date_time.rb +3 -3
  18. data/lib/icalendar/values/duration.rb +3 -3
  19. data/lib/icalendar/values/float.rb +3 -3
  20. data/lib/icalendar/values/helpers/array.rb +7 -6
  21. data/lib/icalendar/values/helpers/time_with_zone.rb +18 -42
  22. data/lib/icalendar/values/integer.rb +3 -3
  23. data/lib/icalendar/values/period.rb +3 -3
  24. data/lib/icalendar/values/recur.rb +3 -3
  25. data/lib/icalendar/values/text.rb +2 -2
  26. data/lib/icalendar/values/time.rb +4 -4
  27. data/lib/icalendar/values/uri.rb +4 -3
  28. data/lib/icalendar/values/utc_offset.rb +2 -2
  29. data/lib/icalendar/version.rb +1 -1
  30. data/spec/fixtures/single_event_bad_location.ics +23 -0
  31. data/spec/fixtures/two_time_events.ics +1 -1
  32. data/spec/fixtures/tz_store_param_bug.ics +30 -0
  33. data/spec/parser_spec.rb +24 -0
  34. data/spec/spec_helper.rb +6 -0
  35. data/spec/values/date_spec.rb +24 -0
  36. data/spec/values/date_time_spec.rb +22 -7
  37. data/spec/values/uri_spec.rb +43 -0
  38. metadata +61 -7
  39. data/History.txt +0 -200
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b9f7e30ef6614ad4175a9d282d1b03b57f140f98a2962b4e0268aa015f8f942
4
- data.tar.gz: 7ebabfddd0f3d8e8e05e1ef82d2389007c1419c727c5404d2ec2c1c09565a8bb
3
+ metadata.gz: ad06e861392ab70f0e800ac4f2a6b81f019aaf3548a35e513f02bcc975968b86
4
+ data.tar.gz: 16562bdeae817fc8afd4e0b6de7090a42c0b095cb56640d5b9183cfb3a07bb74
5
5
  SHA512:
6
- metadata.gz: 8d3221e4e5bd2120014ae11fe80a8e0a3b36af37b10aadd18f3bc6022e296efa47ea27d09572900bb6d6419fff64054caa6709e6b14e5182d32a188d0130b7f0
7
- data.tar.gz: 5d7d996d53a12543de0830fdb8214e2ae39df4c19c649e81cd95ceb8d30d61f1f178b7a9a4f4e37adb591609eeac7e89d930cf5ffc24951c9cbfcb0b815c2a03
6
+ metadata.gz: 927cd1536b413039b75f4c2a100ca169bb17897c10754b4806762d341aaa4b7800fc93e7bc81566681a678a853fefc0d54fad5fdd0316c10f0245f91864d2faf
7
+ data.tar.gz: 5d9c09347062a5dd73ad23cd75905c5508b8a72ce0447241ee282fa6bbcc7d259e4a26309fc90af718f14f14b18ca78403bc849898b42147c5368ae6edb21d13
@@ -15,11 +15,13 @@ jobs:
15
15
  runs-on: ubuntu-latest
16
16
 
17
17
  strategy:
18
+ fail-fast: false
18
19
  matrix:
19
20
  ruby:
20
- - 3.0.6
21
- - 3.1.4
22
- - 3.2.2
21
+ - 3.1
22
+ - 3.2
23
+ - 3.3
24
+ - 3.4
23
25
 
24
26
  steps:
25
27
  - uses: actions/checkout@v4
data/CHANGELOG.md ADDED
@@ -0,0 +1,231 @@
1
+ ## Unreleased
2
+
3
+ ## 2.12.2 - 2026-03-21
4
+ - Fix a potential property injection issue through escaping control characters in URI values - Wes Ring
5
+
6
+ ## 2.12.1 - 2025-10-19
7
+ - Fix a problem with invalid ics generation for calendars with custom properties that include a `tzid` parameter.
8
+
9
+ ## 2.12.0 - 2025-09-26
10
+ - Support timezone lookup by Windows names - Ronak Gothi
11
+
12
+ ## 2.11.2 - 2025-06-21
13
+ - Deal with more bad value parameter values by falling back to the property default type
14
+
15
+ ## 2.11.1 - 2025-06-06
16
+ - Gracefully deal with malformed ics files that use spaces in the value parameter instead of hyphens
17
+
18
+ ## 2.11.0 - 2025-04-12
19
+ - Require gems for ruby 3.4 that used to be in stdlib - Go Sueyoshi
20
+ - Refactor how timezone offsets are calculated - Pat Allan
21
+ - 'tzid' param is always returned as an array when accessing `ical_params` directly, rather than matching whatever the input parsed. ICS output remains unchanged
22
+
23
+ ## 2.10.3 - 2024-09-21
24
+ - Override Icalendar::Value.== so that value objects can be compared to each other.
25
+ - Correctly load activesupport before activesupport/time
26
+ - Load ostruct to address deprecation warning - aki77
27
+
28
+ ## 2.10.2 - 2024-07-21
29
+ - Raise Icalendar::Parser::ParseError on bad .ics file input instead of RuntimeError - Micah Geisel
30
+ - Remove Ruby 3.0 from the test matrix - still should work for now with ice_cube < 0.17.0
31
+ - Add Ruby 3.3 to the test matrix
32
+ - Move from old History.txt file to modern CHANGELOG.md - Guillaume Briday
33
+
34
+ ## 2.10.1 - 2023-12-01
35
+ - Parsing now handles VTIMEZONE blocks defined after their TZID is used in events and other components
36
+
37
+ ## 2.10.0 - 2023-11-01
38
+ - Add changelog metadata to gemspec - Juri Hahn
39
+ - Attempt to rescue timezone info when given a nonstandard tzid with no VTIMEZONE
40
+ - Move Values classes that shouldn't be directly used into Helpers module
41
+
42
+ ## 2.9.0 - 2023-08-11
43
+ - Always include the VALUE of Event URLs for improved compatibility - Sean Kelley
44
+ - Improved parse performance - Thomas Cannon
45
+ - Add helper methods for other Calendar method verbs
46
+ - bugfix: Require stringio before use in Parser - vwyu
47
+
48
+ ## 2.8.0 - 2022-07-10
49
+ - Fix compatibility with ActiveSupport 7 - Pat Allan
50
+ - Set default action of "DISPLAY" on alarms - Rikson
51
+ - Add license information to gemspec - Robert Reiz
52
+ - Support RFC7986 properties - Daniele Frisanco
53
+
54
+ ## 2.7.1 - 2021-03-14
55
+ - Recover from bad line-wrapping code that splits in the middle of Unicode code points
56
+ - Add a verbose option to the Parser to quiet some of the chattier log entries
57
+
58
+ ## 2.7.0 - 2020-09-12
59
+ - Handle custom component names, with and without X- prefix
60
+ - Fix Component lookup to avoid namespace collisions
61
+
62
+ ## 2.6.1 - 2019-12-07
63
+ - Improve performance when generating large ICS files - Alex Balhatchet
64
+
65
+ ## 2.6.0 - 2019-11-26
66
+ - Improve performance for calculating timezone offsets - Justin Howard
67
+ - Make it possible to de/serialize with Marshal - Pawel Niewiadomski
68
+ - Avoid FrozenError when running with frozen_string_literal
69
+ - Update minimum Ruby version to supported versions
70
+
71
+ ## 2.5.3 - 2019-03-04
72
+ - Improve parsing performance - nehresma
73
+ - Support tzinfo 2.0 - Misty De Meo
74
+
75
+ ## 2.5.2 - 2018-12-08
76
+ - Remove usage of the global TimezoneStore instance, in favor of a local variable in the parser
77
+ - Deprecate TimezoneStore class methods
78
+
79
+ ## 2.5.1 - 2018-10-30
80
+ - Fix usage without ActiveSupport installed.
81
+
82
+ ## 2.5.0 - 2018-09-10
83
+ - Set timezone information from VTIMEZONE components in cases that ActiveSupport can't figure it out (or isn't installed)
84
+ - Prevent rewinding the Parser IO input during parsing - Niels Laukens
85
+ - Update tested/supported ruby versions & documentation updates.
86
+
87
+ ## 2.4.1 - 2016-09-03
88
+ - Fix parsing multiple calendars or components in same file - Patrick Schnetger
89
+ - Fix multi-byte folding bug - Niels Laukens
90
+ - Fix typos across the code - Martin Edenhofer & yuuji.yaginuma
91
+
92
+ ## 2.4.0 - 2016-07-04
93
+ - Enable parsing individual ICalendar components - Patrick Schnetger
94
+ - many bug fixes. Thanks to Quan Sun, Garry Shutler, Ryan Bigg, Patrick Schnetger and others
95
+ - README/documentation updates. Thanks to JonMidhir and Hendrik Sollich
96
+
97
+ ## 2.3.0 - 2015-04-26
98
+ - fix value parameter for properties with multiple values
99
+ - fix error when assigning Icalendar::Values::Array to a component
100
+ - Fall back to Icalendar::Values::Date if Icalendar::Values::DateTime is not given a properly formatted value
101
+ - Downcase the keys in ical_params to ensure we aren't assigning both tzid and TZID
102
+
103
+ ## 2.2.2 - 2014-12-27
104
+ - add a `has_#{component}?` method for testing if component exists - John Hope
105
+ - add documentation & tests for organizer attribute - Ben Walding
106
+
107
+ ## 2.2.1 - 2014-12-03
108
+ - Prevent crashes when using ActiveSupport::TimeWithZone in multi-property DateTime fields - Danny (tdg5)
109
+ - Ensure TimeWithZone is loaded before using, not just ActiveSupport - Jeremy Evans
110
+ - Improve error message on unparseable DateTimes - Garry Shutler
111
+
112
+ ## 2.2.0 - 2014-09-23
113
+ - Default to non-strict parsing
114
+ - Enable sorting events by dtstart - Mark Rickert
115
+ - Better tolerate malformed lines in parser - Garry Shutler
116
+ - Deduplicate timezone code - Jan Vlnas
117
+ - Eliminate warnings - rochefort
118
+
119
+ ## 2.1.2 - 2014-09-10
120
+ - Fix timezone abbreviation generation - Jan Vlnas
121
+ - Fix timezone repeat rules for end of month
122
+
123
+ ## 2.1.1 - 2014-07-23
124
+ - Quiet TimeWithZone support logging
125
+ - Use SecureRandom.uuid - antoinelyset
126
+
127
+ ## 2.1.0 - 2014-06-17
128
+ - Enable parsing all custom properties, not just X- prefixed ones
129
+ Requires non-strict parsing
130
+ - Fixed bugs when using non-MRI ruby interpreters
131
+ - Fix bug copying OpenStruct-backed value types
132
+
133
+ ## 2.0.1 - 2014-04-27
134
+ - Re-add support for ruby 1.9.2
135
+
136
+ ## 2.0.0 - 2014-04-22
137
+ - Add Icalendar.logger class & logging in Parser
138
+ - Support tzinfo ~> 0.3 and ~> 1.1
139
+
140
+ ## 2.0.0.beta.2 - 2014-04-11
141
+ - Add uid & acknowledged fields from valarm extensions
142
+ - Swallow NoMethodError on non-strict parsers
143
+ - Expose a parse_property method on Icalendar::Parser
144
+
145
+ ## 2.0.0.beta.1 - 2014-03-30
146
+ - Rewrite for easier development going forward.
147
+
148
+ ## 1.5.2 - 2014-02-22
149
+ - Output timezone components first
150
+ - Fix undefined local variable or method 'e' - Jason Stirk
151
+
152
+ ## 1.5.1 - 2014-02-27
153
+ - Check for dtend existence before setting timezone - Jonas Grau
154
+ - Clean up and refactor components - Kasper Timm Hansen
155
+
156
+ ## 1.5.0 - 2013-12-06
157
+ - Support for custom x- properties - Jake Craige
158
+
159
+ ## 1.4.5 - 2013-11-14
160
+ - Fix Geo accessor methods - bouzuya
161
+ - Add ical_multiline_property :related_to for Alarm
162
+ - Allow using multi setters to append single values
163
+
164
+ ## 1.4.4 - 2013-11-05
165
+ - Allow user to handle TZInfo::AmbiguousTime error - David Bradford
166
+ - Better handling of multiple exdate and rdate values
167
+
168
+ ## 1.4.3 - 2013-09-18
169
+ - Fix concatenation of multiple BYWEEK or BYMONTH recurrence rules
170
+
171
+ ## 1.4.2 - 2013-09-11
172
+ - Double Quote parameter values that contain forbidden characters
173
+ - Update Component#respond_to? to match Ruby 2.0 - Keith Marcum
174
+
175
+ ## 1.4.1 - 2013-06-25
176
+ - Don't escape semicolon in GEO property - temirov
177
+ - Allow access to various parts of RRule class
178
+
179
+ ## 1.4.0 - 2013-05-21
180
+ - Implement ACKNOWLEDGED property for VALARM - tsuzuki08
181
+ - Output VERSION property as first line after BEGIN:VCALENDAR
182
+ - Check for unbounded timezone transitions in tzinfo
183
+
184
+ ## 1.3.0 - 2013-03-31
185
+ - Lenient parsing mode ignores unknown properties - David Grandinetti
186
+ - VTIMEZONE positive offsets properly have "+" prepended (Fixed issue
187
+ #18) - Benjamin Jorgensen (sorry for misspelling your last name)
188
+
189
+ ## 1.2.4 - 2013-03-26
190
+ - Proxy component values now frozen in Ruby 2.0 (Fixed issue #17)
191
+ - Clean up gemspec for cleaner installing via bundler/git
192
+
193
+ ## 1.2.3 - 2013-03-09
194
+ - Call `super` from Component#method_missing
195
+ - Clean up warnings in test suite
196
+ - Add Gemfile for installing development dependencies
197
+
198
+ ## 1.2.2 - 2013-02-16
199
+ - added TZURL property to Timezone component - spacepixels
200
+ - correct days in RRule ("[TU,WE]" -> "TU,WE") - Christoph Finkensiep
201
+
202
+ ## 1.2.1 - 2012-11-12
203
+ - Adds uid property to alarms to support iCloud - Jeroen Jacobs
204
+ - Fix up testing docs - Eric Carty-Fickes
205
+ - Fix parsing property params that have : in them - Sean Dague
206
+ - Clean up warnings in test suite - Sean Dague
207
+
208
+ ## 1.2.0 - 2012-08-30
209
+ * Fix calendar handling for dates < 1000 - Ryan Ahearn
210
+ * Updated license to GPL/BSD/Ruby at users option
211
+
212
+ ## 1.1.6 - 2011-03-10
213
+ * Fix todo handling (thanks to Frank Schwarz)
214
+ * clean up a number of warnings during test runs
215
+
216
+ ## 1.1.5 - 2010-06-21
217
+ * Fix for windows line endings (thanks to Rowan Collins)
218
+
219
+ ## 1.1.4 - 2010-04-23
220
+ * Fix for RRULE escaping
221
+ * Fix tests so they run under 1.8.7 in multiple environments
222
+ * Readme fix
223
+
224
+ ## 1.1.3 - 2010-03-15
225
+ * Revert component sorting behavior that I was trying to make
226
+ the tests run more consistantly on different platforms.
227
+ * Added new test for multiple events in a calendar which caught that break.
228
+
229
+ ## 1.1.2 - 2010-03-10
230
+
231
+ * Convert project to newgem to make for easier publishing
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  iCalendar -- Internet calendaring, Ruby style
2
2
  ===
3
3
 
4
- [![Build Status](https://travis-ci.com/icalendar/icalendar.svg?branch=master)](https://travis-ci.com/icalendar/icalendar)
4
+ [![Ruby](https://github.com/icalendar/icalendar/actions/workflows/main.yml/badge.svg)](https://github.com/icalendar/icalendar/actions/workflows/main.yml)
5
5
  [![Code Climate](https://codeclimate.com/github/icalendar/icalendar.png)](https://codeclimate.com/github/icalendar/icalendar)
6
6
 
7
7
  <http://github.com/icalendar/icalendar>
data/icalendar.gemspec CHANGED
@@ -21,7 +21,7 @@ ActiveSupport is required for TimeWithZone support, but not required for general
21
21
  EOM
22
22
 
23
23
  s.metadata = {
24
- 'changelog_uri' => 'https://github.com/icalendar/icalendar/blob/main/History.txt'
24
+ 'changelog_uri' => 'https://github.com/icalendar/icalendar/blob/main/CHANGELOG.md'
25
25
  }
26
26
 
27
27
  s.files = `git ls-files`.split "\n"
@@ -31,7 +31,10 @@ 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'
37
+ s.add_dependency 'ostruct'
35
38
 
36
39
  s.add_development_dependency 'rake', '~> 13.0'
37
40
  s.add_development_dependency 'bundler', '~> 2.0'
@@ -3,32 +3,65 @@
3
3
  require 'delegate'
4
4
 
5
5
  module Icalendar
6
- class DowncasedHash < ::SimpleDelegator
6
+ class DowncasedHash
7
7
 
8
8
  def initialize(base)
9
- super Hash.new
9
+ @obj = Hash.new
10
10
  base.each do |key, value|
11
11
  self[key] = value
12
12
  end
13
13
  end
14
14
 
15
15
  def []=(key, value)
16
- __getobj__[key.to_s.downcase] = value
16
+ obj[key.to_s.downcase] = value
17
17
  end
18
18
 
19
19
  def [](key)
20
- __getobj__[key.to_s.downcase]
20
+ obj[key.to_s.downcase]
21
21
  end
22
22
 
23
23
  def has_key?(key)
24
- __getobj__.has_key? key.to_s.downcase
24
+ obj.has_key? key.to_s.downcase
25
25
  end
26
26
  alias_method :include?, :has_key?
27
27
  alias_method :member?, :has_key?
28
28
 
29
29
  def delete(key, &block)
30
- __getobj__.delete key.to_s.downcase, &block
30
+ obj.delete key.to_s.downcase, &block
31
31
  end
32
+
33
+ def merge(*other_hashes)
34
+ Icalendar::DowncasedHash.new(obj).merge!(*other_hashes)
35
+ end
36
+
37
+ def merge!(*other_hashes)
38
+ other_hashes.each do |hash|
39
+ hash.each do |key, value|
40
+ self[key] = value
41
+ end
42
+ end
43
+ self
44
+ end
45
+
46
+ def empty?
47
+ obj.empty?
48
+ end
49
+
50
+ def each(&block)
51
+ obj.each &block
52
+ end
53
+
54
+ def map(&block)
55
+ obj.map &block
56
+ end
57
+
58
+ def ==(other)
59
+ obj == Icalendar::DowncasedHash(other).obj
60
+ end
61
+
62
+ protected
63
+
64
+ attr_reader :obj
32
65
  end
33
66
 
34
67
  def self.DowncasedHash(base)
@@ -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,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This module contains mappings from Windows timezone identifiers to Olson timezone identifiers.
4
+ #
5
+ # The data is taken from the unicode consortium [0], the proposal and rationale
6
+ # for this mapping is also available at the unicode consortium [1].
7
+ #
8
+ # [0] https://www.unicode.org/cldr/cldr-aux/charts/29/supplemental/zone_tzid.html
9
+ # [1] https://cldr.unicode.org/development/development-process/design-proposals/extended-windows-olson-zid-mapping
10
+
11
+ module Icalendar
12
+ class Offset
13
+ class WindowsToIana < Offset
14
+ WINDOWS_TO_IANA = {
15
+ 'AUS Central Standard Time' => 'Australia/Darwin',
16
+ 'AUS Eastern Standard Time' => 'Australia/Sydney',
17
+ 'Afghanistan Standard Time' => 'Asia/Kabul',
18
+ 'Alaskan Standard Time' => 'America/Anchorage',
19
+ 'Arab Standard Time' => 'Asia/Riyadh',
20
+ 'Arabian Standard Time' => 'Asia/Dubai',
21
+ 'Arabic Standard Time' => 'Asia/Baghdad',
22
+ 'Argentina Standard Time' => 'America/Argentina/Buenos_Aires',
23
+ 'Atlantic Standard Time' => 'America/Halifax',
24
+ 'Azerbaijan Standard Time' => 'Asia/Baku',
25
+ 'Azores Standard Time' => 'Atlantic/Azores',
26
+ 'Bahia Standard Time' => 'America/Bahia',
27
+ 'Bangladesh Standard Time' => 'Asia/Dhaka',
28
+ 'Belarus Standard Time' => 'Europe/Minsk',
29
+ 'Canada Central Standard Time' => 'America/Regina',
30
+ 'Cape Verde Standard Time' => 'Atlantic/Cape_Verde',
31
+ 'Caucasus Standard Time' => 'Asia/Yerevan',
32
+ 'Cen. Australia Standard Time' => 'Australia/Adelaide',
33
+ 'Central America Standard Time' => 'America/Guatemala',
34
+ 'Central Asia Standard Time' => 'Asia/Almaty',
35
+ 'Central Brazilian Standard Time' => 'America/Cuiaba',
36
+ 'Central Europe Standard Time' => 'Europe/Budapest',
37
+ 'Central European Standard Time' => 'Europe/Warsaw',
38
+ 'Central Pacific Standard Time' => 'Pacific/Guadalcanal',
39
+ 'Central Standard Time' => 'America/Chicago',
40
+ 'Central Standard Time (Mexico)' => 'America/Mexico_City',
41
+ 'China Standard Time' => 'Asia/Shanghai',
42
+ 'Dateline Standard Time' => 'Etc/GMT+12',
43
+ 'E. Africa Standard Time' => 'Africa/Nairobi',
44
+ 'E. Australia Standard Time' => 'Australia/Brisbane',
45
+ 'E. Europe Standard Time' => 'Europe/Chisinau',
46
+ 'E. South America Standard Time' => 'America/Sao_Paulo',
47
+ 'Eastern Standard Time' => 'America/New_York',
48
+ 'Eastern Standard Time (Mexico)' => 'America/Cancun',
49
+ 'Egypt Standard Time' => 'Africa/Cairo',
50
+ 'Ekaterinburg Standard Time' => 'Asia/Yekaterinburg',
51
+ 'FLE Standard Time' => 'Europe/Kyiv',
52
+ 'Fiji Standard Time' => 'Pacific/Fiji',
53
+ 'GMT Standard Time' => 'Europe/London',
54
+ 'GTB Standard Time' => 'Europe/Bucharest',
55
+ 'Georgian Standard Time' => 'Asia/Tbilisi',
56
+ 'Greenland Standard Time' => 'America/Nuuk',
57
+ 'Greenwich Standard Time' => 'Atlantic/Reykjavik',
58
+ 'Hawaiian Standard Time' => 'Pacific/Honolulu',
59
+ 'India Standard Time' => 'Asia/Kolkata',
60
+ 'Iran Standard Time' => 'Asia/Tehran',
61
+ 'Israel Standard Time' => 'Asia/Jerusalem',
62
+ 'Jordan Standard Time' => 'Asia/Amman',
63
+ 'Kaliningrad Standard Time' => 'Europe/Kaliningrad',
64
+ 'Korea Standard Time' => 'Asia/Seoul',
65
+ 'Libya Standard Time' => 'Africa/Tripoli',
66
+ 'Line Islands Standard Time' => 'Pacific/Kiritimati',
67
+ 'Magadan Standard Time' => 'Asia/Magadan',
68
+ 'Mauritius Standard Time' => 'Indian/Mauritius',
69
+ 'Middle East Standard Time' => 'Asia/Beirut',
70
+ 'Montevideo Standard Time' => 'America/Montevideo',
71
+ 'Morocco Standard Time' => 'Africa/Casablanca',
72
+ 'Mountain Standard Time' => 'America/Denver',
73
+ 'Mountain Standard Time (Mexico)' => 'America/Chihuahua',
74
+ 'Myanmar Standard Time' => 'Asia/Yangon',
75
+ 'N. Central Asia Standard Time' => 'Asia/Novosibirsk',
76
+ 'Namibia Standard Time' => 'Africa/Windhoek',
77
+ 'Nepal Standard Time' => 'Asia/Kathmandu',
78
+ 'New Zealand Standard Time' => 'Pacific/Auckland',
79
+ 'Newfoundland Standard Time' => 'America/St_Johns',
80
+ 'North Asia East Standard Time' => 'Asia/Irkutsk',
81
+ 'North Asia Standard Time' => 'Asia/Krasnoyarsk',
82
+ 'North Korea Standard Time' => 'Asia/Pyongyang',
83
+ 'Pacific SA Standard Time' => 'America/Santiago',
84
+ 'Pacific Standard Time' => 'America/Los_Angeles',
85
+ 'Pakistan Standard Time' => 'Asia/Karachi',
86
+ 'Paraguay Standard Time' => 'America/Asuncion',
87
+ 'Romance Standard Time' => 'Europe/Paris',
88
+ 'Russia Time Zone 10' => 'Asia/Srednekolymsk',
89
+ 'Russia Time Zone 11' => 'Asia/Kamchatka',
90
+ 'Russia Time Zone 3' => 'Europe/Samara',
91
+ 'Russian Standard Time' => 'Europe/Moscow',
92
+ 'SA Eastern Standard Time' => 'America/Cayenne',
93
+ 'SA Pacific Standard Time' => 'America/Bogota',
94
+ 'SA Western Standard Time' => 'America/La_Paz',
95
+ 'SE Asia Standard Time' => 'Asia/Bangkok',
96
+ 'Samoa Standard Time' => 'Pacific/Apia',
97
+ 'Singapore Standard Time' => 'Asia/Singapore',
98
+ 'South Africa Standard Time' => 'Africa/Johannesburg',
99
+ 'Sri Lanka Standard Time' => 'Asia/Colombo',
100
+ 'Syria Standard Time' => 'Asia/Damascus',
101
+ 'Taipei Standard Time' => 'Asia/Taipei',
102
+ 'Tasmania Standard Time' => 'Australia/Hobart',
103
+ 'Tokyo Standard Time' => 'Asia/Tokyo',
104
+ 'Tonga Standard Time' => 'Pacific/Tongatapu',
105
+ 'Turkey Standard Time' => 'Europe/Istanbul',
106
+ 'US Eastern Standard Time' => 'America/Indiana/Indianapolis',
107
+ 'US Mountain Standard Time' => 'America/Phoenix',
108
+ 'UTC' => 'Etc/GMT',
109
+ 'UTC+12' => 'Etc/GMT-12',
110
+ 'UTC-02' => 'Etc/GMT+2',
111
+ 'UTC-11' => 'Etc/GMT+11',
112
+ 'Ulaanbaatar Standard Time' => 'Asia/Ulaanbaatar',
113
+ 'Venezuela Standard Time' => 'America/Caracas',
114
+ 'Vladivostok Standard Time' => 'Asia/Vladivostok',
115
+ 'W. Australia Standard Time' => 'Australia/Perth',
116
+ 'W. Central Africa Standard Time' => 'Africa/Lagos',
117
+ 'W. Europe Standard Time' => 'Europe/Berlin',
118
+ 'West Asia Standard Time' => 'Asia/Tashkent',
119
+ 'West Pacific Standard Time' => 'Pacific/Port_Moresby',
120
+ 'Yakutsk Standard Time' => 'Asia/Yakutsk'
121
+ }.freeze
122
+
123
+ def valid?
124
+ support_classes_defined? && tz
125
+ end
126
+
127
+ def normalized_value
128
+ Icalendar.logger.debug("Plan a - parsing #{value}/#{tzid} as ActiveSupport::TimeWithZone")
129
+ # plan a - use ActiveSupport::TimeWithZone
130
+ Icalendar::Values::Helpers::ActiveSupportTimeWithZoneAdapter.new(nil, tz, value)
131
+ end
132
+
133
+ def normalized_tzid
134
+ [WINDOWS_TO_IANA[tzid]].compact
135
+ end
136
+
137
+ private
138
+
139
+ def tz
140
+ @tz ||= ActiveSupport::TimeZone[normalized_tzid.first || '']
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,44 @@
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::WindowsToIana,
14
+ Icalendar::Offset::ActiveSupportPartial,
15
+ Icalendar::Offset::Null
16
+ ].lazy.map { |klass| klass.new(tzid, value, timezone_store) }.detect(&:valid?)
17
+ end
18
+
19
+ def initialize(tzid, value, timezone_store)
20
+ @tzid = tzid
21
+ @value = value
22
+ @timezone_store = timezone_store
23
+ end
24
+
25
+ def normalized_tzid
26
+ Array(tzid)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :tzid, :value, :timezone_store
32
+
33
+ def support_classes_defined?
34
+ defined?(ActiveSupport::TimeZone) &&
35
+ defined?(Icalendar::Values::Helpers::ActiveSupportTimeWithZoneAdapter)
36
+ end
37
+ end
38
+ end
39
+
40
+ require_relative 'offset/active_support_exact'
41
+ require_relative 'offset/active_support_partial'
42
+ require_relative 'offset/null'
43
+ require_relative 'offset/time_zone_store'
44
+ require_relative 'offset/windows_to_iana'