tzinfo 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of tzinfo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGES.md +122 -1
- data/LICENSE +1 -1
- data/Rakefile +4 -1
- data/lib/tzinfo/timezone.rb +55 -23
- data/lib/tzinfo/timezone_offset.rb +4 -0
- data/lib/tzinfo/timezone_period.rb +18 -1
- data/lib/tzinfo/timezone_proxy.rb +29 -0
- data/lib/tzinfo/zoneinfo_data_source.rb +4 -4
- data/lib/tzinfo/zoneinfo_timezone_info.rb +107 -58
- data/test/tc_country.rb +4 -4
- data/test/tc_ruby_data_source.rb +4 -4
- data/test/tc_timezone.rb +32 -16
- data/test/tc_timezone_proxy.rb +39 -25
- data/test/tc_zoneinfo_data_source.rb +85 -14
- data/test/tc_zoneinfo_timezone_info.rb +331 -17
- data/test/test_utils.rb +3 -1
- data/tzinfo.gemspec +1 -1
- metadata +10 -10
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be3c32bd74920808d67de39efaf3a73c6e8906d9
|
4
|
+
data.tar.gz: f553215128b1b18c614252434e45d9d4e1c2dc53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af62bf6235210846b42517a1151a20e2e5c376005c3aa9b90515ed97c729d39e0b9fd2fd743708acfc6bb9fae55bf68a69c7408168f942d4b256feed02016d0a
|
7
|
+
data.tar.gz: b8073737407948dc494a2d9a4215044ffeae2b7ec91e9047e6fdf0b328af021e371f4e21f51d5dc798c232c80d23f2b11ee9bc9cc5d6a3c34cd806c56933c5ba
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
Version 1.2.3 - 25-Mar-2017
|
2
|
+
---------------------------
|
3
|
+
|
4
|
+
* Reduce the number of String objects allocated when loading zoneinfo files.
|
5
|
+
#54.
|
6
|
+
* Make Timezone#friendly_identifier compatible with frozen string literals.
|
7
|
+
* Improve the algorithm for deriving the utc_offset from zoneinfo files. This
|
8
|
+
now correctly handles Pacific/Apia switching from one side of the
|
9
|
+
International Date Line to the other whilst observing daylight savings time.
|
10
|
+
#66.
|
11
|
+
* Fix an UnknownTimezone exception when calling transitions_up_to or
|
12
|
+
offsets_up_to on a TimezoneProxy instance obtained from Timezone.get_proxy.
|
13
|
+
* Allow the Factory zone to be obtained from the Zoneinfo data source.
|
14
|
+
* Ignore the /usr/share/zoneinfo/timeconfig symlink included in Slackware
|
15
|
+
distributions. #64.
|
16
|
+
* Fix Timezone#strftime handling of %Z expansion when %Z is prefixed with more
|
17
|
+
than one percent. #31.
|
18
|
+
* Support expansion of %z, %:z, %::z and %:::z to the UTC offset of the time
|
19
|
+
zone in Timezone#strftime. #31 and #67.
|
20
|
+
|
21
|
+
|
1
22
|
Version 1.2.2 - 8-Aug-2014
|
2
23
|
--------------------------
|
3
24
|
|
@@ -92,6 +113,106 @@ Version 1.0.0 - 2-Jun-2013
|
|
92
113
|
use other TimezonePeriod instance methods instead (issue #7655).
|
93
114
|
|
94
115
|
|
116
|
+
Version 0.3.53 (tzdata v2017b) - 23-Mar-2017
|
117
|
+
--------------------------------------------
|
118
|
+
|
119
|
+
* Updated to tzdata version 2017b
|
120
|
+
(https://mm.icann.org/pipermail/tz-announce/2017-March/000046.html).
|
121
|
+
|
122
|
+
|
123
|
+
Version 0.3.52 (tzdata v2016h) - 28-Oct-2016
|
124
|
+
--------------------------------------------
|
125
|
+
|
126
|
+
* Updated to tzdata version 2016h
|
127
|
+
(https://mm.icann.org/pipermail/tz-announce/2016-October/000042.html).
|
128
|
+
|
129
|
+
|
130
|
+
Version 0.3.51 (tzdata v2016f) - 5-Jul-2016
|
131
|
+
-------------------------------------------
|
132
|
+
|
133
|
+
* Updated to tzdata version 2016f
|
134
|
+
(https://mm.icann.org/pipermail/tz-announce/2016-July/000040.html).
|
135
|
+
|
136
|
+
|
137
|
+
Version 0.3.50 (tzdata v2016e) - 14-Jun-2016
|
138
|
+
--------------------------------------------
|
139
|
+
|
140
|
+
* Updated to tzdata version 2016e
|
141
|
+
(https://mm.icann.org/pipermail/tz-announce/2016-June/000039.html).
|
142
|
+
|
143
|
+
|
144
|
+
Version 0.3.49 (tzdata v2016d) - 18-Apr-2016
|
145
|
+
--------------------------------------------
|
146
|
+
|
147
|
+
* Updated to tzdata version 2016d
|
148
|
+
(https://mm.icann.org/pipermail/tz-announce/2016-April/000038.html).
|
149
|
+
|
150
|
+
|
151
|
+
Version 0.3.48 (tzdata v2016c) - 23-Mar-2016
|
152
|
+
--------------------------------------------
|
153
|
+
|
154
|
+
* Updated to tzdata version 2016c
|
155
|
+
(https://mm.icann.org/pipermail/tz-announce/2016-March/000037.html).
|
156
|
+
|
157
|
+
|
158
|
+
Version 0.3.47 (tzdata v2016b) - 15-Mar-2016
|
159
|
+
--------------------------------------------
|
160
|
+
|
161
|
+
* Updated to tzdata version 2016b
|
162
|
+
(https://mm.icann.org/pipermail/tz-announce/2016-March/000036.html).
|
163
|
+
|
164
|
+
|
165
|
+
Version 0.3.46 (tzdata v2015g) - 2-Dec-2015
|
166
|
+
-------------------------------------------
|
167
|
+
|
168
|
+
* From version 2015e, the IANA time zone database uses non-ASCII characters in
|
169
|
+
country names. Backport the encoding handling from TZInfo::Data to allow
|
170
|
+
TZInfo 0.3.x to support Ruby 1.9 (which would otherwise fail with an invalid
|
171
|
+
byte sequence error when loading the countries index). Resolves #41.
|
172
|
+
|
173
|
+
|
174
|
+
Version 0.3.45 (tzdata v2015g) - 3-Oct-2015
|
175
|
+
-------------------------------------------
|
176
|
+
|
177
|
+
* Updated to tzdata version 2015g
|
178
|
+
(http://mm.icann.org/pipermail/tz-announce/2015-October/000034.html).
|
179
|
+
|
180
|
+
|
181
|
+
Version 0.3.44 (tzdata v2015d) - 24-Apr-2015
|
182
|
+
--------------------------------------------
|
183
|
+
|
184
|
+
* Updated to tzdata version 2015d
|
185
|
+
(http://mm.icann.org/pipermail/tz-announce/2015-April/000031.html).
|
186
|
+
|
187
|
+
|
188
|
+
Version 0.3.43 (tzdata v2015a) - 31-Jan-2015
|
189
|
+
--------------------------------------------
|
190
|
+
|
191
|
+
* Updated to tzdata version 2015a
|
192
|
+
(http://mm.icann.org/pipermail/tz-announce/2015-January/000028.html).
|
193
|
+
|
194
|
+
|
195
|
+
Version 0.3.42 (tzdata v2014i) - 23-Oct-2014
|
196
|
+
--------------------------------------------
|
197
|
+
|
198
|
+
* Updated to tzdata version 2014i
|
199
|
+
(http://mm.icann.org/pipermail/tz-announce/2014-October/000026.html).
|
200
|
+
|
201
|
+
|
202
|
+
Version 0.3.41 (tzdata v2014f) - 8-Aug-2014
|
203
|
+
-------------------------------------------
|
204
|
+
|
205
|
+
* Updated to tzdata version 2014f
|
206
|
+
(http://mm.icann.org/pipermail/tz-announce/2014-August/000023.html).
|
207
|
+
|
208
|
+
|
209
|
+
Version 0.3.40 (tzdata v2014e) - 10-Jul-2014
|
210
|
+
--------------------------------------------
|
211
|
+
|
212
|
+
* Updated to tzdata version 2014e
|
213
|
+
(http://mm.icann.org/pipermail/tz-announce/2014-June/000022.html).
|
214
|
+
|
215
|
+
|
95
216
|
Version 0.3.39 (tzdata v2014a) - 9-Mar-2014
|
96
217
|
-------------------------------------------
|
97
218
|
|
@@ -177,7 +298,7 @@ Version 0.3.29 (tzdata v2011h) - 27-Jun-2011
|
|
177
298
|
|
178
299
|
|
179
300
|
Version 0.3.28 (tzdata v2011g) - 13-Jun-2011
|
180
|
-
|
301
|
+
---------------------------------------------
|
181
302
|
|
182
303
|
* Add support for Ruby 1.9.3 (trunk revision 31668 and later). Thanks to
|
183
304
|
Aaron Patterson for reporting the problems running on the new version.
|
data/LICENSE
CHANGED
data/Rakefile
CHANGED
@@ -21,7 +21,10 @@ class TZInfoPackageTask < Gem::PackageTask
|
|
21
21
|
private :orig_sh
|
22
22
|
|
23
23
|
def sh(*cmd, &block)
|
24
|
-
if cmd
|
24
|
+
if cmd[0] == '__tar_with_owner__' && cmd[1] =~ /\A-?[zjcvf]+\z/
|
25
|
+
opts = cmd[1]
|
26
|
+
cmd = ['tar', 'c', '--owner', '0', '--group', '0', "#{opts.start_with?('-') ? '' : '-'}#{opts.gsub('c', '')}"] + cmd.drop(2)
|
27
|
+
elsif cmd.first =~ /\A__tar_with_owner__ -?([zjcvf]+)(.*)\z/
|
25
28
|
opts = $1
|
26
29
|
args = $2
|
27
30
|
cmd[0] = "tar c --owner 0 --group 0 -#{opts.gsub('c', '')}#{args}"
|
data/lib/tzinfo/timezone.rb
CHANGED
@@ -236,13 +236,9 @@ module TZInfo
|
|
236
236
|
elsif parts.length == 1
|
237
237
|
parts[0]
|
238
238
|
else
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
result = parts[0] + ' - '
|
243
|
-
end
|
244
|
-
|
245
|
-
parts[1, parts.length - 1].reverse_each {|part|
|
239
|
+
prefix = skip_first_part ? nil : "#{parts[0]} - "
|
240
|
+
|
241
|
+
parts = parts.drop(1).map do |part|
|
246
242
|
part.gsub!(/_/, ' ')
|
247
243
|
|
248
244
|
if part.index(/[a-z]/)
|
@@ -254,13 +250,11 @@ module TZInfo
|
|
254
250
|
# Missing an apostrophe if two consecutive upper case characters.
|
255
251
|
part.gsub!(/([A-Z])([A-Z])/, '\1\'\2')
|
256
252
|
end
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
result.slice!(result.length - 2, 2)
|
263
|
-
result
|
253
|
+
|
254
|
+
part
|
255
|
+
end
|
256
|
+
|
257
|
+
"#{prefix}#{parts.reverse.join(', ')}"
|
264
258
|
end
|
265
259
|
end
|
266
260
|
|
@@ -559,22 +553,60 @@ module TZInfo
|
|
559
553
|
|
560
554
|
alias :current_time_and_period :current_period_and_time
|
561
555
|
|
562
|
-
# Converts a time in UTC to local time and returns it as a string
|
563
|
-
#
|
564
|
-
#
|
565
|
-
#
|
556
|
+
# Converts a time in UTC to local time and returns it as a string according
|
557
|
+
# to the given format.
|
558
|
+
#
|
559
|
+
# The formatting is identical to Time.strftime and DateTime.strftime, except
|
560
|
+
# %Z and %z are replaced with the timezone abbreviation (for example, EST or
|
561
|
+
# EDT) and offset for the specified Timezone and time.
|
562
|
+
#
|
563
|
+
# The offset can be formatted as follows:
|
564
|
+
#
|
565
|
+
# - %z - hour and minute (e.g. +0500)
|
566
|
+
# - %:z - hour and minute separated with a colon (e.g. +05:00)
|
567
|
+
# - %::z - hour minute and second separated with colons (e.g. +05:00:00)
|
568
|
+
# - %:::z - hour only (e.g. +05)
|
569
|
+
#
|
570
|
+
# Timezone#strftime currently handles the replacement of %z. From TZInfo
|
571
|
+
# version 2.0.0, %z will be passed to Time#strftime and DateTime#strftime
|
572
|
+
# instead. Some of the formatting options may cease to be available
|
573
|
+
# depending on the version of Ruby in use (for example, %:::z is only
|
574
|
+
# supported by Time#strftime from MRI version 2.0.0 onwards.)
|
566
575
|
def strftime(format, utc = Time.now.utc)
|
567
576
|
period = period_for_utc(utc)
|
568
577
|
local = period.to_local(utc)
|
569
578
|
local = Time.at(local).utc unless local.kind_of?(Time) || local.kind_of?(DateTime)
|
570
579
|
abbreviation = period.abbreviation.to_s.gsub(/%/, '%%')
|
571
580
|
|
572
|
-
format = format.gsub(
|
573
|
-
if $1
|
574
|
-
#
|
575
|
-
|
576
|
-
|
581
|
+
format = format.gsub(/%(%*)(Z|:*z)/) do
|
582
|
+
if $1.length.odd?
|
583
|
+
# Escaped literal percent or series of percents. Pass on to strftime.
|
584
|
+
"#$1%#$2"
|
585
|
+
elsif $2 == "Z"
|
577
586
|
"#$1#{abbreviation}"
|
587
|
+
else
|
588
|
+
m, s = period.utc_total_offset.divmod(60)
|
589
|
+
h, m = m.divmod(60)
|
590
|
+
case $2.length
|
591
|
+
when 1
|
592
|
+
"#$1#{'%+03d%02d' % [h,m]}"
|
593
|
+
when 2
|
594
|
+
"#$1#{'%+03d:%02d' % [h,m]}"
|
595
|
+
when 3
|
596
|
+
"#$1#{'%+03d:%02d:%02d' % [h,m,s]}"
|
597
|
+
when 4
|
598
|
+
"#$1#{'%+03d' % [h]}"
|
599
|
+
else # more than 3 colons - not a valid option
|
600
|
+
# Passing the invalid format string through to Time#strftime or
|
601
|
+
# DateTime#strtime would normally result in it being returned in the
|
602
|
+
# result. However, with Ruby 1.8.7 on Windows (as tested with Ruby
|
603
|
+
# 1.8.7-p374 from http://rubyinstaller.org/downloads/archives), this
|
604
|
+
# causes Time#strftime to always return an empty string (e.g.
|
605
|
+
# Time.now.strftime('a %::::z b') returns '').
|
606
|
+
#
|
607
|
+
# Escape the percent to force it to be evaluated as a literal.
|
608
|
+
"#$1%%#$2"
|
609
|
+
end
|
578
610
|
end
|
579
611
|
end
|
580
612
|
|
@@ -34,6 +34,8 @@ module TZInfo
|
|
34
34
|
|
35
35
|
# Converts a UTC Time, DateTime or integer timestamp to local time, based on
|
36
36
|
# the offset of this period.
|
37
|
+
#
|
38
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
37
39
|
def to_local(utc)
|
38
40
|
TimeOrDateTime.wrap(utc) {|wrapped|
|
39
41
|
wrapped + @utc_total_offset
|
@@ -42,6 +44,8 @@ module TZInfo
|
|
42
44
|
|
43
45
|
# Converts a local Time, DateTime or integer timestamp to UTC, based on the
|
44
46
|
# offset of this period.
|
47
|
+
#
|
48
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
45
49
|
def to_utc(local)
|
46
50
|
TimeOrDateTime.wrap(local) {|wrapped|
|
47
51
|
wrapped - @utc_total_offset
|
@@ -126,45 +126,62 @@ module TZInfo
|
|
126
126
|
end
|
127
127
|
|
128
128
|
# true if this period is valid for the given UTC DateTime; otherwise false.
|
129
|
+
#
|
130
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
129
131
|
def valid_for_utc?(utc)
|
130
132
|
utc_after_start?(utc) && utc_before_end?(utc)
|
131
133
|
end
|
132
134
|
|
133
135
|
# true if the given UTC DateTime is after the start of the period
|
134
136
|
# (inclusive); otherwise false.
|
137
|
+
#
|
138
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
135
139
|
def utc_after_start?(utc)
|
136
140
|
!@start_transition || @start_transition.at <= utc
|
137
141
|
end
|
138
142
|
|
139
143
|
# true if the given UTC DateTime is before the end of the period
|
140
144
|
# (exclusive); otherwise false.
|
145
|
+
#
|
146
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
141
147
|
def utc_before_end?(utc)
|
142
148
|
!@end_transition || @end_transition.at > utc
|
143
149
|
end
|
144
150
|
|
145
|
-
# true if this period is valid for the given local DateTime; otherwise
|
151
|
+
# true if this period is valid for the given local DateTime; otherwise
|
152
|
+
# false.
|
153
|
+
#
|
154
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
146
155
|
def valid_for_local?(local)
|
147
156
|
local_after_start?(local) && local_before_end?(local)
|
148
157
|
end
|
149
158
|
|
150
159
|
# true if the given local DateTime is after the start of the period
|
151
160
|
# (inclusive); otherwise false.
|
161
|
+
#
|
162
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
152
163
|
def local_after_start?(local)
|
153
164
|
!@start_transition || @start_transition.local_start_at <= local
|
154
165
|
end
|
155
166
|
|
156
167
|
# true if the given local DateTime is before the end of the period
|
157
168
|
# (exclusive); otherwise false.
|
169
|
+
#
|
170
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
158
171
|
def local_before_end?(local)
|
159
172
|
!@end_transition || @end_transition.local_end_at > local
|
160
173
|
end
|
161
174
|
|
162
175
|
# Converts a UTC DateTime to local time based on the offset of this period.
|
176
|
+
#
|
177
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
163
178
|
def to_local(utc)
|
164
179
|
@offset.to_local(utc)
|
165
180
|
end
|
166
181
|
|
167
182
|
# Converts a local DateTime to UTC based on the offset of this period.
|
183
|
+
#
|
184
|
+
# Deprecation warning: this method will be removed in TZInfo version 2.0.0.
|
168
185
|
def to_utc(local)
|
169
186
|
@offset.to_utc(local)
|
170
187
|
end
|
@@ -38,6 +38,35 @@ module TZInfo
|
|
38
38
|
real_timezone.periods_for_local(local)
|
39
39
|
end
|
40
40
|
|
41
|
+
# Returns an Array of TimezoneTransition instances representing the times
|
42
|
+
# where the UTC offset of the timezone changes.
|
43
|
+
#
|
44
|
+
# Transitions are returned up to a given date and time up to a given date
|
45
|
+
# and time (to).
|
46
|
+
#
|
47
|
+
# A from date and time may also be supplied using the from parameter. If
|
48
|
+
# from is not nil, only transitions from that date and time onwards will be
|
49
|
+
# returned.
|
50
|
+
#
|
51
|
+
# Comparisons with to are exclusive. Comparisons with from are inclusive.
|
52
|
+
# If a transition falls precisely on to, it will be excluded. If a
|
53
|
+
# transition falls on from, it will be included.
|
54
|
+
#
|
55
|
+
# Transitions returned are ordered by when they occur, from earliest to
|
56
|
+
# latest.
|
57
|
+
#
|
58
|
+
# to and from can be specified using either a Time, DateTime, Time or
|
59
|
+
# Timestamp.
|
60
|
+
#
|
61
|
+
# If from is specified and to is not greater than from, then an
|
62
|
+
# ArgumentError exception is raised.
|
63
|
+
#
|
64
|
+
# ArgumentError is raised if to is nil or of either to or from are
|
65
|
+
# Timestamps with unspecified offsets.
|
66
|
+
def transitions_up_to(to, from = nil)
|
67
|
+
real_timezone.transitions_up_to(to, from)
|
68
|
+
end
|
69
|
+
|
41
70
|
# Returns the canonical zone for this Timezone.
|
42
71
|
def canonical_zone
|
43
72
|
real_timezone.canonical_zone
|
@@ -349,9 +349,9 @@ module TZInfo
|
|
349
349
|
# localtime current local timezone (may be a link).
|
350
350
|
# posix, posixrules and right are directories containing other versions of the zoneinfo files.
|
351
351
|
# src is a directory containing the tzdata source included on Solaris.
|
352
|
-
#
|
352
|
+
# timeconfig is a symlink included on Slackware.
|
353
353
|
|
354
|
-
enum_timezones(nil, ['+VERSION', 'localtime', 'posix', 'posixrules', 'right', 'src', '
|
354
|
+
enum_timezones(nil, ['+VERSION', 'localtime', 'posix', 'posixrules', 'right', 'src', 'timeconfig']) do |identifier|
|
355
355
|
index << identifier
|
356
356
|
end
|
357
357
|
|
@@ -432,7 +432,7 @@ module TZInfo
|
|
432
432
|
|
433
433
|
file_is_5_column = true if column5
|
434
434
|
|
435
|
-
zone_tab << [codes.split(','), zone_identifier, latitude, longitude, column4, column5]
|
435
|
+
zone_tab << [codes.split(','.freeze), zone_identifier, latitude, longitude, column4, column5]
|
436
436
|
end
|
437
437
|
end
|
438
438
|
end
|
@@ -480,7 +480,7 @@ module TZInfo
|
|
480
480
|
def dms_to_rational(sign, degrees, minutes, seconds = nil)
|
481
481
|
result = degrees.to_i + Rational(minutes.to_i, 60)
|
482
482
|
result += Rational(seconds.to_i, 3600) if seconds
|
483
|
-
result = -result if sign == '-'
|
483
|
+
result = -result if sign == '-'.freeze
|
484
484
|
result
|
485
485
|
end
|
486
486
|
end
|
@@ -56,39 +56,109 @@ module TZInfo
|
|
56
56
|
result
|
57
57
|
end
|
58
58
|
|
59
|
-
# Zoneinfo
|
60
|
-
#
|
61
|
-
#
|
59
|
+
# Zoneinfo files don't include the offset from standard time (std_offset)
|
60
|
+
# for DST periods. Derive the base offset (utc_offset) where DST is
|
61
|
+
# observed from either the previous or next non-DST period.
|
62
62
|
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
def derive_offsets(transitions, offsets)
|
66
|
-
|
63
|
+
# Returns the index of the offset to be used prior to the first
|
64
|
+
# transition.
|
65
|
+
def derive_offsets(transitions, offsets)
|
66
|
+
# The first non-DST offset (if there is one) is the offset observed
|
67
|
+
# before the first transition. Fallback to the first DST offset if there
|
68
|
+
# are no non-DST offsets.
|
69
|
+
first_non_dst_offset_index = offsets.index {|o| !o[:is_dst] }
|
70
|
+
first_offset_index = first_non_dst_offset_index || 0
|
71
|
+
return first_offset_index if transitions.empty?
|
67
72
|
|
68
|
-
|
69
|
-
|
73
|
+
# Determine the utc_offset of the next non-dst offset at each transition.
|
74
|
+
utc_offset_from_next = nil
|
70
75
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
76
|
+
transitions.reverse_each do |transition|
|
77
|
+
offset = offsets[transition[:offset]]
|
78
|
+
if offset[:is_dst]
|
79
|
+
transition[:utc_offset_from_next] = utc_offset_from_next if utc_offset_from_next
|
80
|
+
else
|
81
|
+
utc_offset_from_next = offset[:utc_total_offset]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
utc_offset_from_previous = first_non_dst_offset_index ? offsets[first_non_dst_offset_index][:utc_total_offset] : nil
|
86
|
+
defined_offsets = {}
|
87
|
+
|
88
|
+
transitions.each do |transition|
|
89
|
+
offset_index = transition[:offset]
|
90
|
+
offset = offsets[offset_index]
|
91
|
+
utc_total_offset = offset[:utc_total_offset]
|
92
|
+
|
93
|
+
if offset[:is_dst]
|
94
|
+
utc_offset_from_next = transition[:utc_offset_from_next]
|
95
|
+
|
96
|
+
difference_to_previous = utc_total_offset - (utc_offset_from_previous || utc_total_offset)
|
97
|
+
difference_to_next = utc_total_offset - (utc_offset_from_next || utc_total_offset)
|
98
|
+
|
99
|
+
utc_offset = if difference_to_previous > 0 && difference_to_next > 0
|
100
|
+
difference_to_previous < difference_to_next ? utc_offset_from_previous : utc_offset_from_next
|
101
|
+
elsif difference_to_previous > 0
|
102
|
+
utc_offset_from_previous
|
103
|
+
elsif difference_to_next > 0
|
104
|
+
utc_offset_from_next
|
105
|
+
else # difference_to_previous <= 0 && difference_to_next <= 0
|
106
|
+
# DST, but the either the offset has stayed the same or decreased
|
107
|
+
# relative to both the previous and next used base utc offset, or
|
108
|
+
# there are no non-DST offsets. Assume a 1 hour offset from base.
|
109
|
+
utc_total_offset - 3600
|
82
110
|
end
|
83
|
-
|
84
|
-
if
|
85
|
-
offset[:
|
86
|
-
offset
|
111
|
+
|
112
|
+
if !offset[:utc_offset]
|
113
|
+
offset[:utc_offset] = utc_offset
|
114
|
+
defined_offsets[offset] = offset_index
|
115
|
+
elsif offset[:utc_offset] != utc_offset
|
116
|
+
# An earlier transition has already derived a different
|
117
|
+
# utc_offset. Define a new offset or reuse an existing identically
|
118
|
+
# defined offset.
|
119
|
+
new_offset = offset.dup
|
120
|
+
new_offset[:utc_offset] = utc_offset
|
121
|
+
|
122
|
+
offset_index = defined_offsets[new_offset]
|
123
|
+
|
124
|
+
unless offset_index
|
125
|
+
offsets << new_offset
|
126
|
+
offset_index = offsets.length - 1
|
127
|
+
defined_offsets[new_offset] = offset_index
|
128
|
+
end
|
129
|
+
|
130
|
+
transition[:offset] = offset_index
|
87
131
|
end
|
132
|
+
else
|
133
|
+
utc_offset_from_previous = utc_total_offset
|
88
134
|
end
|
89
|
-
|
90
|
-
previous_offset = offset
|
91
135
|
end
|
136
|
+
|
137
|
+
first_offset_index
|
138
|
+
end
|
139
|
+
|
140
|
+
# Defines an offset for the timezone based on the given index and offset
|
141
|
+
# Hash.
|
142
|
+
def define_offset(index, offset)
|
143
|
+
utc_total_offset = offset[:utc_total_offset]
|
144
|
+
utc_offset = offset[:utc_offset]
|
145
|
+
|
146
|
+
if utc_offset
|
147
|
+
# DST offset with base utc_offset derived by derive_offsets.
|
148
|
+
std_offset = utc_total_offset - utc_offset
|
149
|
+
elsif offset[:is_dst]
|
150
|
+
# DST offset unreferenced by a transition (offset in use before the
|
151
|
+
# first transition). No derived base UTC offset, so assume 1 hour
|
152
|
+
# DST.
|
153
|
+
utc_offset = utc_total_offset - 3600
|
154
|
+
std_offset = 3600
|
155
|
+
else
|
156
|
+
# Non-DST offset.
|
157
|
+
utc_offset = utc_total_offset
|
158
|
+
std_offset = 0
|
159
|
+
end
|
160
|
+
|
161
|
+
offset index, utc_offset, std_offset, offset[:abbr].untaint.to_sym
|
92
162
|
end
|
93
163
|
|
94
164
|
# Parses a zoneinfo file and intializes the DataTimezoneInfo structures.
|
@@ -127,27 +197,27 @@ module TZInfo
|
|
127
197
|
transitions = []
|
128
198
|
|
129
199
|
if using_64bit
|
130
|
-
|
131
|
-
high, low = check_read(file, 8).unpack('NN')
|
200
|
+
timecnt.times do |i|
|
201
|
+
high, low = check_read(file, 8).unpack('NN'.freeze)
|
132
202
|
transition_time = make_signed_int64(high, low)
|
133
203
|
transitions << {:at => transition_time}
|
134
204
|
end
|
135
205
|
else
|
136
|
-
|
137
|
-
transition_time = make_signed_int32(check_read(file, 4).unpack('N')[0])
|
206
|
+
timecnt.times do |i|
|
207
|
+
transition_time = make_signed_int32(check_read(file, 4).unpack('N'.freeze)[0])
|
138
208
|
transitions << {:at => transition_time}
|
139
209
|
end
|
140
210
|
end
|
141
211
|
|
142
|
-
|
143
|
-
localtime_type = check_read(file, 1).unpack('C')[0]
|
212
|
+
timecnt.times do |i|
|
213
|
+
localtime_type = check_read(file, 1).unpack('C'.freeze)[0]
|
144
214
|
transitions[i][:offset] = localtime_type
|
145
215
|
end
|
146
216
|
|
147
217
|
offsets = []
|
148
218
|
|
149
|
-
|
150
|
-
gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC')
|
219
|
+
typecnt.times do |i|
|
220
|
+
gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC'.freeze)
|
151
221
|
gmtoff = make_signed_int32(gmtoff)
|
152
222
|
isdst = isdst == 1
|
153
223
|
offset = {:utc_total_offset => gmtoff, :is_dst => isdst, :abbr_index => abbrind}
|
@@ -179,33 +249,12 @@ module TZInfo
|
|
179
249
|
end
|
180
250
|
|
181
251
|
# Derive the offsets from standard time (std_offset).
|
182
|
-
derive_offsets(transitions, offsets)
|
183
|
-
derive_offsets(transitions.reverse, offsets)
|
252
|
+
first_offset_index = derive_offsets(transitions, offsets)
|
184
253
|
|
185
|
-
|
186
|
-
offsets.each do |o|
|
187
|
-
if !o[:std_offset] && o[:is_dst]
|
188
|
-
o[:std_offset] = 3600
|
189
|
-
o[:utc_offset] = o[:utc_total_offset] - 3600
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
# Find the first non-dst offset. This is used as the offset for the time
|
194
|
-
# before the first transition.
|
195
|
-
first = nil
|
196
|
-
offsets.each_with_index do |o, i|
|
197
|
-
if !o[:is_dst]
|
198
|
-
first = i
|
199
|
-
break
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
if first
|
204
|
-
offset first, offsets[first][:utc_offset], offsets[first][:std_offset], offsets[first][:abbr].untaint.to_sym
|
205
|
-
end
|
254
|
+
define_offset(first_offset_index, offsets[first_offset_index])
|
206
255
|
|
207
256
|
offsets.each_with_index do |o, i|
|
208
|
-
|
257
|
+
define_offset(i, o) unless i == first_offset_index
|
209
258
|
end
|
210
259
|
|
211
260
|
if !using_64bit && !RubyCoreSupport.time_supports_negative
|