tzinfo 2.0.2 → 2.0.5

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: 28818edc06842caea3c6a7ee9fc63174498a3fd9f5d065324b3923ba20702ff6
4
- data.tar.gz: 1691bcf9786a63c21777f22326f79d27fd2cd6a19dd6cfa269e00bcc58ca394c
3
+ metadata.gz: 8f5b3120678f9251533f0c044814f666142eb5538412c92c06aa66719251f474
4
+ data.tar.gz: a837074505ff48d553506e1eeb4eac8e3148cc6aa48e996e552d4d9bde1ef614
5
5
  SHA512:
6
- metadata.gz: f070f1ae1e08386d00a0825a035d7b7b598b2c9d47cf822be81c5778bcaca47c5541d602cf676aea6d476b49500b13a667a013b80f6bcd69a5acd9691dbba38a
7
- data.tar.gz: 2e263e61fa7178427178b6109a31e627b899b17d69c41ecfbb9978e98be7a520ba68b148cf903107ff244947b8b8e43b782daef70e103d2e1b81a416663771a7
6
+ metadata.gz: f9f43bcf636bc1c3311cc3d417a951dfeb7cc697ad37add1b6b4bbbb0caa0a7226da508ca5c5521d1cf122254ded7ecd4b1da7f6240121dc311b1706c15119d1
7
+ data.tar.gz: 48314ac805148665c326cc450e2dc96582bb26a2ecc58d97234252c866a162f4f60d2495b6ddaaf3f7b3bd27190d9db452159d58ae57505463a836ce097b5acc
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changes
2
2
 
3
+ ## Version 2.0.5 - 19-Jul-2022
4
+
5
+ * Changed `DateTime` results to always use the proleptic Gregorian calendar.
6
+ This affects `DateTime` results prior to 1582-10-15 and any arithmetic
7
+ performed on the results that would produce a secondary result prior to
8
+ 1582-10-15.
9
+ * Added support for eager loading all the time zone and country data by calling
10
+ either `TZInfo::DataSource#eager_load!` or `TZInfo.eager_load!`. Compatible
11
+ with Ruby On Rails' `eager_load_namespaces`. #129.
12
+ * Ignore the SECURITY file from Arch Linux's tzdata package. #134.
13
+
14
+
15
+ ## Version 2.0.4 - 16-Dec-2020
16
+
17
+ * Fixed an incorrect `InvalidTimezoneIdentifier` exception raised when loading a
18
+ zoneinfo file that includes rules specifying an additional transition to the
19
+ final defined offset (for example, Africa/Casablanca in version 2018e of the
20
+ Time Zone Database). #123.
21
+
22
+
23
+ ## Version 2.0.3 - 8-Nov-2020
24
+
25
+ * Added support for handling "slim" format zoneinfo files that are produced by
26
+ default by zic version 2020b and later. The POSIX-style TZ string is now used
27
+ calculate DST transition times after the final defined transition in the file.
28
+ #120.
29
+ * Fixed `TimeWithOffset#getlocal` returning a `TimeWithOffset` with the
30
+ `timezone_offset` still assigned when called with an offset argument on JRuby
31
+ 9.3.
32
+ * Rubinius is no longer supported.
33
+
34
+
3
35
  ## Version 2.0.2 - 2-Apr-2020
4
36
 
5
37
  * Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114.
@@ -162,6 +194,33 @@
162
194
  `TZInfo::Country.get('US').zone_identifiers` should be used instead.
163
195
 
164
196
 
197
+ ## Version 1.2.10 - 19-Jul-2022
198
+
199
+ * Fixed a relative path traversal bug that could cause arbitrary files to be
200
+ loaded with `require` when used with `RubyDataSource`. Please refer to
201
+ <https://github.com/tzinfo/tzinfo/security/advisories/GHSA-5cm2-9h8c-rvfx> for
202
+ details. CVE-2022-31163.
203
+ * Ignore the SECURITY file from Arch Linux's tzdata package. #134.
204
+
205
+
206
+ ## Version 1.2.9 - 16-Dec-2020
207
+
208
+ * Fixed an incorrect `InvalidTimezoneIdentifier` exception raised when loading a
209
+ zoneinfo file that includes rules specifying an additional transition to the
210
+ final defined offset (for example, Africa/Casablanca in version 2018e of the
211
+ Time Zone Database). #123.
212
+
213
+
214
+ ## Version 1.2.8 - 8-Nov-2020
215
+
216
+ * Added support for handling "slim" format zoneinfo files that are produced by
217
+ default by zic version 2020b and later. The POSIX-style TZ string is now used
218
+ calculate DST transition times after the final defined transition in the file.
219
+ The 64-bit section is now always used regardless of whether Time has support
220
+ for 64-bit times. #120.
221
+ * Rubinius is no longer supported.
222
+
223
+
165
224
  ## Version 1.2.7 - 2-Apr-2020
