Parent

Files

TZInfo::TZDataParser

Parses tzdata from elsie.nci.nih.gov/pub/ and transforms it into a set of Ruby modules that can be used through Timezone and Country.

Normally, this class wouldn’t be used. It is only run to update the timezone data and index modules.

Constants

MIN_YEAR

Minimum year that will be considered.

MAX_YEAR

Maximum year that will be considered.

Attributes

generate_zones[RW]

Whether to generate zone definitions (set to false to stop zones being generated).

generate_countries[RW]

Whether to generate country definitions (set to false to stop countries being generated).

only_zones[RW]

Limit the set of zones to generate (set to an array containing zone identifiers).

exclude_zones[RW]

Zones to exclude from generation when not using only_zones (set to an array containing zone identifiers).

Public Class Methods

new(input_dir, output_dir) click to toggle source

Initializes a new TZDataParser. input_dir must contain the extracted tzdata tarball. output_dir is the location to output the modules (in definitions and indexes directories).

    # File lib/tzinfo/tzdataparser.rb, line 59
59:     def initialize(input_dir, output_dir)
60:       super()
61:       @input_dir = input_dir
62:       @output_dir = output_dir      
63:       @rule_sets = {}
64:       @zones = {}
65:       @countries = {}
66:       @no_rules = TZDataNoRules.new
67:       @generate_zones = true
68:       @generate_countries = true
69:       @only_zones = []      
70:       @exclude_zones = []      
71:     end
parse_month(month) click to toggle source

Parses a month specified in the tz data and converts it to a number between 1 and 12 representing January to December.

     # File lib/tzinfo/tzdataparser.rb, line 114
114:     def self.parse_month(month)
115:       lower = month.downcase
116:       if lower =~ /^jan/
117:         @month = 1
118:       elsif lower =~ /^feb/
119:         @month = 2
120:       elsif lower =~ /^mar/
121:         @month = 3
122:       elsif lower =~ /^apr/
123:         @month = 4
124:       elsif lower =~ /^may/
125:         @month = 5
126:       elsif lower =~ /^jun/
127:         @month = 6
128:       elsif lower =~ /^jul/
129:         @month = 7
130:       elsif lower =~ /^aug/
131:         @month = 8
132:       elsif lower =~ /^sep/
133:         @month = 9
134:       elsif lower =~ /^oct/
135:         @month = 10
136:       elsif lower =~ /^nov/
137:         @month = 11
138:       elsif lower =~ /^dec/
139:         @month = 12
140:       else
141:         raise "Invalid month: #{month}"
142:       end
143:     end
parse_offset(offset) click to toggle source

Parses an offset string [-]h:m:s (minutes and seconds are optional). Returns the offset in seconds.

     # File lib/tzinfo/tzdataparser.rb, line 147
147:     def self.parse_offset(offset)
148:       raise "Invalid time: #{offset}" if offset !~ /^(-)?(?:([0-9]+)(?::([0-9]+)(?::([0-9]+))?)?)?$/
149:       
150:       negative = !$1.nil?      
151:       hour = $2.nil? ? 0 : $2.to_i
152:       minute = $3.nil? ? 0 : $3.to_i
153:       second = $4.nil? ? 0 : $4.to_i
154:       
155:       seconds = hour
156:       seconds = seconds * 60
157:       seconds = seconds + minute
158:       seconds = seconds * 60
159:       seconds = seconds + second
160:       seconds = -seconds if negative
161:       seconds
162:     end
quote_str(str) click to toggle source

Encloses the string in single quotes and escapes any single quotes in the content.

     # File lib/tzinfo/tzdataparser.rb, line 166
166:     def self.quote_str(str)
167:       "'#{str.gsub('\'', '\\\\\'')}'"
168:     end

Public Instance Methods

execute() click to toggle source

Reads the tzdata source and generates the classes. Takes a long time to run. Currently outputs debugging information to standard out.

     # File lib/tzinfo/tzdataparser.rb, line 75
 75:     def execute
 76:       Dir.foreach(@input_dir) {|file|
 77:         load_rules(file) if file =~ /^[^\.]+$/        
 78:       }  
 79:       
 80:       Dir.foreach(@input_dir) {|file|
 81:         load_zones(file) if file =~ /^[^\.]+$/        
 82:       }
 83:       
 84:       Dir.foreach(@input_dir) {|file|
 85:         load_links(file) if file =~ /^[^\.]+$/        
 86:       }
 87:       
 88:       load_countries
 89:       
 90:       if @generate_zones
 91:         modules = []
 92:         
 93:         if @only_zones.nil? || @only_zones.empty?
 94:           @zones.each_value {|zone|
 95:             zone.write_module(@output_dir) unless @exclude_zones.include?(zone.name)
 96:           }
 97:         else
 98:           @only_zones.each {|id|
 99:             zone = @zones[id]
100:             zone.write_module(@output_dir)            
101:           }          
102:         end
103:         
104:         write_timezones_index
105:       end
106:       
107:       if @generate_countries        
108:         write_countries_index
109:       end
110:     end

Private Instance Methods

get_rules(ref) click to toggle source

Gets a rules object for the given reference. Might be a named rule set, a fixed offset or an empty ruleset.

     # File lib/tzinfo/tzdataparser.rb, line 195
