tzinfo-data 1.2018.7 → 1.2018.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -2
- data.tar.gz.sig +0 -0
- data/LICENSE +12 -12
- data/README.md +2 -2
- data/lib/tzinfo/data/definitions/Africa/Casablanca.rb +42 -1
- data/lib/tzinfo/data/definitions/Africa/El_Aaiun.rb +42 -1
- data/lib/tzinfo/data/definitions/America/Metlakatla.rb +1 -1
- data/lib/tzinfo/data/definitions/Asia/Hong_Kong.rb +8 -7
- data/lib/tzinfo/data/definitions/Asia/Qostanay.rb +77 -0
- data/lib/tzinfo/data/definitions/Asia/Qyzylorda.rb +1 -0
- data/lib/tzinfo/data/definitions/Asia/Tehran.rb +28 -28
- data/lib/tzinfo/data/definitions/Pacific/Chuuk.rb +10 -3
- data/lib/tzinfo/data/definitions/Pacific/Guam.rb +22 -2
- data/lib/tzinfo/data/definitions/Pacific/Kosrae.rb +15 -6
- data/lib/tzinfo/data/definitions/Pacific/Kwajalein.rb +9 -4
- data/lib/tzinfo/data/definitions/Pacific/Majuro.rb +9 -2
- data/lib/tzinfo/data/definitions/Pacific/Nauru.rb +3 -3
- data/lib/tzinfo/data/definitions/Pacific/Palau.rb +5 -3
- data/lib/tzinfo/data/definitions/Pacific/Pohnpei.rb +12 -3
- data/lib/tzinfo/data/indexes/countries.rb +2 -1
- data/lib/tzinfo/data/indexes/timezones.rb +1 -0
- data/lib/tzinfo/data/tzdataparser.rb +322 -322
- data/lib/tzinfo/data/version.rb +4 -4
- metadata +4 -4
- metadata.gz.sig +0 -0
@@ -11,13 +11,22 @@ module TZInfo
|
|
11
11
|
include TimezoneDefinition
|
12
12
|
|
13
13
|
timezone 'Pacific/Kosrae' do |tz|
|
14
|
-
tz.offset :o0,
|
15
|
-
tz.offset :o1,
|
16
|
-
tz.offset :o2,
|
14
|
+
tz.offset :o0, -47284, 0, :LMT
|
15
|
+
tz.offset :o1, 39116, 0, :LMT
|
16
|
+
tz.offset :o2, 39600, 0, :'+11'
|
17
|
+
tz.offset :o3, 32400, 0, :'+09'
|
18
|
+
tz.offset :o4, 36000, 0, :'+10'
|
19
|
+
tz.offset :o5, 43200, 0, :'+12'
|
17
20
|
|
18
|
-
tz.transition
|
19
|
-
tz.transition
|
20
|
-
tz.transition
|
21
|
+
tz.transition 1844, 12, :o1, -3944631116, 51730532221, 21600
|
22
|
+
tz.transition 1900, 12, :o2, -2177491916, 52172317021, 21600
|
23
|
+
tz.transition 1914, 9, :o3, -1743678000, 58089745, 24
|
24
|
+
tz.transition 1919, 1, :o2, -1606813200, 19375921, 8
|
25
|
+
tz.transition 1936, 12, :o4, -1041418800, 58284817, 24
|
26
|
+
tz.transition 1941, 3, :o3, -907408800, 29161021, 12
|
27
|
+
tz.transition 1945, 7, :o2, -770634000, 19453345, 8
|
28
|
+
tz.transition 1969, 9, :o5, -7988400, 58571881, 24
|
29
|
+
tz.transition 1998, 12, :o2, 915105600
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -13,12 +13,17 @@ module TZInfo
|
|
13
13
|
timezone 'Pacific/Kwajalein' do |tz|
|
14
14
|
tz.offset :o0, 40160, 0, :LMT
|
15
15
|
tz.offset :o1, 39600, 0, :'+11'
|
16
|
-
tz.offset :o2,
|
17
|
-
tz.offset :o3,
|
16
|
+
tz.offset :o2, 36000, 0, :'+10'
|
17
|
+
tz.offset :o3, 32400, 0, :'+09'
|
18
|
+
tz.offset :o4, -43200, 0, :'-12'
|
19
|
+
tz.offset :o5, 43200, 0, :'+12'
|
18
20
|
|
19
21
|
tz.transition 1900, 12, :o1, -2177492960, 1304307919, 540
|
20
|
-
tz.transition
|
21
|
-
tz.transition
|
22
|
+
tz.transition 1936, 12, :o2, -1041418800, 58284817, 24
|
23
|
+
tz.transition 1941, 3, :o3, -907408800, 29161021, 12
|
24
|
+
tz.transition 1944, 2, :o1, -817462800, 19449009, 8
|
25
|
+
tz.transition 1969, 9, :o4, -7988400, 58571881, 24
|
26
|
+
tz.transition 1993, 8, :o5, 745934400
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
@@ -13,10 +13,17 @@ module TZInfo
|
|
13
13
|
timezone 'Pacific/Majuro' do |tz|
|
14
14
|
tz.offset :o0, 41088, 0, :LMT
|
15
15
|
tz.offset :o1, 39600, 0, :'+11'
|
16
|
-
tz.offset :o2,
|
16
|
+
tz.offset :o2, 32400, 0, :'+09'
|
17
|
+
tz.offset :o3, 36000, 0, :'+10'
|
18
|
+
tz.offset :o4, 43200, 0, :'+12'
|
17
19
|
|
18
20
|
tz.transition 1900, 12, :o1, -2177493888, 1086923261, 450
|
19
|
-
tz.transition
|
21
|
+
tz.transition 1914, 9, :o2, -1743678000, 58089745, 24
|
22
|
+
tz.transition 1919, 1, :o1, -1606813200, 19375921, 8
|
23
|
+
tz.transition 1936, 12, :o3, -1041418800, 58284817, 24
|
24
|
+
tz.transition 1941, 3, :o2, -907408800, 29161021, 12
|
25
|
+
tz.transition 1944, 1, :o1, -818067600, 19448953, 8
|
26
|
+
tz.transition 1969, 9, :o4, -7988400, 58571881, 24
|
20
27
|
end
|
21
28
|
end
|
22
29
|
end
|
@@ -17,9 +17,9 @@ module TZInfo
|
|
17
17
|
tz.offset :o3, 43200, 0, :'+12'
|
18
18
|
|
19
19
|
tz.transition 1921, 1, :o1, -1545131260, 10466081437, 4320
|
20
|
-
tz.transition 1942,
|
21
|
-
tz.transition
|
22
|
-
tz.transition 1979,
|
20
|
+
tz.transition 1942, 8, :o2, -862918200, 116668801, 48
|
21
|
+
tz.transition 1945, 9, :o1, -767350800, 19453649, 8
|
22
|
+
tz.transition 1979, 2, :o3, 287418600
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -11,10 +11,12 @@ module TZInfo
|
|
11
11
|
include TimezoneDefinition
|
12
12
|
|
13
13
|
timezone 'Pacific/Palau' do |tz|
|
14
|
-
tz.offset :o0,
|
15
|
-
tz.offset :o1,
|
14
|
+
tz.offset :o0, -54124, 0, :LMT
|
15
|
+
tz.offset :o1, 32276, 0, :LMT
|
16
|
+
tz.offset :o2, 32400, 0, :'+09'
|
16
17
|
|
17
|
-
tz.transition
|
18
|
+
tz.transition 1844, 12, :o1, -3944624276, 51730533931, 21600
|
19
|
+
tz.transition 1900, 12, :o2, -2177485076, 52172318731, 21600
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -11,10 +11,19 @@ module TZInfo
|
|
11
11
|
include TimezoneDefinition
|
12
12
|
|
13
13
|
timezone 'Pacific/Pohnpei' do |tz|
|
14
|
-
tz.offset :o0,
|
15
|
-
tz.offset :o1,
|
14
|
+
tz.offset :o0, -48428, 0, :LMT
|
15
|
+
tz.offset :o1, 37972, 0, :LMT
|
16
|
+
tz.offset :o2, 39600, 0, :'+11'
|
17
|
+
tz.offset :o3, 32400, 0, :'+09'
|
18
|
+
tz.offset :o4, 36000, 0, :'+10'
|
16
19
|
|
17
|
-
tz.transition
|
20
|
+
tz.transition 1844, 12, :o1, -3944629972, 51730532507, 21600
|
21
|
+
tz.transition 1900, 12, :o2, -2177490772, 52172317307, 21600
|
22
|
+
tz.transition 1914, 9, :o3, -1743678000, 58089745, 24
|
23
|
+
tz.transition 1919, 1, :o2, -1606813200, 19375921, 8
|
24
|
+
tz.transition 1936, 12, :o4, -1041418800, 58284817, 24
|
25
|
+
tz.transition 1941, 3, :o3, -907408800, 29161021, 12
|
26
|
+
tz.transition 1945, 7, :o2, -770634000, 19453345, 8
|
18
27
|
end
|
19
28
|
end
|
20
29
|
end
|
@@ -473,6 +473,7 @@ module TZInfo
|
|
473
473
|
country 'KZ', 'Kazakhstan' do |c|
|
474
474
|
c.timezone 'Asia/Almaty', 173, 4, 1539, 20, 'Kazakhstan (most areas)'
|
475
475
|
c.timezone 'Asia/Qyzylorda', 224, 5, 982, 15, 'Qyzylorda/Kyzylorda/Kzyl-Orda'
|
476
|
+
c.timezone 'Asia/Qostanay', 266, 5, 3817, 60, 'Qostanay/Kostanay/Kustanay'
|
476
477
|
c.timezone 'Asia/Aqtobe', 3017, 60, 343, 6, 'Aqtöbe/Aktobe'
|
477
478
|
c.timezone 'Asia/Aqtau', 2671, 60, 754, 15, 'Mangghystaū/Mankistau'
|
478
479
|
c.timezone 'Asia/Atyrau', 2827, 60, 779, 15, 'Atyraū/Atirau/Gur\'yev'
|
@@ -698,9 +699,9 @@ module TZInfo
|
|
698
699
|
c.timezone 'Europe/Kaliningrad', 3283, 60, 41, 2, 'MSK-01 - Kaliningrad'
|
699
700
|
c.timezone 'Europe/Moscow', 66907, 1200, 8464, 225, 'MSK+00 - Moscow area'
|
700
701
|
c.timezone 'Europe/Simferopol', 899, 20, 341, 10, 'MSK+00 - Crimea'
|
701
|
-
c.timezone 'Europe/Volgograd', 731, 15, 533, 12, 'MSK+00 - Volgograd'
|
702
702
|
c.timezone 'Europe/Kirov', 293, 5, 993, 20, 'MSK+00 - Kirov'
|
703
703
|
c.timezone 'Europe/Astrakhan', 927, 20, 961, 20, 'MSK+01 - Astrakhan'
|
704
|
+
c.timezone 'Europe/Volgograd', 731, 15, 533, 12, 'MSK+01 - Volgograd'
|
704
705
|
c.timezone 'Europe/Saratov', 1547, 30, 1381, 30, 'MSK+01 - Saratov'
|
705
706
|
c.timezone 'Europe/Ulyanovsk', 163, 3, 242, 5, 'MSK+01 - Ulyanovsk'
|
706
707
|
c.timezone 'Europe/Samara', 266, 5, 1003, 20, 'MSK+01 - Samara, Udmurtia'
|
@@ -3,7 +3,7 @@ require 'fileutils'
|
|
3
3
|
|
4
4
|
module TZInfo
|
5
5
|
module Data
|
6
|
-
|
6
|
+
|
7
7
|
# Utility methods used by TZDataParser and associated classes.
|
8
8
|
#
|
9
9
|
# @private
|
@@ -20,11 +20,11 @@ module TZInfo
|
|
20
20
|
File.open(file_name, mode, opts, &block)
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
private :open_file
|
25
|
-
|
25
|
+
|
26
26
|
private
|
27
|
-
|
27
|
+
|
28
28
|
# Parses a month specified in the tz data and converts it to a number
|
29
29
|
# between 1 and 12 representing January to December.
|
30
30
|
def parse_month(month)
|
@@ -57,17 +57,17 @@ module TZInfo
|
|
57
57
|
raise "Invalid month: #{month}"
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
# Parses an offset string [-]h:m:s (minutes and seconds are optional). Returns
|
62
62
|
# the offset in seconds.
|
63
63
|
def parse_offset(offset)
|
64
64
|
raise "Invalid time: #{offset}" if offset !~ /^(-)?(?:([0-9]+)(?::([0-9]+)(?::([0-9]+))?)?)?$/
|
65
|
-
|
66
|
-
negative = !$1.nil?
|
65
|
+
|
66
|
+
negative = !$1.nil?
|
67
67
|
hour = $2.nil? ? 0 : $2.to_i
|
68
68
|
minute = $3.nil? ? 0 : $3.to_i
|
69
69
|
second = $4.nil? ? 0 : $4.to_i
|
70
|
-
|
70
|
+
|
71
71
|
seconds = hour
|
72
72
|
seconds = seconds * 60
|
73
73
|
seconds = seconds + minute
|
@@ -76,52 +76,52 @@ module TZInfo
|
|
76
76
|
seconds = -seconds if negative
|
77
77
|
seconds
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
# Encloses the string in single quotes and escapes any single quotes in
|
81
81
|
# the content.
|
82
82
|
def quote_str(str)
|
83
83
|
"'#{str.gsub('\'', '\\\\\'')}'"
|
84
84
|
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Parses Time Zone Data from the IANA Time Zone Database and transforms it
|
85
|
+
end
|
86
|
+
|
87
|
+
# Parses Time Zone Data from the IANA Time Zone Database and transforms it
|
88
88
|
# into a set of Ruby modules that can be used with TZInfo.
|
89
|
-
#
|
90
|
-
# Normally, this class wouldn't be used. It is only run to update the
|
89
|
+
#
|
90
|
+
# Normally, this class wouldn't be used. It is only run to update the
|
91
91
|
# timezone data and index modules.
|
92
92
|
class TZDataParser
|
93
93
|
include TZDataParserUtils
|
94
|
-
|
94
|
+
|
95
95
|
# Default earliest year that will be considered.
|
96
96
|
DEFAULT_MIN_YEAR = 1800
|
97
|
-
|
98
|
-
# Default number of future years data to generate (not including the
|
97
|
+
|
98
|
+
# Default number of future years data to generate (not including the
|
99
99
|
# current year).
|
100
100
|
DEFAULT_FUTURE_YEARS = 50
|
101
|
-
|
101
|
+
|
102
102
|
# Earliest year that will be considered. Defaults to DEFAULT_MIN_YEAR.
|
103
103
|
attr_accessor :min_year
|
104
|
-
|
104
|
+
|
105
105
|
# Latest year that will be considered. Defaults to the current year plus
|
106
106
|
# FUTURE_YEARS.
|
107
107
|
attr_accessor :max_year
|
108
|
-
|
108
|
+
|
109
109
|
# Whether to generate zone definitions (set to false to stop zones being
|
110
|
-
# generated).
|
110
|
+
# generated).
|
111
111
|
attr_accessor :generate_zones
|
112
|
-
|
112
|
+
|
113
113
|
# Whether to generate country definitions (set to false to stop countries
|
114
114
|
# being generated).
|
115
115
|
attr_accessor :generate_countries
|
116
|
-
|
116
|
+
|
117
117
|
# Limit the set of zones to generate (set to an array containing zone
|
118
118
|
# identifiers).
|
119
119
|
attr_accessor :only_zones
|
120
|
-
|
120
|
+
|
121
121
|
# Zones to exclude from generation when not using only_zones (set to an
|
122
122
|
# array containing zone identifiers).
|
123
123
|
attr_accessor :exclude_zones
|
124
|
-
|
124
|
+
|
125
125
|
# Initializes a new TZDataParser. input_dir must contain the extracted
|
126
126
|
# tzdata tarball. output_dir is the location to output the modules
|
127
127
|
# (in definitions and indexes directories).
|
@@ -140,7 +140,7 @@ module TZInfo
|
|
140
140
|
@only_zones = []
|
141
141
|
@exclude_zones = []
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
# Reads the tzdata source and generates the classes. Progress information
|
145
145
|
# is written to standard out.
|
146
146
|
def execute
|
@@ -150,20 +150,20 @@ module TZInfo
|
|
150
150
|
# install its entries by default.
|
151
151
|
|
152
152
|
files = Dir.entries(@input_dir).select do |file|
|
153
|
-
file =~ /\A[^\.]+\z/ &&
|
153
|
+
file =~ /\A[^\.]+\z/ &&
|
154
154
|
!%w(backzone calendars leapseconds CONTRIBUTING LICENSE Makefile NEWS README SOURCE Theory version).include?(file) &&
|
155
155
|
File.file?(File.join(@input_dir, file))
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
files.each {|file| load_rules(file) }
|
159
159
|
files.each {|file| load_zones(file) }
|
160
160
|
files.each {|file| load_links(file) }
|
161
|
-
|
161
|
+
|
162
162
|
load_countries
|
163
|
-
|
163
|
+
|
164
164
|
if @generate_zones
|
165
165
|
modules = []
|
166
|
-
|
166
|
+
|
167
167
|
if @only_zones.nil? || @only_zones.empty?
|
168
168
|
@zones.each_value {|zone|
|
169
169
|
zone.write_module(@output_dir) unless @exclude_zones.include?(zone.name)
|
@@ -171,45 +171,45 @@ module TZInfo
|
|
171
171
|
else
|
172
172
|
@only_zones.each {|id|
|
173
173
|
zone = @zones[id]
|
174
|
-
zone.write_module(@output_dir)
|
175
|
-
}
|
174
|
+
zone.write_module(@output_dir)
|
175
|
+
}
|
176
176
|
end
|
177
|
-
|
177
|
+
|
178
178
|
write_timezones_index
|
179
179
|
end
|
180
|
-
|
181
|
-
if @generate_countries
|
180
|
+
|
181
|
+
if @generate_countries
|
182
182
|
write_countries_index
|
183
183
|
end
|
184
184
|
end
|
185
|
-
|
186
|
-
private
|
185
|
+
|
186
|
+
private
|
187
187
|
# Loads all the Rule definitions from the tz data and stores them in
|
188
188
|
# the rule_sets instance variable.
|
189
189
|
def load_rules(file)
|
190
190
|
puts 'load_rules: ' + file
|
191
|
-
|
191
|
+
|
192
192
|
# Files are in ASCII, but may change to UTF-8 (a superset of ASCII)
|
193
193
|
# in the future.
|
194
194
|
open_file(File.join(@input_dir, file), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
195
195
|
file.each_line do |line|
|
196
196
|
line = line.gsub(/#.*$/, '')
|
197
197
|
line = line.gsub(/\s+$/, '')
|
198
|
-
|
198
|
+
|
199
199
|
if line =~ /^Rule\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/
|
200
|
-
|
201
|
-
name = $1
|
202
|
-
|
203
|
-
if @rule_sets[name].nil?
|
204
|
-
@rule_sets[name] = TZDataRuleSet.new(name)
|
200
|
+
|
201
|
+
name = $1
|
202
|
+
|
203
|
+
if @rule_sets[name].nil?
|
204
|
+
@rule_sets[name] = TZDataRuleSet.new(name)
|
205
205
|
end
|
206
|
-
|
206
|
+
|
207
207
|
@rule_sets[name].add_rule(TZDataRule.new($2, $3, $4, $5, $6, $7, $8, $9))
|
208
|
-
end
|
208
|
+
end
|
209
209
|
end
|
210
210
|
end
|
211
211
|
end
|
212
|
-
|
212
|
+
|
213
213
|
# Gets a rules object for the given reference. Might be a named rule set,
|
214
214
|
# a fixed offset or an empty ruleset.
|
215
215
|
def get_rules(ref)
|
@@ -219,80 +219,80 @@ module TZInfo
|
|
219
219
|
TZDataFixedOffsetRules.new(parse_offset(ref))
|
220
220
|
else
|
221
221
|
rule_set = @rule_sets[ref]
|
222
|
-
raise "Ruleset not found: #{ref}" if rule_set.nil?
|
222
|
+
raise "Ruleset not found: #{ref}" if rule_set.nil?
|
223
223
|
rule_set
|
224
|
-
end
|
224
|
+
end
|
225
225
|
end
|
226
|
-
|
226
|
+
|
227
227
|
# Loads in the Zone definitions from the tz data and stores them in @zones.
|
228
228
|
def load_zones(file)
|
229
229
|
puts 'load_zones: ' + file
|
230
|
-
|
230
|
+
|
231
231
|
in_zone = nil
|
232
|
-
|
232
|
+
|
233
233
|
# Files are in ASCII, but may change to UTF-8 (a superset of ASCII)
|
234
234
|
# in the future.
|
235
235
|
open_file(File.join(@input_dir, file), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
236
236
|
file.each_line do |line|
|
237
237
|
line = line.gsub(/#.*$/, '')
|
238
238
|
line = line.gsub(/\s+$/, '')
|
239
|
-
|
239
|
+
|
240
240
|
if in_zone
|
241
|
-
if line =~ /^\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
242
|
-
|
241
|
+
if line =~ /^\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
242
|
+
|
243
243
|
in_zone.add_observance(TZDataObservance.new($1, get_rules($2), $3, $5))
|
244
|
-
|
245
|
-
in_zone = nil if $4.nil?
|
244
|
+
|
245
|
+
in_zone = nil if $4.nil?
|
246
246
|
end
|
247
247
|
else
|
248
|
-
if line =~ /^Zone\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
248
|
+
if line =~ /^Zone\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
249
249
|
name = $1
|
250
|
-
|
251
|
-
if @zones[name].nil?
|
250
|
+
|
251
|
+
if @zones[name].nil?
|
252
252
|
@zones[name] = TZDataZone.new(name, @min_year..@max_year)
|
253
|
-
end
|
254
|
-
|
253
|
+
end
|
254
|
+
|
255
255
|
@zones[name].add_observance(TZDataObservance.new($2, get_rules($3), $4, $6))
|
256
|
-
|
256
|
+
|
257
257
|
in_zone = @zones[name] if !$5.nil?
|
258
258
|
end
|
259
259
|
end
|
260
260
|
end
|
261
261
|
end
|
262
262
|
end
|
263
|
-
|
263
|
+
|
264
264
|
# Loads in the links and stores them in @zones.
|
265
265
|
def load_links(file)
|
266
266
|
puts 'load_links: ' + file
|
267
|
-
|
267
|
+
|
268
268
|
# Files are in ASCII, but may change to UTF-8 (a superset of ASCII)
|
269
269
|
# in the future.
|
270
270
|
open_file(File.join(@input_dir, file), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
271
271
|
file.each_line do |line|
|
272
272
|
line = line.gsub(/#.*$/, '')
|
273
273
|
line = line.gsub(/\s+$/, '')
|
274
|
-
|
275
|
-
if line =~ /^Link\s+([^\s]+)\s+([^\s]+)/
|
276
|
-
name = $2
|
274
|
+
|
275
|
+
if line =~ /^Link\s+([^\s]+)\s+([^\s]+)/
|
276
|
+
name = $2
|
277
277
|
link_to = @zones[$1]
|
278
278
|
raise "Link to zone not found (#{name}->#{link_to})" if link_to.nil?
|
279
279
|
raise "Zone already defined: #{name}" if !@zones[name].nil?
|
280
280
|
@zones[name] = TZDataLink.new(name, link_to)
|
281
|
-
end
|
281
|
+
end
|
282
282
|
end
|
283
283
|
end
|
284
284
|
end
|
285
|
-
|
285
|
+
|
286
286
|
# Loads countries from iso3166.tab and zone1970.tab and stores the
|
287
287
|
# result in the countries instance variable.
|
288
288
|
def load_countries
|
289
289
|
puts 'load_countries'
|
290
|
-
|
290
|
+
|
291
291
|
# iso3166.tab is ASCII encoded, but is planned to change to UTF-8 (a
|
292
292
|
# superset of ASCII) in the future.
|
293
293
|
open_file(File.join(@input_dir, 'iso3166.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
294
294
|
file.each_line do |line|
|
295
|
-
|
295
|
+
|
296
296
|
if line =~ /^([A-Z]{2})\t(.*)$/
|
297
297
|
code = $1
|
298
298
|
name = $2
|
@@ -307,22 +307,22 @@ module TZInfo
|
|
307
307
|
# zone1970.tab is UTF-8 encoded.
|
308
308
|
open_file(File.join(@input_dir, 'zone1970.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
309
309
|
file.each_line do |line|
|
310
|
-
|
311
|
-
line.chomp!
|
310
|
+
|
311
|
+
line.chomp!
|
312
312
|
|
313
313
|
if line =~ /^([A-Z]{2}(?:,[A-Z]{2})*)\t([^\t]+)\t([^\t]+)(\t(.*))?$/
|
314
314
|
codes = $1
|
315
315
|
location_str = $2
|
316
316
|
zone_name = $3
|
317
317
|
description = $5
|
318
|
-
|
318
|
+
|
319
319
|
location = TZDataLocation.new(location_str)
|
320
|
-
|
320
|
+
|
321
321
|
zone = @zones[zone_name]
|
322
|
-
raise "Zone not found: #{zone_name}" if zone.nil?
|
323
|
-
|
322
|
+
raise "Zone not found: #{zone_name}" if zone.nil?
|
323
|
+
|
324
324
|
description = nil if description == ''
|
325
|
-
|
325
|
+
|
326
326
|
country_timezone = TZDataCountryTimezone.new(zone, description, location)
|
327
327
|
|
328
328
|
codes = codes.split(',')
|
@@ -347,95 +347,95 @@ module TZInfo
|
|
347
347
|
end
|
348
348
|
end
|
349
349
|
end
|
350
|
-
|
350
|
+
|
351
351
|
# Writes a country index file.
|
352
352
|
def write_countries_index
|
353
353
|
dir = File.join(@output_dir, 'indexes')
|
354
354
|
FileUtils.mkdir_p(dir)
|
355
|
-
|
355
|
+
|
356
356
|
open_file(File.join(dir, 'countries.rb'), 'w', :external_encoding => 'UTF-8', :universal_newline => true) do |file|
|
357
357
|
file.puts('# encoding: UTF-8')
|
358
358
|
file.puts('')
|
359
359
|
file.puts('# This file contains data derived from the IANA Time Zone Database')
|
360
360
|
file.puts('# (http://www.iana.org/time-zones).')
|
361
361
|
file.puts('')
|
362
|
-
|
362
|
+
|
363
363
|
file.puts('module TZInfo')
|
364
364
|
file.puts(' module Data')
|
365
365
|
file.puts(' module Indexes')
|
366
366
|
file.puts(' module Countries')
|
367
367
|
file.puts(' include CountryIndexDefinition')
|
368
368
|
file.puts('')
|
369
|
-
|
370
|
-
countries = @countries.values.sort {|c1,c2| c1.code <=> c2.code}
|
369
|
+
|
370
|
+
countries = @countries.values.sort {|c1,c2| c1.code <=> c2.code}
|
371
371
|
countries.each {|country| country.write_index_record(file)}
|
372
|
-
|
373
|
-
file.puts(' end') # end module Countries
|
372
|
+
|
373
|
+
file.puts(' end') # end module Countries
|
374
374
|
file.puts(' end') # end module Indexes
|
375
375
|
file.puts(' end') # end module Data
|
376
376
|
file.puts('end') # end module TZInfo
|
377
|
-
end
|
377
|
+
end
|
378
378
|
end
|
379
|
-
|
379
|
+
|
380
380
|
# Writes a timezone index file.
|
381
381
|
def write_timezones_index
|
382
382
|
dir = File.join(@output_dir, 'indexes')
|
383
383
|
FileUtils.mkdir_p(dir)
|
384
|
-
|
384
|
+
|
385
385
|
open_file(File.join(dir, 'timezones.rb'), 'w', :external_encoding => 'UTF-8', :universal_newline => true) do |file|
|
386
386
|
file.puts('# encoding: UTF-8')
|
387
387
|
file.puts('')
|
388
388
|
file.puts('# This file contains data derived from the IANA Time Zone Database')
|
389
389
|
file.puts('# (http://www.iana.org/time-zones).')
|
390
390
|
file.puts('')
|
391
|
-
|
391
|
+
|
392
392
|
file.puts('module TZInfo')
|
393
393
|
file.puts(' module Data')
|
394
394
|
file.puts(' module Indexes')
|
395
395
|
file.puts(' module Timezones')
|
396
396
|
file.puts(' include TimezoneIndexDefinition')
|
397
397
|
file.puts('')
|
398
|
-
|
398
|
+
|
399
399
|
zones = @zones.values.sort {|t1,t2| t1.name <=> t2.name}
|
400
400
|
zones.each {|zone| zone.write_index_record(file)}
|
401
|
-
|
401
|
+
|
402
402
|
file.puts(' end') # end module Timezones
|
403
403
|
file.puts(' end') # end module Indexes
|
404
404
|
file.puts(' end') # end module Data
|
405
405
|
file.puts('end') # end module TZInfo
|
406
406
|
end
|
407
|
-
|
407
|
+
|
408
408
|
end
|
409
409
|
end
|
410
|
-
|
410
|
+
|
411
411
|
# Base class for all rule sets.
|
412
412
|
#
|
413
413
|
# @private
|
414
414
|
class TZDataRules #:nodoc:
|
415
415
|
# Name of the rule set, e.g. EU.
|
416
416
|
attr_reader :name
|
417
|
-
|
417
|
+
|
418
418
|
def initialize(name)
|
419
419
|
@name = name
|
420
420
|
end
|
421
|
-
|
421
|
+
|
422
422
|
def count
|
423
423
|
0
|
424
424
|
end
|
425
425
|
end
|
426
|
-
|
426
|
+
|
427
427
|
# Empty rule set with a fixed daylight savings (std) offset.
|
428
428
|
#
|
429
429
|
# @private
|
430
430
|
class TZDataFixedOffsetRules < TZDataRules #:nodoc:
|
431
431
|
attr_reader :offset
|
432
|
-
|
432
|
+
|
433
433
|
def initialize(offset)
|
434
434
|
super(offset.to_s)
|
435
435
|
@offset = offset
|
436
|
-
end
|
436
|
+
end
|
437
437
|
end
|
438
|
-
|
438
|
+
|
439
439
|
# An empty set of rules.
|
440
440
|
#
|
441
441
|
# @private
|
@@ -444,38 +444,38 @@ module TZInfo
|
|
444
444
|
super('-')
|
445
445
|
end
|
446
446
|
end
|
447
|
-
|
447
|
+
|
448
448
|
# A rule set (as defined by Rule name in the tz data).
|
449
449
|
#
|
450
450
|
# @private
|
451
|
-
class TZDataRuleSet < TZDataRules #:nodoc:
|
451
|
+
class TZDataRuleSet < TZDataRules #:nodoc:
|
452
452
|
attr_reader :rules
|
453
|
-
|
453
|
+
|
454
454
|
def initialize(name)
|
455
455
|
super
|
456
456
|
@rules = []
|
457
457
|
end
|
458
|
-
|
458
|
+
|
459
459
|
# Adds a new rule to the set.
|
460
460
|
def add_rule(rule)
|
461
461
|
@rules << rule
|
462
462
|
end
|
463
|
-
|
463
|
+
|
464
464
|
def count
|
465
465
|
@rules.length
|
466
466
|
end
|
467
|
-
|
467
|
+
|
468
468
|
def each
|
469
469
|
@rules.each {|rule| yield rule}
|
470
470
|
end
|
471
|
-
end
|
472
|
-
|
471
|
+
end
|
472
|
+
|
473
473
|
# A rule in a RuleSet (a single Rule line in the tz data).
|
474
474
|
#
|
475
475
|
# @private
|
476
476
|
class TZDataRule #:nodoc:
|
477
477
|
include TZDataParserUtils
|
478
|
-
|
478
|
+
|
479
479
|
attr_reader :from
|
480
480
|
attr_reader :to
|
481
481
|
attr_reader :type
|
@@ -484,15 +484,15 @@ module TZInfo
|
|
484
484
|
attr_reader :at_time
|
485
485
|
attr_reader :save
|
486
486
|
attr_reader :letter
|
487
|
-
|
487
|
+
|
488
488
|
def initialize(from, to, type, in_month, on_day, at_time, save, letter)
|
489
489
|
@from = parse_from(from)
|
490
490
|
@to = parse_to(to)
|
491
|
-
|
491
|
+
|
492
492
|
# replace a to of :only with the from year
|
493
493
|
raise 'to cannot be only if from is minimum' if @to == :only && @from == :min
|
494
|
-
@to = @from if @to == :only
|
495
|
-
|
494
|
+
@to = @from if @to == :only
|
495
|
+
|
496
496
|
@type = parse_type(type)
|
497
497
|
@in_month = parse_month(in_month)
|
498
498
|
@on_day = TZDataDayOfMonth.new(on_day)
|
@@ -500,22 +500,22 @@ module TZInfo
|
|
500
500
|
@save = parse_offset(save)
|
501
501
|
@letter = parse_letter(letter)
|
502
502
|
end
|
503
|
-
|
503
|
+
|
504
504
|
def activate(year)
|
505
505
|
# The following test ignores yearistype at present (currently unused in
|
506
506
|
# the data. parse_type currently excepts on encountering a year type.
|
507
|
-
if (@from == :min || @from <= year) && (@to == :max || @to >= year)
|
507
|
+
if (@from == :min || @from <= year) && (@to == :max || @to >= year)
|
508
508
|
TZDataActivatedRule.new(self, year)
|
509
509
|
else
|
510
510
|
nil
|
511
511
|
end
|
512
512
|
end
|
513
|
-
|
513
|
+
|
514
514
|
def at_utc_time(year, utc_offset, std_offset)
|
515
515
|
@at_time.to_utc(utc_offset, std_offset,
|
516
516
|
year, @in_month, @on_day.to_absolute(year, @in_month))
|
517
517
|
end
|
518
|
-
|
518
|
+
|
519
519
|
private
|
520
520
|
def parse_from(from)
|
521
521
|
lower = from.downcase
|
@@ -527,7 +527,7 @@ module TZInfo
|
|
527
527
|
raise "Invalid from: #{from}"
|
528
528
|
end
|
529
529
|
end
|
530
|
-
|
530
|
+
|
531
531
|
def parse_to(to)
|
532
532
|
lower = to.downcase
|
533
533
|
if lower =~ /^max/
|
@@ -540,12 +540,12 @@ module TZInfo
|
|
540
540
|
raise "Invalid to: #{to}"
|
541
541
|
end
|
542
542
|
end
|
543
|
-
|
543
|
+
|
544
544
|
def parse_type(type)
|
545
545
|
raise "Unsupported rule type: #{type}" if type != '-'
|
546
546
|
nil
|
547
|
-
end
|
548
|
-
|
547
|
+
end
|
548
|
+
|
549
549
|
def parse_letter(letter)
|
550
550
|
if letter == '-'
|
551
551
|
nil
|
@@ -554,40 +554,40 @@ module TZInfo
|
|
554
554
|
end
|
555
555
|
end
|
556
556
|
end
|
557
|
-
|
557
|
+
|
558
558
|
# Base class for Zones and Links.
|
559
559
|
#
|
560
560
|
# @private
|
561
561
|
class TZDataDefinition #:nodoc:
|
562
562
|
include TZDataParserUtils
|
563
|
-
|
563
|
+
|
564
564
|
attr_reader :name
|
565
565
|
attr_reader :name_elements
|
566
566
|
attr_reader :path_elements
|
567
|
-
|
567
|
+
|
568
568
|
def initialize(name)
|
569
569
|
@name = name
|
570
|
-
|
570
|
+
|
571
571
|
# + and - aren't allowed in class names
|
572
572
|
@name_elements = name.gsub(/-/, '__m__').gsub(/\+/, '__p__').split(/\//)
|
573
573
|
@path_elements = @name_elements.clone
|
574
574
|
@path_elements.pop
|
575
|
-
end
|
576
|
-
|
575
|
+
end
|
576
|
+
|
577
577
|
# Creates necessary directories, the file, writes the class header and footer
|
578
|
-
# and yields to a block to write the content.
|
579
|
-
def create_file(output_dir)
|
578
|
+
# and yields to a block to write the content.
|
579
|
+
def create_file(output_dir)
|
580
580
|
dir = File.join(output_dir, 'definitions', @path_elements.join(File::SEPARATOR))
|
581
581
|
FileUtils.mkdir_p(dir)
|
582
|
-
|
582
|
+
|
583
583
|
open_file(File.join(output_dir, 'definitions', @name_elements.join(File::SEPARATOR)) + '.rb', 'w', :external_encoding => 'UTF-8', :universal_newline => true) do |file|
|
584
584
|
|
585
585
|
file.instance_variable_set(:@tz_indent, 0)
|
586
|
-
|
586
|
+
|
587
587
|
def file.indent(by)
|
588
588
|
@tz_indent += by
|
589
589
|
end
|
590
|
-
|
590
|
+
|
591
591
|
def file.puts(s)
|
592
592
|
super("#{' ' * @tz_indent}#{s}")
|
593
593
|
end
|
@@ -602,21 +602,21 @@ module TZInfo
|
|
602
602
|
file.puts('module Data')
|
603
603
|
file.indent(2)
|
604
604
|
file.puts('module Definitions')
|
605
|
-
file.indent(2)
|
606
|
-
|
607
|
-
@name_elements.each do |part|
|
605
|
+
file.indent(2)
|
606
|
+
|
607
|
+
@name_elements.each do |part|
|
608
608
|
file.puts("module #{part}")
|
609
609
|
file.indent(2)
|
610
610
|
end
|
611
|
-
|
611
|
+
|
612
612
|
file.puts('include TimezoneDefinition')
|
613
613
|
file.puts('')
|
614
|
-
|
614
|
+
|
615
615
|
yield file
|
616
|
-
|
616
|
+
|
617
617
|
@name_elements.each do
|
618
|
-
file.indent(-2)
|
619
|
-
file.puts('end')
|
618
|
+
file.indent(-2)
|
619
|
+
file.puts('end')
|
620
620
|
end
|
621
621
|
file.indent(-2)
|
622
622
|
file.puts('end') # end module Definitions
|
@@ -625,88 +625,88 @@ module TZInfo
|
|
625
625
|
file.indent(-2)
|
626
626
|
file.puts('end') # end module TZInfo
|
627
627
|
end
|
628
|
-
end
|
628
|
+
end
|
629
629
|
end
|
630
|
-
|
630
|
+
|
631
631
|
# A tz data Link.
|
632
632
|
#
|
633
633
|
# @private
|
634
634
|
class TZDataLink < TZDataDefinition #:nodoc:
|
635
635
|
include TZDataParserUtils
|
636
|
-
|
636
|
+
|
637
637
|
attr_reader :link_to
|
638
|
-
|
638
|
+
|
639
639
|
def initialize(name, link_to)
|
640
640
|
super(name)
|
641
641
|
@link_to = link_to
|
642
642
|
end
|
643
|
-
|
643
|
+
|
644
644
|
# Writes a module for this link.
|
645
645
|
def write_module(output_dir)
|
646
646
|
puts "writing link #{name}"
|
647
|
-
|
647
|
+
|
648
648
|
create_file(output_dir) {|file|
|
649
|
-
file.puts("linked_timezone #{quote_str(@name)}, #{quote_str(@link_to.name)}")
|
649
|
+
file.puts("linked_timezone #{quote_str(@name)}, #{quote_str(@link_to.name)}")
|
650
650
|
}
|
651
651
|
end
|
652
|
-
|
653
|
-
# Writes an index record for this link.
|
652
|
+
|
653
|
+
# Writes an index record for this link.
|
654
654
|
def write_index_record(file)
|
655
655
|
file.puts(" linked_timezone #{quote_str(@name)}")
|
656
656
|
end
|
657
657
|
end
|
658
|
-
|
658
|
+
|
659
659
|
# A tz data Zone. Each line from the tz data is loaded as a TZDataObservance.
|
660
660
|
#
|
661
661
|
# @private
|
662
662
|
class TZDataZone < TZDataDefinition #:nodoc:
|
663
663
|
include TZDataParserUtils
|
664
|
-
|
664
|
+
|
665
665
|
attr_reader :observances
|
666
|
-
|
666
|
+
|
667
667
|
def initialize(name, years)
|
668
668
|
super(name)
|
669
669
|
@years = years
|
670
670
|
@observances = []
|
671
671
|
end
|
672
|
-
|
673
|
-
def add_observance(observance)
|
672
|
+
|
673
|
+
def add_observance(observance)
|
674
674
|
@observances << observance
|
675
|
-
end
|
676
|
-
|
675
|
+
end
|
676
|
+
|
677
677
|
# Writes the module for the zone. Iterates all the periods and asks them
|
678
678
|
# to write all periods in the timezone.
|
679
|
-
def write_module(output_dir)
|
679
|
+
def write_module(output_dir)
|
680
680
|
puts "writing zone #{name}"
|
681
|
-
|
682
|
-
create_file(output_dir) {|file|
|
683
|
-
|
681
|
+
|
682
|
+
create_file(output_dir) {|file|
|
683
|
+
|
684
684
|
file.puts("timezone #{quote_str(@name)} do |tz|")
|
685
685
|
file.indent(2)
|
686
|
-
|
686
|
+
|
687
687
|
transitions = find_transitions
|
688
688
|
transitions.output_module(file)
|
689
|
-
|
689
|
+
|
690
690
|
file.indent(-2)
|
691
691
|
file.puts('end')
|
692
|
-
}
|
692
|
+
}
|
693
693
|
end
|
694
|
-
|
695
|
-
# Writes an index record for this zone.
|
694
|
+
|
695
|
+
# Writes an index record for this zone.
|
696
696
|
def write_index_record(file)
|
697
697
|
file.puts(" timezone #{quote_str(@name)}")
|
698
698
|
end
|
699
|
-
|
699
|
+
|
700
700
|
private
|
701
701
|
def find_transitions
|
702
702
|
transitions = TZDataTransitions.new(@years)
|
703
|
-
|
703
|
+
|
704
704
|
# algorithm from zic.c outzone
|
705
|
-
|
705
|
+
|
706
706
|
start_time = nil
|
707
707
|
until_time = nil
|
708
|
-
|
709
|
-
|
708
|
+
|
709
|
+
|
710
710
|
@observances.each_with_index {|observance, i|
|
711
711
|
std_offset = 0
|
712
712
|
use_start = i > 0
|
@@ -715,11 +715,11 @@ module TZInfo
|
|
715
715
|
start_zone_id = nil
|
716
716
|
start_utc_offset = observance.utc_offset
|
717
717
|
start_std_offset = 0
|
718
|
-
|
718
|
+
|
719
719
|
if observance.rule_set.count == 0
|
720
720
|
std_offset = observance.std_offset
|
721
721
|
start_zone_id = observance.format.expand(utc_offset, std_offset, nil)
|
722
|
-
|
722
|
+
|
723
723
|
if use_start
|
724
724
|
transitions << TZDataTransition.new(start_time, utc_offset, std_offset, start_zone_id)
|
725
725
|
use_start = false
|
@@ -727,38 +727,38 @@ module TZInfo
|
|
727
727
|
# zic algorithm only outputs this if std_offset is non-zero
|
728
728
|
# to get the initial LMT range, we output this regardless
|
729
729
|
transitions << TZDataTransition.new(nil, utc_offset, std_offset, start_zone_id)
|
730
|
-
end
|
730
|
+
end
|
731
731
|
else
|
732
732
|
@years.each {|year|
|
733
733
|
if use_until && year > observance.valid_until.year
|
734
734
|
break
|
735
735
|
end
|
736
|
-
|
736
|
+
|
737
737
|
activated_rules = []
|
738
|
-
|
738
|
+
|
739
739
|
observance.rule_set.each {|rule|
|
740
740
|
activated_rule = rule.activate(year)
|
741
741
|
activated_rules << activated_rule unless activated_rule.nil?
|
742
742
|
}
|
743
|
-
|
744
|
-
while true
|
743
|
+
|
744
|
+
while true
|
745
745
|
# turn until_time into UTC using the current utc_offset and std_offset
|
746
746
|
until_time = observance.valid_until.to_utc(utc_offset, std_offset) if use_until
|
747
|
-
|
747
|
+
|
748
748
|
earliest = nil
|
749
749
|
|
750
|
-
activated_rules.each {|activated_rule|
|
750
|
+
activated_rules.each {|activated_rule|
|
751
751
|
# recalculate the time using the current std_offset
|
752
|
-
activated_rule.calculate_time(utc_offset, std_offset)
|
753
|
-
earliest = activated_rule if earliest.nil? || activated_rule.at < earliest.at
|
752
|
+
activated_rule.calculate_time(utc_offset, std_offset)
|
753
|
+
earliest = activated_rule if earliest.nil? || activated_rule.at < earliest.at
|
754
754
|
}
|
755
|
-
|
756
|
-
break if earliest.nil?
|
757
|
-
activated_rules.delete(earliest)
|
758
|
-
break if use_until && earliest.at >= until_time
|
759
|
-
std_offset = earliest.rule.save
|
755
|
+
|
756
|
+
break if earliest.nil?
|
757
|
+
activated_rules.delete(earliest)
|
758
|
+
break if use_until && earliest.at >= until_time
|
759
|
+
std_offset = earliest.rule.save
|
760
760
|
use_start = false if use_start && earliest.at == start_time
|
761
|
-
|
761
|
+
|
762
762
|
if use_start
|
763
763
|
if earliest.at < start_time
|
764
764
|
start_utc_offset = observance.utc_offset
|
@@ -766,49 +766,49 @@ module TZInfo
|
|
766
766
|
start_zone_id = observance.format.expand(start_utc_offset, earliest.rule.save, earliest.rule.letter)
|
767
767
|
next
|
768
768
|
end
|
769
|
-
|
769
|
+
|
770
770
|
if start_zone_id.nil? && start_utc_offset + start_std_offset == observance.utc_offset + std_offset
|
771
771
|
start_zone_id = observance.format.expand(start_utc_offset, earliest.rule.save, earliest.rule.letter)
|
772
772
|
end
|
773
773
|
end
|
774
|
-
|
774
|
+
|
775
775
|
zone_id = observance.format.expand(observance.utc_offset, earliest.rule.save, earliest.rule.letter)
|
776
776
|
transitions << TZDataTransition.new(earliest.at, observance.utc_offset, earliest.rule.save, zone_id)
|
777
|
-
end
|
777
|
+
end
|
778
778
|
}
|
779
779
|
end
|
780
|
-
|
780
|
+
|
781
781
|
if use_start
|
782
782
|
start_zone_id = observance.format.expand(nil, nil, nil) if start_zone_id.nil? && observance.format.fixed?
|
783
|
-
raise 'Could not determine time zone abbreviation to use just after until time' if start_zone_id.nil?
|
783
|
+
raise 'Could not determine time zone abbreviation to use just after until time' if start_zone_id.nil?
|
784
784
|
transitions << TZDataTransition.new(start_time, start_utc_offset, start_std_offset, start_zone_id)
|
785
785
|
end
|
786
|
-
|
787
|
-
start_time = observance.valid_until.to_utc(utc_offset, std_offset) if use_until
|
786
|
+
|
787
|
+
start_time = observance.valid_until.to_utc(utc_offset, std_offset) if use_until
|
788
788
|
}
|
789
|
-
|
789
|
+
|
790
790
|
transitions
|
791
791
|
end
|
792
792
|
end
|
793
|
-
|
793
|
+
|
794
794
|
# A observance within a zone (a line within the zone definition).
|
795
795
|
#
|
796
796
|
# @private
|
797
797
|
class TZDataObservance #:nodoc:
|
798
798
|
include TZDataParserUtils
|
799
|
-
|
799
|
+
|
800
800
|
attr_reader :utc_offset
|
801
801
|
attr_reader :rule_set
|
802
802
|
attr_reader :format
|
803
803
|
attr_reader :valid_until
|
804
|
-
|
804
|
+
|
805
805
|
def initialize(utc_offset, rule_set, format, valid_until)
|
806
806
|
@utc_offset = parse_offset(utc_offset)
|
807
|
-
@rule_set = rule_set
|
807
|
+
@rule_set = rule_set
|
808
808
|
@format = TZDataFormat.new(format)
|
809
|
-
@valid_until = valid_until.nil? ? nil : TZDataUntil.new(valid_until)
|
810
|
-
end
|
811
|
-
|
809
|
+
@valid_until = valid_until.nil? ? nil : TZDataUntil.new(valid_until)
|
810
|
+
end
|
811
|
+
|
812
812
|
def std_offset
|
813
813
|
if @rule_set.kind_of?(TZDataFixedOffsetRules)
|
814
814
|
@rule_set.offset
|
@@ -817,159 +817,159 @@ module TZInfo
|
|
817
817
|
end
|
818
818
|
end
|
819
819
|
end
|
820
|
-
|
820
|
+
|
821
821
|
# Collection of TZDataTransition instances used when building a zone class.
|
822
822
|
#
|
823
823
|
# @private
|
824
824
|
class TZDataTransitions #:nodoc:
|
825
825
|
include TZDataParserUtils
|
826
|
-
|
826
|
+
|
827
827
|
def initialize(years)
|
828
828
|
@years = years
|
829
829
|
@transitions = []
|
830
830
|
end
|
831
|
-
|
831
|
+
|
832
832
|
def << (transition)
|
833
833
|
@transitions << transition
|
834
|
-
end
|
835
|
-
|
834
|
+
end
|
835
|
+
|
836
836
|
def output_module(file)
|
837
837
|
optimize
|
838
|
-
|
838
|
+
|
839
839
|
# Try and end on a transition to std if one happens in the last year.
|
840
|
-
if @transitions.length > 1 &&
|
840
|
+
if @transitions.length > 1 &&
|
841
841
|
@transitions.last.std_offset != 0 &&
|
842
842
|
@transitions[@transitions.length - 2].std_offset == 0 &&
|
843
843
|
@transitions[@transitions.length - 2].at_utc.year == @years.max
|
844
|
-
|
844
|
+
|
845
845
|
transitions = @transitions[0..@transitions.length - 2]
|
846
846
|
else
|
847
847
|
transitions = @transitions
|
848
848
|
end
|
849
|
-
|
849
|
+
|
850
850
|
process_offsets(file)
|
851
851
|
file.puts('')
|
852
|
-
|
853
|
-
transitions.each do |t|
|
852
|
+
|
853
|
+
transitions.each do |t|
|
854
854
|
t.write(file)
|
855
|
-
end
|
855
|
+
end
|
856
856
|
end
|
857
|
-
|
857
|
+
|
858
858
|
private
|
859
859
|
def optimize
|
860
860
|
@transitions.sort!
|
861
|
-
|
861
|
+
|
862
862
|
# Optimization logic from zic.c writezone.
|
863
|
-
|
863
|
+
|
864
864
|
from_i = 0
|
865
865
|
to_i = 0
|
866
|
-
|
866
|
+
|
867
867
|
while from_i < @transitions.length
|
868
|
-
if to_i > 1 &&
|
868
|
+
if to_i > 1 &&
|
869
869
|
!@transitions[from_i].at_utc.nil? &&
|
870
870
|
!@transitions[to_i - 1].at_utc.nil? &&
|
871
871
|
@transitions[from_i].at_utc + Rational(@transitions[to_i - 1].total_offset, 86400) <=
|
872
872
|
@transitions[to_i - 1].at_utc + Rational(@transitions[to_i - 2].total_offset, 86400)
|
873
|
-
|
874
|
-
@transitions[to_i - 1] = @transitions[from_i].clone_with_at(@transitions[to_i - 1].at_utc)
|
873
|
+
|
874
|
+
@transitions[to_i - 1] = @transitions[from_i].clone_with_at(@transitions[to_i - 1].at_utc)
|
875
875
|
from_i += 1
|
876
876
|
next
|
877
877
|
end
|
878
|
-
|
879
|
-
# Shuffle transitions up, eliminating any redundant transitions
|
878
|
+
|
879
|
+
# Shuffle transitions up, eliminating any redundant transitions
|
880
880
|
# along the way.
|
881
881
|
if to_i == 0 ||
|
882
882
|
@transitions[to_i - 1].utc_offset != @transitions[from_i].utc_offset ||
|
883
883
|
@transitions[to_i - 1].std_offset != @transitions[from_i].std_offset ||
|
884
884
|
@transitions[to_i - 1].zone_id != @transitions[from_i].zone_id
|
885
|
-
|
885
|
+
|
886
886
|
@transitions[to_i] = @transitions[from_i]
|
887
|
-
to_i += 1
|
887
|
+
to_i += 1
|
888
888
|
end
|
889
|
-
|
889
|
+
|
890
890
|
from_i += 1
|
891
|
-
end
|
892
|
-
|
891
|
+
end
|
892
|
+
|
893
893
|
if to_i > 0
|
894
894
|
@transitions = @transitions[0..to_i - 1]
|
895
895
|
else
|
896
896
|
@transitions = []
|
897
|
-
end
|
897
|
+
end
|
898
898
|
end
|
899
|
-
|
900
|
-
def quote_zone_id(zone_id)
|
899
|
+
|
900
|
+
def quote_zone_id(zone_id)
|
901
901
|
if zone_id =~ %r{[\-+']}
|
902
|
-
":#{quote_str(zone_id)}"
|
902
|
+
":#{quote_str(zone_id)}"
|
903
903
|
else
|
904
904
|
":#{zone_id}"
|
905
905
|
end
|
906
|
-
end
|
907
|
-
|
906
|
+
end
|
907
|
+
|
908
908
|
def process_offsets(file)
|
909
909
|
# A bit of a hack at the moment. The offset used to be output with
|
910
910
|
# each period (pair of transitions). They are now separated from the
|
911
911
|
# transition data. The code should probably be changed at some point to
|
912
|
-
# setup the offsets at an earlier stage.
|
913
|
-
|
912
|
+
# setup the offsets at an earlier stage.
|
913
|
+
|
914
914
|
# Assume that when this is called, the first transition is the Local
|
915
915
|
# Mean Time initial rule or a transition with no time that defines the
|
916
916
|
# offset for the entire zone.
|
917
|
-
|
917
|
+
|
918
918
|
offsets = []
|
919
|
-
|
919
|
+
|
920
920
|
# Find the first std offset. Timezones always start in std.
|
921
921
|
@transitions.each do |t|
|
922
922
|
if t.std_offset == 0
|
923
|
-
offset = {:utc_offset => t.utc_offset,
|
923
|
+
offset = {:utc_offset => t.utc_offset,
|
924
924
|
:std_offset => t.std_offset,
|
925
925
|
:zone_id => t.zone_id,
|
926
926
|
:name => 'o0'}
|
927
|
-
|
927
|
+
|
928
928
|
offsets << offset
|
929
929
|
break
|
930
930
|
end
|
931
931
|
end
|
932
|
-
|
932
|
+
|
933
933
|
@transitions.each do |t|
|
934
|
-
offset = offsets.find do |o|
|
934
|
+
offset = offsets.find do |o|
|
935
935
|
o[:utc_offset] == t.utc_offset &&
|
936
936
|
o[:std_offset] == t.std_offset &&
|
937
937
|
o[:zone_id] == t.zone_id
|
938
938
|
end
|
939
|
-
|
939
|
+
|
940
940
|
unless offset
|
941
|
-
offset = {:utc_offset => t.utc_offset,
|
941
|
+
offset = {:utc_offset => t.utc_offset,
|
942
942
|
:std_offset => t.std_offset,
|
943
943
|
:zone_id => t.zone_id,
|
944
944
|
:name => "o#{offsets.length}"}
|
945
|
-
|
945
|
+
|
946
946
|
offsets << offset
|
947
947
|
end
|
948
|
-
|
948
|
+
|
949
949
|
t.offset_name = offset[:name]
|
950
950
|
end
|
951
|
-
|
951
|
+
|
952
952
|
offsets.each do |offset|
|
953
953
|
file.puts("tz.offset :#{offset[:name]}, #{offset[:utc_offset]}, #{offset[:std_offset]}, #{quote_zone_id(offset[:zone_id])}")
|
954
954
|
end
|
955
|
-
|
955
|
+
|
956
956
|
end
|
957
957
|
end
|
958
|
-
|
958
|
+
|
959
959
|
# A transition that will be used to write the periods in a zone class.
|
960
960
|
#
|
961
961
|
# @private
|
962
962
|
class TZDataTransition #:nodoc:
|
963
963
|
include Comparable
|
964
|
-
|
964
|
+
|
965
965
|
EPOCH = DateTime.new(1970, 1, 1)
|
966
|
-
|
966
|
+
|
967
967
|
attr_reader :at_utc
|
968
968
|
attr_reader :utc_offset
|
969
969
|
attr_reader :std_offset
|
970
970
|
attr_reader :zone_id
|
971
971
|
attr_accessor :offset_name
|
972
|
-
|
972
|
+
|
973
973
|
def initialize(at_utc, utc_offset, std_offset, zone_id)
|
974
974
|
@at_utc = at_utc
|
975
975
|
@utc_offset = utc_offset
|
@@ -977,11 +977,11 @@ module TZInfo
|
|
977
977
|
@zone_id = zone_id
|
978
978
|
@offset_name = nil
|
979
979
|
end
|
980
|
-
|
980
|
+
|
981
981
|
def to_s
|
982
982
|
"At #{at_utc} UTC switch to UTC offset #{@utc_offset} with std offset #{@std_offset}, zone id #{@zone_id}"
|
983
983
|
end
|
984
|
-
|
984
|
+
|
985
985
|
def <=>(transition)
|
986
986
|
if @at_utc == transition.at_utc
|
987
987
|
0
|
@@ -989,29 +989,29 @@ module TZInfo
|
|
989
989
|
-1
|
990
990
|
elsif transition.nil?
|
991
991
|
1
|
992
|
-
else
|
992
|
+
else
|
993
993
|
@at_utc - transition.at_utc
|
994
994
|
end
|
995
995
|
end
|
996
|
-
|
996
|
+
|
997
997
|
def total_offset
|
998
998
|
@utc_offset + @std_offset
|
999
999
|
end
|
1000
|
-
|
1000
|
+
|
1001
1001
|
def clone_with_at(at_utc)
|
1002
1002
|
TZDataTransition.new(at_utc, @utc_offset, @std_offset, @zone_id)
|
1003
1003
|
end
|
1004
|
-
|
1005
|
-
def write(file)
|
1004
|
+
|
1005
|
+
def write(file)
|
1006
1006
|
if @at_utc
|
1007
|
-
file.puts "tz.transition #{@at_utc.year}, #{@at_utc.mon}, :#{@offset_name}, #{timestamp_parameters(@at_utc)}"
|
1008
|
-
end
|
1007
|
+
file.puts "tz.transition #{@at_utc.year}, #{@at_utc.mon}, :#{@offset_name}, #{timestamp_parameters(@at_utc)}"
|
1008
|
+
end
|
1009
1009
|
end
|
1010
|
-
|
1010
|
+
|
1011
1011
|
private
|
1012
1012
|
def timestamp_parameters(datetime)
|
1013
1013
|
timestamp = ((datetime - EPOCH) * 86400).to_i
|
1014
|
-
|
1014
|
+
|
1015
1015
|
if timestamp < 0 || timestamp > 2147483647
|
1016
1016
|
# Output DateTime parameters as well as a timestamp for platforms
|
1017
1017
|
# where Time doesn't support negative or 64-bit values.
|
@@ -1021,7 +1021,7 @@ module TZInfo
|
|
1021
1021
|
end
|
1022
1022
|
end
|
1023
1023
|
end
|
1024
|
-
|
1024
|
+
|
1025
1025
|
# An instance of a rule for a year.
|
1026
1026
|
#
|
1027
1027
|
# @private
|
@@ -1029,18 +1029,18 @@ module TZInfo
|
|
1029
1029
|
attr_reader :rule
|
1030
1030
|
attr_reader :year
|
1031
1031
|
attr_reader :at
|
1032
|
-
|
1032
|
+
|
1033
1033
|
def initialize(rule, year)
|
1034
1034
|
@rule = rule
|
1035
1035
|
@year = year
|
1036
1036
|
@at = nil
|
1037
1037
|
end
|
1038
|
-
|
1038
|
+
|
1039
1039
|
def calculate_time(utc_offset, std_offset)
|
1040
1040
|
@at = @rule.at_utc_time(@year, utc_offset, std_offset)
|
1041
1041
|
end
|
1042
1042
|
end
|
1043
|
-
|
1043
|
+
|
1044
1044
|
# A tz data time definition - a sign (1 or -1), hour, minute, second and
|
1045
1045
|
# reference (:utc, :standard or :wall_clock).
|
1046
1046
|
#
|
@@ -1051,15 +1051,15 @@ module TZInfo
|
|
1051
1051
|
attr_reader :minute
|
1052
1052
|
attr_reader :second
|
1053
1053
|
attr_reader :ref
|
1054
|
-
|
1054
|
+
|
1055
1055
|
def initialize(spec)
|
1056
1056
|
raise "Invalid time: #{spec}" if spec !~ /^(-?)([0-9]+)(:([0-9]+)(:([0-9]+))?)?([wguzs])?$/
|
1057
|
-
|
1057
|
+
|
1058
1058
|
@sign = $1 == '-' ? -1 : 1
|
1059
1059
|
@hour = $2.to_i
|
1060
1060
|
@minute = $4.nil? ? 0 : $4.to_i
|
1061
1061
|
@second = $6.nil? ? 0 : $6.to_i
|
1062
|
-
|
1062
|
+
|
1063
1063
|
if $7 == 's'
|
1064
1064
|
@ref = :standard
|
1065
1065
|
elsif $7 == 'g' || $7 == 'u' || $7 == 'z'
|
@@ -1068,9 +1068,9 @@ module TZInfo
|
|
1068
1068
|
@ref = :wall_clock
|
1069
1069
|
end
|
1070
1070
|
end
|
1071
|
-
|
1071
|
+
|
1072
1072
|
# Converts the time to UTC given a utc_offset and std_offset.
|
1073
|
-
def to_utc(utc_offset, std_offset, year, month, day)
|
1073
|
+
def to_utc(utc_offset, std_offset, year, month, day)
|
1074
1074
|
result = if @hour > 24 || @hour == 24 && (@minute > 0 || @second > 0) || @sign != 1
|
1075
1075
|
DateTime.new(year, month, day, 0, 0, 0) + Rational(@sign * (@second + (@minute + @hour * 60) * 60), 86400)
|
1076
1076
|
else
|
@@ -1078,12 +1078,12 @@ module TZInfo
|
|
1078
1078
|
end
|
1079
1079
|
|
1080
1080
|
offset = 0
|
1081
|
-
offset = offset + utc_offset if @ref == :standard || @ref == :wall_clock
|
1082
|
-
offset = offset + std_offset if @ref == :wall_clock
|
1083
|
-
result - Rational(offset, 86400)
|
1081
|
+
offset = offset + utc_offset if @ref == :standard || @ref == :wall_clock
|
1082
|
+
offset = offset + std_offset if @ref == :wall_clock
|
1083
|
+
result - Rational(offset, 86400)
|
1084
1084
|
end
|
1085
1085
|
end
|
1086
|
-
|
1086
|
+
|
1087
1087
|
# A tz data day of the month reference. Can either be an absolute day,
|
1088
1088
|
# a last week day or a week day >= or <= than a specific day of month.
|
1089
1089
|
#
|
@@ -1093,10 +1093,10 @@ module TZInfo
|
|
1093
1093
|
attr_reader :day_of_month
|
1094
1094
|
attr_reader :day_of_week
|
1095
1095
|
attr_reader :operator
|
1096
|
-
|
1096
|
+
|
1097
1097
|
def initialize(spec)
|
1098
1098
|
raise "Invalid on: #{spec}" if spec !~ /^([0-9]+)|(last([A-Za-z]+))|(([A-Za-z]+)([<>]=)([0-9]+))$/
|
1099
|
-
|
1099
|
+
|
1100
1100
|
if $1
|
1101
1101
|
@type = :absolute
|
1102
1102
|
@day_of_month = $1.to_i
|
@@ -1110,21 +1110,21 @@ module TZInfo
|
|
1110
1110
|
@day_of_month = $7.to_i
|
1111
1111
|
end
|
1112
1112
|
end
|
1113
|
-
|
1113
|
+
|
1114
1114
|
# Returns the absolute day of month for the given year and month.
|
1115
1115
|
def to_absolute(year, month)
|
1116
1116
|
case @type
|
1117
1117
|
when :last
|
1118
|
-
last_day_in_month = (Date.new(year, month, 1) >> 1) - 1
|
1118
|
+
last_day_in_month = (Date.new(year, month, 1) >> 1) - 1
|
1119
1119
|
offset = last_day_in_month.wday - @day_of_week
|
1120
1120
|
offset = offset + 7 if offset < 0
|
1121
1121
|
(last_day_in_month - offset).day
|
1122
1122
|
when :comparison
|
1123
|
-
pivot = Date.new(year, month, @day_of_month)
|
1123
|
+
pivot = Date.new(year, month, @day_of_month)
|
1124
1124
|
offset = @day_of_week - pivot.wday
|
1125
1125
|
offset = -offset if @operator == :less_equal
|
1126
1126
|
offset = offset + 7 if offset < 0
|
1127
|
-
offset = -offset if @operator == :less_equal
|
1127
|
+
offset = -offset if @operator == :less_equal
|
1128
1128
|
result = pivot + offset
|
1129
1129
|
if result.month != pivot.month
|
1130
1130
|
puts self.inspect
|
@@ -1132,12 +1132,12 @@ module TZInfo
|
|
1132
1132
|
puts month
|
1133
1133
|
end
|
1134
1134
|
raise 'No suitable date found' if result.month != pivot.month
|
1135
|
-
result.day
|
1135
|
+
result.day
|
1136
1136
|
else #absolute
|
1137
1137
|
@day_of_month
|
1138
1138
|
end
|
1139
1139
|
end
|
1140
|
-
|
1140
|
+
|
1141
1141
|
private
|
1142
1142
|
def parse_day_of_week(day_of_week)
|
1143
1143
|
lower = day_of_week.downcase
|
@@ -1159,7 +1159,7 @@ module TZInfo
|
|
1159
1159
|
raise "Invalid day of week: #{day_of_week}"
|
1160
1160
|
end
|
1161
1161
|
end
|
1162
|
-
|
1162
|
+
|
1163
1163
|
def parse_operator(operator)
|
1164
1164
|
if operator == '>='
|
1165
1165
|
:greater_equal
|
@@ -1169,40 +1169,40 @@ module TZInfo
|
|
1169
1169
|
raise "Invalid operator: #{operator}"
|
1170
1170
|
end
|
1171
1171
|
end
|
1172
|
-
end
|
1173
|
-
|
1172
|
+
end
|
1173
|
+
|
1174
1174
|
# A tz data Zone until reference.
|
1175
1175
|
#
|
1176
1176
|
# @private
|
1177
1177
|
class TZDataUntil #:nodoc:
|
1178
1178
|
include TZDataParserUtils
|
1179
|
-
|
1179
|
+
|
1180
1180
|
attr_reader :year
|
1181
1181
|
attr_reader :month
|
1182
1182
|
attr_reader :day
|
1183
1183
|
attr_reader :time
|
1184
|
-
|
1185
|
-
def initialize(spec)
|
1186
|
-
parts = spec.split(/\s+/)
|
1184
|
+
|
1185
|
+
def initialize(spec)
|
1186
|
+
parts = spec.split(/\s+/)
|
1187
1187
|
raise "Invalid until: #{spec}" if parts.length < 1
|
1188
|
-
|
1188
|
+
|
1189
1189
|
@year = parts[0].to_i
|
1190
1190
|
@month = parts.length > 1 ? parse_month(parts[1]) : 1
|
1191
1191
|
@day = TZDataDayOfMonth.new(parts.length > 2 ? parts[2] : '1')
|
1192
1192
|
@time = TZDataTime.new(parts.length > 3 ? parts[3] : '00:00')
|
1193
1193
|
end
|
1194
|
-
|
1194
|
+
|
1195
1195
|
# Converts the reference to a UTC DateTime.
|
1196
1196
|
def to_utc(utc_offset, std_offset)
|
1197
|
-
@time.to_utc(utc_offset, std_offset, @year, @month, @day.to_absolute(@year, @month))
|
1197
|
+
@time.to_utc(utc_offset, std_offset, @year, @month, @day.to_absolute(@year, @month))
|
1198
1198
|
end
|
1199
1199
|
end
|
1200
|
-
|
1200
|
+
|
1201
1201
|
# A tz data Zone format string. Either alternate standard/daylight-savings,
|
1202
1202
|
# substitution (%s) format or a fixed string.
|
1203
1203
|
#
|
1204
1204
|
# @private
|
1205
|
-
class TZDataFormat #:nodoc:
|
1205
|
+
class TZDataFormat #:nodoc:
|
1206
1206
|
def initialize(spec)
|
1207
1207
|
if spec =~ /\A([^\/]*)\/(.*)\z/
|
1208
1208
|
@type = :alternate
|
@@ -1216,7 +1216,7 @@ module TZInfo
|
|
1216
1216
|
@abbrev = spec
|
1217
1217
|
end
|
1218
1218
|
end
|
1219
|
-
|
1219
|
+
|
1220
1220
|
# Expands given the base offset to UTC, the current daylight savings
|
1221
1221
|
# offset and rule string.
|
1222
1222
|
def expand(utc_offset, std_offset, rule_string)
|
@@ -1232,14 +1232,14 @@ module TZInfo
|
|
1232
1232
|
end
|
1233
1233
|
else
|
1234
1234
|
@abbrev
|
1235
|
-
end
|
1235
|
+
end
|
1236
1236
|
end
|
1237
|
-
|
1237
|
+
|
1238
1238
|
# True if the format requires substitutions (%s or %z).
|
1239
1239
|
def subst?
|
1240
1240
|
@type == :subst
|
1241
1241
|
end
|
1242
|
-
|
1242
|
+
|
1243
1243
|
# Is a fixed format string.
|
1244
1244
|
def fixed?
|
1245
1245
|
@type == :fixed
|
@@ -1277,67 +1277,67 @@ module TZInfo
|
|
1277
1277
|
end
|
1278
1278
|
end
|
1279
1279
|
end
|
1280
|
-
|
1280
|
+
|
1281
1281
|
# A location (latitude + longitude)
|
1282
1282
|
#
|
1283
1283
|
# @private
|
1284
1284
|
class TZDataLocation #:nodoc:
|
1285
1285
|
attr_reader :latitude
|
1286
1286
|
attr_reader :longitude
|
1287
|
-
|
1288
|
-
# Constructs a new TZDataLocation from a string in ISO 6709
|
1289
|
-
# sign-degrees-minutes-seconds format, either +-DDMM+-DDDMM
|
1290
|
-
# or +-DDMMSS+-DDDMMSS, first latitude (+ is north),
|
1287
|
+
|
1288
|
+
# Constructs a new TZDataLocation from a string in ISO 6709
|
1289
|
+
# sign-degrees-minutes-seconds format, either +-DDMM+-DDDMM
|
1290
|
+
# or +-DDMMSS+-DDDMMSS, first latitude (+ is north),
|
1291
1291
|
# then longitude (+ is east).
|
1292
1292
|
def initialize(coordinates)
|
1293
1293
|
if coordinates !~ /^([+\-])([0-9]{2})([0-9]{2})([0-9]{2})?([+\-])([0-9]{3})([0-9]{2})([0-9]{2})?$/
|
1294
1294
|
raise "Invalid coordinates: #{coordinates}"
|
1295
1295
|
end
|
1296
|
-
|
1296
|
+
|
1297
1297
|
@latitude = Rational($2.to_i) + Rational($3.to_i, 60)
|
1298
1298
|
@latitude += Rational($4.to_i, 3600) unless $4.nil?
|
1299
1299
|
@latitude = -@latitude if $1 == '-'
|
1300
|
-
|
1300
|
+
|
1301
1301
|
@longitude = Rational($6.to_i) + Rational($7.to_i, 60)
|
1302
1302
|
@longitude += Rational($8.to_i, 3600) unless $8.nil?
|
1303
1303
|
@longitude = -@longitude if $5 == '-'
|
1304
1304
|
end
|
1305
|
-
end
|
1305
|
+
end
|
1306
1306
|
|
1307
1307
|
# @private
|
1308
1308
|
TZDataCountryTimezone = Struct.new(:timezone, :description, :location) #:nodoc:
|
1309
|
-
|
1309
|
+
|
1310
1310
|
# An ISO 3166 country.
|
1311
1311
|
#
|
1312
1312
|
# @private
|
1313
1313
|
class TZDataCountry #:nodoc:
|
1314
1314
|
include TZDataParserUtils
|
1315
|
-
|
1315
|
+
|
1316
1316
|
attr_reader :code
|
1317
1317
|
attr_reader :name
|
1318
1318
|
attr_reader :zones
|
1319
|
-
|
1319
|
+
|
1320
1320
|
def initialize(code, name)
|
1321
1321
|
@code = code
|
1322
1322
|
@name = name
|
1323
1323
|
@zones = []
|
1324
1324
|
end
|
1325
|
-
|
1325
|
+
|
1326
1326
|
# Adds a TZDataCountryTimezone
|
1327
|
-
def add_zone(zone)
|
1328
|
-
@zones << zone
|
1329
|
-
end
|
1330
|
-
|
1327
|
+
def add_zone(zone)
|
1328
|
+
@zones << zone
|
1329
|
+
end
|
1330
|
+
|
1331
1331
|
def write_index_record(file)
|
1332
|
-
s = " country #{quote_str(@code)}, #{quote_str(@name)}"
|
1332
|
+
s = " country #{quote_str(@code)}, #{quote_str(@name)}"
|
1333
1333
|
s << ' do |c|' if @zones.length > 0
|
1334
|
-
|
1334
|
+
|
1335
1335
|
file.puts s
|
1336
|
-
|
1336
|
+
|
1337
1337
|
@zones.each do |zone|
|
1338
|
-
file.puts " c.timezone #{quote_str(zone.timezone.name)}, #{zone.location.latitude.numerator}, #{zone.location.latitude.denominator}, #{zone.location.longitude.numerator}, #{zone.location.longitude.denominator}#{zone.description.nil? ? '' : ', ' + quote_str(zone.description)}"
|
1338
|
+
file.puts " c.timezone #{quote_str(zone.timezone.name)}, #{zone.location.latitude.numerator}, #{zone.location.latitude.denominator}, #{zone.location.longitude.numerator}, #{zone.location.longitude.denominator}#{zone.description.nil? ? '' : ', ' + quote_str(zone.description)}"
|
1339
1339
|
end
|
1340
|
-
|
1340
|
+
|
1341
1341
|
file.puts ' end' if @zones.length > 0
|
1342
1342
|
end
|
1343
1343
|
end
|