166
225
 
167
226
  * Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114.
@@ -302,6 +361,52 @@
302
361
  use other `TimezonePeriod` instance methods instead (issue #7655).
303
362
 
304
363
 
364
+ ## Version 0.3.61 (tzdata v2022a) - 19-Jul-2022
365
+
366
+ * Fixed a relative path traversal bug that could cause arbitrary files to be
367
+ loaded with `require` from the Ruby load path. Please refer to
368
+ <https://github.com/tzinfo/tzinfo/security/advisories/GHSA-5cm2-9h8c-rvfx> for
369
+ details. CVE-2022-31163.
370
+ * Updated to tzdata version 2022a
371
+ (<https://mm.icann.org/pipermail/tz-announce/2022-March/000070.html>).
372
+
373
+
374
+ ## Version 0.3.60 (tzdata v2021a) - 6-Feb-2021
375
+
376
+ * Updated to tzdata version 2021a
377
+ (<https://mm.icann.org/pipermail/tz-announce/2021-January/000065.html>).
378
+
379
+
380
+ ## Version 0.3.59 (tzdata v2020e) - 24-Dec-2020
381
+
382
+ * Updated to tzdata version 2020e
383
+ (<https://mm.icann.org/pipermail/tz-announce/2020-December/000063.html>).
384
+
385
+
386
+ ## Version 0.3.58 (tzdata v2020d) - 8-Nov-2020
387
+
388
+ * Updated to tzdata version 2020d
389
+ (<https://mm.icann.org/pipermail/tz-announce/2020-October/000062.html>).
390
+
391
+
392
+ ## Version 0.3.57 (tzdata v2020a) - 17-May-2020
393
+
394
+ * Updated to tzdata version 2020a
395
+ (<https://mm.icann.org/pipermail/tz-announce/2020-April/000058.html>).
396
+
397
+
398
+ ## Version 0.3.56 (tzdata v2019c) - 1-Nov-2019
399
+
400
+ * Updated to tzdata version 2019c
401
+ (<https://mm.icann.org/pipermail/tz-announce/2019-September/000057.html>).
402
+
403
+
404
+ ## Version 0.3.55 (tzdata v2018g) - 27-Oct-2018
405
+
406
+ * Updated to tzdata version 2018g
407
+ (<https://mm.icann.org/pipermail/tz-announce/2018-October/000052.html>).
408
+
409
+
305
410
  ## Version 0.3.54 (tzdata v2018d) - 25-Mar-2018
306
411
 
307
412
  * Updated to tzdata version 2018d
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2020 Philip Ross
1
+ Copyright (c) 2005-2022 Philip Ross
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TZInfo - Ruby Time Zone Library
2
2
 
3
- [![RubyGems](https://img.shields.io/gem/v/tzinfo)](https://rubygems.org/gems/tzinfo) [![Travis CI Build](https://img.shields.io/travis/tzinfo/tzinfo?logo=travis)](https://travis-ci.org/tzinfo/tzinfo) [![AppVeyor Build](https://img.shields.io/appveyor/build/philr/tzinfo?logo=appveyor)](https://ci.appveyor.com/project/philr/tzinfo)
3
+ [![RubyGems](https://img.shields.io/gem/v/tzinfo?logo=rubygems&label=Gem)](https://rubygems.org/gems/tzinfo) [![Tests](https://github.com/tzinfo/tzinfo/workflows/Tests/badge.svg?branch=master&event=push)](https://github.com/tzinfo/tzinfo/actions?query=workflow%3ATests+branch%3Amaster+event%3Apush)
4
4
 
5
5
  [TZInfo](https://tzinfo.github.io) is a Ruby library that provides access to
6
6
  time zone data and allows times to be converted using time zone rules.
@@ -36,7 +36,7 @@ documentation for further details.
36
36
  ## Installation
37
37
 
38
38
  The TZInfo gem can be installed by running `gem install tzinfo` or by adding
39
- to `gem 'tzinfo'` to your `Gemfile` and running `bundle install`.
39
+ `gem 'tzinfo'` to your `Gemfile` and running `bundle install`.
40
40
 
41
41
  To use the Ruby modules as the data source, TZInfo::Data will also need to be
42
42
  installed by running `gem install tzinfo-data` or by adding `gem 'tzinfo-data'`
@@ -368,8 +368,8 @@ claims.
368
368
 
369
369
  ## Compatibility
370
370
 
371
- TZInfo v2.0.0 requires a minimum of Ruby MRI 1.9.3, JRuby 1.7 (in 1.9 mode or
372
- later) or Rubinius 3.
371
+ TZInfo v2.0.0 requires a minimum of Ruby MRI 1.9.3 or JRuby 1.7 (in 1.9 mode or
372
+ later).
373
373
 
374
374
 
375
375
  ## Thread-Safety
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ module TZInfo
5
+ # A set of rules that define when transitions occur in time zones with
6
+ # annually occurring daylight savings time.
7
+ #
8
+ # @private
9
+ class AnnualRules #:nodoc:
10
+ # @return [TimezoneOffset] the standard offset that applies when daylight
11
+ # savings time is not in force.
12
+ attr_reader :std_offset
13
+
14
+ # @return [TimezoneOffset] the offset that applies when daylight savings
15
+ # time is in force.
16
+ attr_reader :dst_offset
17
+
18
+ # @return [TransitionRule] the rule that determines when daylight savings
19
+ # time starts.
20
+ attr_reader :dst_start_rule
21
+
22
+ # @return [TransitionRule] the rule that determines when daylight savings
23
+ # time ends.
24
+ attr_reader :dst_end_rule
25
+
26
+ # Initializes a new {AnnualRules} instance.
27
+ #
28
+ # @param std_offset [TimezoneOffset] the standard offset that applies when
29
+ # daylight savings time is not in force.
30
+ # @param dst_offset [TimezoneOffset] the offset that applies when daylight
31
+ # savings time is in force.
32
+ # @param dst_start_rule [TransitionRule] the rule that determines when
33
+ # daylight savings time starts.
34
+ # @param dst_end_rule [TransitionRule] the rule that determines when daylight
35
+ # savings time ends.
36
+ def initialize(std_offset, dst_offset, dst_start_rule, dst_end_rule)
37
+ @std_offset = std_offset
38
+ @dst_offset = dst_offset
39
+ @dst_start_rule = dst_start_rule
40
+ @dst_end_rule = dst_end_rule
41
+ end
42
+
43
+ # Returns the transitions between standard and daylight savings time for a
44
+ # given year. The results are ordered by time of occurrence (earliest to
45
+ # latest).
46
+ #
47
+ # @param year [Integer] the year to calculate transitions for.
48
+ # @return [Array<TimezoneTransition>] the transitions for the year.
49
+ def transitions(year)
50
+ start_dst = apply_rule(@dst_start_rule, @std_offset, @dst_offset, year)
51
+ end_dst = apply_rule(@dst_end_rule, @dst_offset, @std_offset, year)
52
+
53
+ end_dst.timestamp_value < start_dst.timestamp_value ? [end_dst, start_dst] : [start_dst, end_dst]
54
+ end
55
+
56
+ private
57
+
58
+ # Applies a given rule between offsets on a year.
59
+ #
60
+ # @param rule [TransitionRule] the rule to apply.
61
+ # @param from_offset [TimezoneOffset] the offset the rule transitions from.
62
+ # @param to_offset [TimezoneOffset] the offset the rule transitions to.
63
+ # @param year [Integer] the year when the transition occurs.
64
+ # @return [TimezoneTransition] the transition determined by the rule.
65
+ def apply_rule(rule, from_offset, to_offset, year)
66
+ at = rule.at(from_offset, year)
67
+ TimezoneTransition.new(to_offset, from_offset, at.value)
68
+ end
69
+ end
70
+ private_constant :AnnualRules
71
+ end
@@ -247,6 +247,17 @@ module TZInfo
247
247
  raise_invalid_data_source('country_codes')
248
248
  end
249
249
 
250
+ # Loads all timezone and country data into memory.
251
+ #
252
+ # This may be desirable in production environments to improve copy-on-write
253
+ # performance and to avoid flushing the constant cache every time a new
254
+ # timezone or country is loaded from {DataSources::RubyDataSource}.
255
+ def eager_load!
256
+ timezone_identifiers.each {|identifier| load_timezone_info(identifier) }
257
+ country_codes.each {|code| load_country_info(code) }
258
+ nil
259
+ end
260
+
250
261
  # @return [String] a description of the {DataSource}.
251
262
  def to_s
252
263
  "Default DataSource"
@@ -0,0 +1,181 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'strscan'
5
+
6
+ module TZInfo
7
+ # Use send as a workaround for erroneous 'wrong number of arguments' errors
8
+ # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114.
9
+ send(:using, UntaintExt) if TZInfo.const_defined?(:UntaintExt)
10
+
11
+ module DataSources
12
+ # An {InvalidPosixTimeZone} exception is raised if an invalid POSIX-style
13
+ # time zone string is encountered.
14
+ #
15
+ # @private
16
+ class InvalidPosixTimeZone < StandardError #:nodoc:
17
+ end
18
+ private_constant :InvalidPosixTimeZone
19
+
20
+ # A parser for POSIX-style TZ strings used in zoneinfo files and specified
21
+ # by tzfile.5 and tzset.3.
22
+ #
23
+ # @private
24
+ class PosixTimeZoneParser #:nodoc:
25
+ # Initializes a new {PosixTimeZoneParser}.
26
+ #
27
+ # @param string_deduper [StringDeduper] a {StringDeduper} instance to use
28
+ # to dedupe abbreviations.
29
+ def initialize(string_deduper)
30
+ @string_deduper = string_deduper
31
+ end
32
+
33
+ # Parses a POSIX-style TZ string.
34
+ #
35
+ # @param tz_string [String] the string to parse.
36
+ # @return [Object] either a {TimezoneOffset} for a constantly applied
37
+ # offset or an {AnnualRules} instance representing the rules.
38
+ # @raise [InvalidPosixTimeZone] if `tz_string` is not a `String`.
39
+ # @raise [InvalidPosixTimeZone] if `tz_string` is is not valid.
40
+ def parse(tz_string)
41
+ raise InvalidPosixTimeZone unless tz_string.kind_of?(String)
42
+ return nil if tz_string.empty?
43
+
44
+ s = StringScanner.new(tz_string)
45
+ check_scan(s, /([^-+,\d<][^-+,\d]*) | <([^>]+)>/x)
46
+ std_abbrev = @string_deduper.dedupe((s[1] || s[2]).untaint)
47
+ check_scan(s, /([-+]?\d+)(?::(\d+)(?::(\d+))?)?/)
48
+ std_offset = get_offset_from_hms(s[1], s[2], s[3])
49
+
50
+ if s.scan(/([^-+,\d<][^-+,\d]*) | <([^>]+)>/x)
51
+ dst_abbrev = @string_deduper.dedupe((s[1] || s[2]).untaint)
52
+
53
+ if s.scan(/([-+]?\d+)(?::(\d+)(?::(\d+))?)?/)
54
+ dst_offset = get_offset_from_hms(s[1], s[2], s[3])
55
+ else
56
+ # POSIX is negative for ahead of UTC.
57
+ dst_offset = std_offset - 3600
58
+ end
59
+
60
+ dst_difference = std_offset - dst_offset
61
+
62
+ start_rule = parse_rule(s, 'start')
63
+ end_rule = parse_rule(s, 'end')
64
+
65
+ raise InvalidPosixTimeZone, "Expected the end of a POSIX-style time zone string but found '#{s.rest}'." if s.rest?
66
+
67
+ if start_rule.is_always_first_day_of_year? && start_rule.transition_at == 0 &&
68
+ end_rule.is_always_last_day_of_year? && end_rule.transition_at == 86400 + dst_difference
69
+ # Constant daylight savings time.
70
+ # POSIX is negative for ahead of UTC.
71
+ TimezoneOffset.new(-std_offset, dst_difference, dst_abbrev)
72
+ else
73
+ AnnualRules.new(
74
+ TimezoneOffset.new(-std_offset, 0, std_abbrev),
75
+ TimezoneOffset.new(-std_offset, dst_difference, dst_abbrev),
76
+ start_rule,
77
+ end_rule)
78
+ end
79
+ elsif !s.rest?
80
+ # Constant standard time.
81
+ # POSIX is negative for ahead of UTC.
82
+ TimezoneOffset.new(-std_offset, 0, std_abbrev)
83
+ else
84
+ raise InvalidPosixTimeZone, "Expected the end of a POSIX-style time zone string but found '#{s.rest}'."
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ # Parses a rule.
91
+ #
92
+ # @param s [StringScanner] the `StringScanner` to read the rule from.
93
+ # @param type [String] the type of rule (either `'start'` or `'end'`).
94
+ # @raise [InvalidPosixTimeZone] if the rule is not valid.
95
+ # @return [TransitionRule] the parsed rule.
96
+ def parse_rule(s, type)
97
+ check_scan(s, /,(?: (?: J(\d+) ) | (\d+) | (?: M(\d+)\.(\d)\.(\d) ) )/x)
98
+ julian_day_of_year = s[1]
99
+ absolute_day_of_year = s[2]
100
+ month = s[3]
101
+ week = s[4]
102
+ day_of_week = s[5]
103
+
104
+ if s.scan(/\//)
105
+ check_scan(s, /([-+]?\d+)(?::(\d+)(?::(\d+))?)?/)
106
+ transition_at = get_seconds_after_midnight_from_hms(s[1], s[2], s[3])
107
+ else
108
+ transition_at = 7200
109
+ end
110
+
111
+ begin
112
+ if julian_day_of_year
113
+ JulianDayOfYearTransitionRule.new(julian_day_of_year.to_i, transition_at)
114
+ elsif absolute_day_of_year
115
+ AbsoluteDayOfYearTransitionRule.new(absolute_day_of_year.to_i, transition_at)
116
+ elsif week == '5'
117
+ LastDayOfMonthTransitionRule.new(month.to_i, day_of_week.to_i, transition_at)
118
+ else
119
+ DayOfMonthTransitionRule.new(month.to_i, week.to_i, day_of_week.to_i, transition_at)
120
+ end
121
+ rescue ArgumentError => e
122
+ raise InvalidPosixTimeZone, "Invalid #{type} rule in POSIX-style time zone string: #{e}"
123
+ end
124
+ end
125
+
126
+ # Returns an offset in seconds from hh:mm:ss values. The value can be
127
+ # negative. -02:33:12 would represent 2 hours, 33 minutes and 12 seconds
128
+ # ahead of UTC.
129
+ #
130
+ # @param h [String] the hours.
131
+ # @param m [String] the minutes.
132
+ # @param s [String] the seconds.
133
+ # @return [Integer] the offset.
134
+ # @raise [InvalidPosixTimeZone] if the mm and ss values are greater than
135
+ # 59.
136
+ def get_offset_from_hms(h, m, s)
137
+ h = h.to_i
138
+ m = m.to_i
139
+ s = s.to_i
140
+ raise InvalidPosixTimeZone, "Invalid minute #{m} in offset for POSIX-style time zone string." if m > 59
141
+ raise InvalidPosixTimeZone, "Invalid second #{s} in offset for POSIX-style time zone string." if s > 59
142
+ magnitude = (h.abs * 60 + m) * 60 + s
143
+ h < 0 ? -magnitude : magnitude
144
+ end
145
+
146
+ # Returns the seconds from midnight from hh:mm:ss values. Hours can exceed
147
+ # 24 for a time on the following day. Hours can be negative to subtract
148
+ # hours from midnight on the given day. -02:33:12 represents 22:33:12 on
149
+ # the prior day.
150
+ #
151
+ # @param h [String] the hour.
152
+ # @param m [String] the minutes past the hour.
153
+ # @param s [String] the seconds past the minute.
154
+ # @return [Integer] the number of seconds after midnight.
155
+ # @raise [InvalidPosixTimeZone] if the mm and ss values are greater than
156
+ # 59.
157
+ def get_seconds_after_midnight_from_hms(h, m, s)
158
+ h = h.to_i
159
+ m = m.to_i
160
+ s = s.to_i
161
+ raise InvalidPosixTimeZone, "Invalid minute #{m} in time for POSIX-style time zone string." if m > 59
162
+ raise InvalidPosixTimeZone, "Invalid second #{s} in time for POSIX-style time zone string." if s > 59
163
+ (h * 3600) + m * 60 + s
164
+ end
165
+
166
+ # Scans for a pattern and raises an exception if the pattern does not
167
+ # match the input.
168
+ #
169
+ # @param s [StringScanner] the `StringScanner` to scan.
170
+ # @param pattern [Regexp] the pattern to match.
171
+ # @return [String] the result of the scan.
172
+ # @raise [InvalidPosixTimeZone] if the pattern does not match the input.
173
+ def check_scan(s, pattern)
174
+ result = s.scan(pattern)
175
+ raise InvalidPosixTimeZone, "Expected '#{s.rest}' to match #{pattern} in POSIX-style time zone string." unless result
176
+ result
177
+ end
178
+ end
179
+ private_constant :PosixTimeZoneParser
180
+ end
181
+ end
@@ -116,14 +116,14 @@ module TZInfo
116
116
  # @param identifier [Array<string>] the component parts of a time zone
117
117
  # identifier (split on /). This must have already been validated.
118
118
  def require_definition(identifier)
119
- require_data(*(['definitions'] + identifier))
119
+ require_data('definitions', *identifier)
120
120
  end
121
121
 
122
122
  # Requires an index by its name.
123
123
  #
124
124
  # @param name [String] an index name.
125
125
  def require_index(name)
126
- require_data(*['indexes', name])
126
+ require_data('indexes', name)
127
127
  end
128
128
 
129
129
  # Requires a file from tzinfo/data.
@@ -78,6 +78,30 @@ module TZInfo
78
78
  DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH = ['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'].freeze
79
79
  private_constant :DEFAULT_ALTERNATE_ISO3166_TAB_SEARCH_PATH
80
80
 
81
+ # Files and directories in the top level zoneinfo directory that will be
82
+ # excluded from the list of available time zones:
83
+ #
84
+ # - +VERSION is included on Mac OS X.
85
+ # - leapseconds is a list of leap seconds.
86
+ # - localtime is the current local timezone (may be a link).
87
+ # - posix, posixrules and right are directories containing other
88
+ # versions of the zoneinfo files.
89
+ # - SECURITY is included in the Arch Linux tzdata package.
90
+ # - src is a directory containing the tzdata source included on Solaris.
91
+ # - timeconfig is a symlink included on Slackware.
92
+ EXCLUDED_FILENAMES = [
93
+ '+VERSION',
94
+ 'leapseconds',
95
+ 'localtime',
96
+ 'posix',
97
+ 'posixrules',
98
+ 'right',
99
+ 'SECURITY',
100
+ 'src',
101
+ 'timeconfig'
102
+ ].freeze
103
+ private_constant :EXCLUDED_FILENAMES
104
+
81
105
  # Paths to be checked to find the system zoneinfo directory.
82
106
  #
83
107
  # @private
@@ -237,7 +261,10 @@ module TZInfo
237
261
  @timezone_identifiers = load_timezone_identifiers.freeze
238
262
  @countries = load_countries(iso3166_tab_path, zone_tab_path).freeze
239
263
  @country_codes = @countries.keys.sort!.freeze
240
- @zoneinfo_reader = ZoneinfoReader.new(ConcurrentStringDeduper.new)
264
+
265
+ string_deduper = ConcurrentStringDeduper.new
266
+ posix_tz_parser = PosixTimeZoneParser.new(string_deduper)
267
+ @zoneinfo_reader = ZoneinfoReader.new(posix_tz_parser, string_deduper)
241
268
  end
242
269
 
243
270
  # Returns a frozen `Array` of all the available time zone identifiers. The
@@ -391,15 +418,7 @@ module TZInfo
391
418
  def load_timezone_identifiers
392
419
  index = []
393
420
 
394
- # Ignoring particular files:
395
- # +VERSION is included on Mac OS X.
396
- # leapseconds is a list of leap seconds.
397
- # localtime is the current local timezone (may be a link).
398
- # posix, posixrules and right are directories containing other versions of the zoneinfo files.
399
- # src is a directory containing the tzdata source included on Solaris.
400
- # timeconfig is a symlink included on Slackware.
401
-
402
- enum_timezones([], ['+VERSION', 'leapseconds', 'localtime', 'posix', 'posixrules', 'right', 'src', 'timeconfig']) do |identifier|
421
+ enum_timezones([], EXCLUDED_FILENAMES) do |identifier|
403
422
  index << identifier.join('/').freeze
404
423
  end
405
424