195:       def get_rules(ref)
196:         if ref == '-'
197:           @no_rules
198:         elsif ref =~ /^[0-9]+:[0-9]+$/
199:           TZDataFixedOffsetRules.new(TZDataParser.parse_offset(ref))
200:         else
201:           rule_set = @rule_sets[ref]
202:           raise "Ruleset not found: #{ref}" if rule_set.nil?    
203:           rule_set
204:         end  
205:       end
load_countries() click to toggle source

Loads countries from iso3166.tab and zone.tab and stores the result in @countries.

     # File lib/tzinfo/tzdataparser.rb, line 260
260:       def load_countries
261:         puts 'load_countries'
262:         
263:         IO.foreach(@input_dir + File::SEPARATOR + 'iso3166.tab') {|line|          
264:           if line =~ /^([A-Z]{2})\t(.*)$/
265:             code = $1
266:             name = $2
267:             @countries[code] = TZDataCountry.new(code, name)
268:           end
269:         }
270:         
271:         IO.foreach(@input_dir + File::SEPARATOR + 'zone.tab') {|line|          
272:           line.chomp!          
273: 
274:           if line =~ /^([A-Z]{2})\t([^\t]+)\t([^\t]+)(\t(.*))?$/
275:             code = $1
276:             location_str = $2
277:             zone_name = $3
278:             description = $5
279: 
280:             country = @countries[code]
281:             raise "Country not found: #{code}" if country.nil?
282:             
283:             location = TZDataLocation.new(location_str)
284:             
285:             zone = @zones[zone_name]
286:             raise "Zone not found: #{zone_name}" if zone.nil?                        
287:             
288:             description = nil if description == ''
289:             
290:             country.add_zone(TZDataCountryTimezone.new(zone, description, location))
291:           end
292:         }
293:       end
load_rules(file) click to toggle source

Loads all the Rule definitions from the tz data and stores them in @rule_sets.

     # File lib/tzinfo/tzdataparser.rb, line 173
173:       def load_rules(file)
174:         puts 'load_rules: ' + file
175:         
176:         IO.foreach(@input_dir + File::SEPARATOR + file) {|line|
177:           line = line.gsub(/#.*$/, '')
178:           line = line.gsub(/\s+$/, '')
179:         
180:           if line =~ /^Rule\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/
181:             
182:             name = $1    
183:             
184:             if @rule_sets[name].nil? 
185:               @rule_sets[name] = TZDataRuleSet.new(name) 
186:             end
187:             
188:             @rule_sets[name].add_rule(TZDataRule.new($2, $3, $4, $5, $6, $7, $8, $9))
189:           end          
190:         }                
191:       end
load_zones(file) click to toggle source

Loads in the Zone definitions from the tz data and stores them in @zones.

     # File lib/tzinfo/tzdataparser.rb, line 208
208:       def load_zones(file)
209:         puts 'load_zones: ' + file
210:         
211:         in_zone = nil
212:         
213:         IO.foreach(@input_dir + File::SEPARATOR + file) {|line|
214:           line = line.gsub(/#.*$/, '')
215:           line = line.gsub(/\s+$/, '')
216:         
217:           if in_zone
218:             if line =~ /^\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/              
219:               
220:               in_zone.add_observance(TZDataObservance.new($1, get_rules($2), $3, $5))
221:               
222:               in_zone = nil if $4.nil? 
223:             end
224:           else
225:             if line =~ /^Zone\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/              
226:               name = $1
227:               
228:               if @zones[name].nil? 
229:                 @zones[name] = TZDataZone.new(name)
230:               end                            
231:               
232:               @zones[name].add_observance(TZDataObservance.new($2, get_rules($3), $4, $6))
233:               
234:               in_zone = @zones[name] if !$5.nil?
235:             end
236:           end
237:         }
238:       end
write_countries_index() click to toggle source

Writes a country index file.

     # File lib/tzinfo/tzdataparser.rb, line 296
296:       def write_countries_index
297:         dir = @output_dir + File::SEPARATOR + 'indexes'      
298:         FileUtils.mkdir_p(dir)
299:         
300:         File.open(dir + File::SEPARATOR + 'countries.rb', 'w') {|file|
301:           file.binmode
302:           
303:           file.puts('module TZInfo')
304:           file.puts('  module Indexes')
305:           file.puts('    module Countries')
306:           file.puts('      include CountryIndexDefinition')
307:           file.puts('')
308:           
309:           countries = @countries.values.sort {|c1,c2| c1.code <=> c2.code}  
310:           countries.each {|country| country.write_index_record(file)}
311:                     
312:           file.puts('    end') # end module Countries                    
313:           file.puts('  end') # end module Indexes
314:           file.puts('end') # end module TZInfo
315:         }                      
316:       end
write_timezones_index() click to toggle source

Writes a timezone index file.

     # File lib/tzinfo/tzdataparser.rb, line 319
319:       def write_timezones_index
320:         dir = File.join(@output_dir, 'indexes')
321:         FileUtils.mkdir_p(dir)
322:         
323:         File.open(File.join(dir, 'timezones.rb'), 'w') do |file|
324:           file.binmode
325:           
326:           file.puts('module TZInfo')
327:           file.puts('  module Indexes')
328:           file.puts('    module Timezones')
329:           file.puts('      include TimezoneIndexDefinition')
330:           file.puts('')
331:           
332:           zones = @zones.values.sort {|t1,t2| t1.name <=> t2.name}
333:           zones.each {|zone| zone.write_index_record(file)}
334:           
335:           file.puts('    end') # end module Timezones
336:           file.puts('  end') # end module Indexes
337:           file.puts('end') # end module TZInfo
338:         end
339:         
340:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.