class TZInfo::TZDataTransitions
:nodoc:
Collection of TZDataTransition instances used when building a zone class.
def << (transition)
def << (transition) @transitions << transition end
def initialize
def initialize @transitions = [] end
def optimize
def optimize @transitions.sort! # Optimization logic from zic.c writezone. from_i = 0 to_i = 0 while from_i < @transitions.length if to_i > 1 && !@transitions[from_i].at_utc.nil? && !@transitions[to_i - 1].at_utc.nil? && @transitions[from_i].at_utc + Rational(@transitions[to_i - 1].total_offset, 86400) <= @transitions[to_i - 1].at_utc + Rational(@transitions[to_i - 2].total_offset, 86400) @transitions[to_i - 1] = @transitions[from_i].clone_with_at(@transitions[to_i - 1].at_utc) from_i += 1 next end # Shuffle transitions up, eliminating any redundant transitions # along the way. if to_i == 0 || @transitions[to_i - 1].utc_offset != @transitions[from_i].utc_offset || @transitions[to_i - 1].std_offset != @transitions[from_i].std_offset || @transitions[to_i - 1].zone_id != @transitions[from_i].zone_id @transitions[to_i] = @transitions[from_i] to_i += 1 end from_i += 1 end if to_i > 0 @transitions = @transitions[0..to_i - 1] else @transitions = [] end end
def output_module(file)
def output_module(file) optimize # Try and end on a transition to std if one happens in the last year. if @transitions.length > 1 && @transitions.last.std_offset != 0 && @transitions[@transitions.length - 2].std_offset == 0 && @transitions[@transitions.length - 2].at_utc.year == TZDataParser::MAX_YEAR transitions = @transitions[0..@transitions.length - 2] else transitions = @transitions end process_offsets(file) file.puts('') transitions.each do |t| t.write(file) end end
def process_offsets(file)
def process_offsets(file) # A bit of a hack at the moment. The offset used to be output with # each period (pair of transitions). They are now separated from the # transition data. The code should probably be changed at some point to # setup the offsets at an earlier stage. # Assume that when this is called, the first transition is the Local # Mean Time initial rule or a transition with no time that defines the # offset for the entire zone. offsets = [] # Find the first std offset. Timezones always start in std. @transitions.each do |t| if t.std_offset == 0 offset = {:utc_offset => t.utc_offset, :std_offset => t.std_offset, :zone_id => t.zone_id, :name => 'o0'} offsets << offset break end end @transitions.each do |t| offset = offsets.find do |o| o[:utc_offset] == t.utc_offset && o[:std_offset] == t.std_offset && o[:zone_id] == t.zone_id end unless offset offset = {:utc_offset => t.utc_offset, :std_offset => t.std_offset, :zone_id => t.zone_id, :name => "o#{offsets.length}"} offsets << offset end t.offset_name = offset[:name] end offsets.each do |offset| file.puts("tz.offset :#{offset[:name]}, #{offset[:utc_offset]}, #{offset[:std_offset]}, #{quote_zone_id(offset[:zone_id])}") end end
def quote_zone_id(zone_id)
def quote_zone_id(zone_id) if zone_id =~ %r{[\-+']} ":#{TZDataParser.quote_str(zone_id)}" else ":#{zone_id}" end end