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.
@@ -11,13 +11,22 @@ module TZInfo
11
11
  include TimezoneDefinition
12
12
 
13
13
  timezone 'Pacific/Kosrae' do |tz|
14
- tz.offset :o0, 39116, 0, :LMT
15
- tz.offset :o1, 39600, 0, :'+11'
16
- tz.offset :o2, 43200, 0, :'+12'
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 1900, 12, :o1, -2177491916, 52172317021, 21600
19
- tz.transition 1969, 9, :o2, -7988400, 58571881, 24
20
- tz.transition 1998, 12, :o1, 915105600
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, -43200, 0, :'-12'
17
- tz.offset :o3, 43200, 0, :'+12'
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 1969, 9, :o2, -7988400, 58571881, 24
21
- tz.transition 1993, 8, :o3, 745848000
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, 43200, 0, :'+12'
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 1969, 9, :o2, -7988400, 58571881, 24
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, 3, :o2, -877347000, 116660785, 48
21
- tz.transition 1944, 8, :o1, -800960400, 19450537, 8
22
- tz.transition 1979, 4, :o3, 294323400
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, 32276, 0, :LMT
15
- tz.offset :o1, 32400, 0, :'+09'
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 1900, 12, :o1, -2177485076, 52172318731, 21600
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, 37972, 0, :LMT
15
- tz.offset :o1, 39600, 0, :'+11'
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 1900, 12, :o1, -2177490772, 52172317307, 21600
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'
@@ -310,6 +310,7 @@ module TZInfo
310
310
  timezone 'Asia/Pontianak'
311
311
  timezone 'Asia/Pyongyang'
312
312
  timezone 'Asia/Qatar'
313
+ timezone 'Asia/Qostanay'
313
314
  timezone 'Asia/Qyzylorda'
314
315
  linked_timezone 'Asia/Rangoon'
315
316
  timezone 'Asia/Riyadh'
@@ -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