Object
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.
Whether to generate zone definitions (set to false to stop zones being generated).
Whether to generate country definitions (set to false to stop countries being generated).
Zones to exclude from generation when not using only_zones (set to an array containing zone identifiers).
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
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
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
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
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
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
Loads in the links and stores them in @zones.
# File lib/tzinfo/tzdataparser.rb, line 241 241: def load_links(file) 242: puts 'load_links: ' + file 243: 244: IO.foreach(@input_dir + File::SEPARATOR + file) {|line| 245: line = line.gsub(/#.*$/, '') 246: line = line.gsub(/\s+$/, '') 247: 248: if line =~ /^Link\s+([^\s]+)\s+([^\s]+)/ 249: name = $2 250: link_to = @zones[$1] 251: raise "Link to zone not found (#{name}->#{link_to})" if link_to.nil? 252: raise "Zone already defined: #{name}" if !@zones[name].nil? 253: @zones[name] = TZDataLink.new(name, link_to) 254: end 255: } 256: end
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
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
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
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.
Generated with the Darkfish Rdoc Generator 1.1.6.