vendor/bundle/ruby/2.3.0/gems/tzinfo-1.2.2/lib/tzinfo/zoneinfo_timezone_info.rb
# Parses a zoneinfo file and intializes the DataTimezoneInfo structures.
Parses a zoneinfo file and intializes the DataTimezoneInfo structures.
Parses a zoneinfo file and intializes the DataTimezoneInfo structures .
def parse(file)
        magic, version, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt =
          check_read(file, 44).unpack('a4 a x15 NNNNNN')
        if magic != 'TZif'
          raise InvalidZoneinfoFile, "The file '{file.path}' does not start with the expected header."
        end
        if (version == '2' || version == '3') && RubyCoreSupport.time_supports_64bit
          file.seek(timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisgmtcnt + ttisstdcnt, IO::SEEK_CUR)
          prev_version = version
          magic, version, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt =
            check_read(file, 44).unpack('a4 a x15 NNNNNN')
          unless magic == 'TZif' && (version == prev_version)
            raise InvalidZoneinfoFile, "The file '{file.path}' contains an invalid 64-bit section header."
          end
          using_64bit = true
        elsif version != '3' && version != '2' && version != "\0"
          raise InvalidZoneinfoFile, "The file '{file.path}' contains a version of the zoneinfo format that is not currently supported."
        else
          using_64bit = false
        end
        unless leapcnt == 0
          raise InvalidZoneinfoFile, "The zoneinfo file '{file.path}' contains leap second data. TZInfo requires zoneinfo files that omit leap seconds."
        end
        transitions = []
        if using_64bit
          (0...timecnt).each do |i|
            high, low = check_read(file, 8).unpack('NN')
            transition_time = make_signed_int64(high, low)
            transitions << {:at => transition_time}          
          end
        else
          (0...timecnt).each do |i|
            transition_time = make_signed_int32(check_read(file, 4).unpack('N')[0])
            transitions << {:at => transition_time}          
          end
        end
        (0...timecnt).each do |i|
          localtime_type = check_read(file, 1).unpack('C')[0]
          transitions[i][:offset] = localtime_type
        end
        offsets = []
        (0...typecnt).each do |i|
          gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC')
          gmtoff = make_signed_int32(gmtoff)
          isdst = isdst == 1
          offset = {:utc_total_offset => gmtoff, :is_dst => isdst, :abbr_index => abbrind}
          unless isdst
            offset[:utc_offset] = gmtoff
            offset[:std_offset] = 0
          end
          offsets << offset
        end
        abbrev = check_read(file, charcnt)
        offsets.each do |o|
          abbrev_start = o[:abbr_index]         
          raise InvalidZoneinfoFile, "Abbreviation index is out of range in file '{file.path}'" unless abbrev_start < abbrev.length
          abbrev_end = abbrev.index("\0", abbrev_start)
          raise InvalidZoneinfoFile, "Missing abbreviation null terminator in file '{file.path}'" unless abbrev_end
          o[:abbr] = RubyCoreSupport.force_encoding(abbrev[abbrev_start...abbrev_end], 'UTF-8')
        end
        transitions.each do |t|
          if t[:offset] < 0 || t[:offset] >= offsets.length
            raise InvalidZoneinfoFile, "Invalid offset referenced by transition in file '{file.path}'."
          end
        end
        derive_offsets(transitions, offsets)
        derive_offsets(transitions.reverse, offsets)
        offsets.each do |o|
          if !o[:std_offset] && o[:is_dst]
            o[:std_offset] = 3600
            o[:utc_offset] = o[:utc_total_offset] - 3600
          end
        end
        first = nil
        offsets.each_with_index do |o, i|
          if !o[:is_dst]
            first = i
            break
          end
        end
        if first
          offset first, offsets[first][:utc_offset], offsets[first][:std_offset], offsets[first][:abbr].untaint.to_sym
        end
        offsets.each_with_index do |o, i|
          offset i, o[:utc_offset], o[:std_offset], o[:abbr].untaint.to_sym unless i == first
        end
        if !using_64bit && !RubyCoreSupport.time_supports_negative
          before_epoch, after_epoch = transitions.partition {|t| t[:at] < 0}
          if before_epoch.length > 0 && after_epoch.length > 0 && after_epoch.first[:at] != 0
            last_before = before_epoch.last
            last_before[:at] = 0
            transitions = [last_before] + after_epoch
          else
            transitions = after_epoch
          end
        end
         This is primarily intended to ignore the far in the past transition
         added in zic 2014c (at timestamp -2**63 in zic 2014c and at the
         approximate time of the big bang from zic 2014d).
        transitions.each do |t|
          at = t[:at]
          if at >= MIN_TIMESTAMP && at < MAX_TIMESTAMP
            time = Time.at(at).utc
            transition time.year, time.mon, t[:offset], at
          end
        end
      end
def parse ( file ) magic , version , ttisgmtcnt , ttisstdcnt , leapcnt , timecnt , typecnt , charcnt = check_read ( file , 44 ) . unpack ( 'a4 a x15 NNNNNN' ) if magic != 'TZif' raise InvalidZoneinfoFile , "The file '#{file.path}' does not start with the expected header." end if ( version == '2' || version == '3' ) && RubyCoreSupport . time_supports_64bit file . seek ( timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisgmtcnt + ttisstdcnt , IO :: SEEK_CUR ) prev_version = version magic , version , ttisgmtcnt , ttisstdcnt , leapcnt , timecnt , typecnt , charcnt = check_read ( file , 44 ) . unpack ( 'a4 a x15 NNNNNN' ) unless magic == 'TZif' && ( version == prev_version ) raise InvalidZoneinfoFile , "The file '#{file.path}' contains an invalid 64-bit section header." end using_64bit = true elsif version != '3' && version != '2' && version != "\0" raise InvalidZoneinfoFile , "The file '#{file.path}' contains a version of the zoneinfo format that is not currently supported." else using_64bit = false end unless leapcnt == 0 raise InvalidZoneinfoFile , "The zoneinfo file '#{file.path}' contains leap second data. TZInfo requires zoneinfo files that omit leap seconds." end transitions = [ ] if using_64bit ( 0 ... timecnt ) . each do | i | high , low = check_read ( file , 8 ) . unpack ( 'NN' ) transition_time = make_signed_int64 ( high , low ) transitions << { :at => transition_time } end else ( 0 ... timecnt ) . each do | i | transition_time = make_signed_int32 ( check_read ( file , 4 ) . unpack ( 'N' ) [ 0 ] ) transitions << { :at => transition_time } end end ( 0 ... timecnt ) . each do | i | localtime_type = check_read ( file , 1 ) . unpack ( 'C' ) [ 0 ] transitions [ i ] [ :offset ] = localtime_type end offsets = [ ] ( 0 ... typecnt ) . each do | i | gmtoff , isdst , abbrind = check_read ( file , 6 ) . unpack ( 'NCC' ) gmtoff = make_signed_int32 ( gmtoff ) isdst = isdst == 1 offset = { :utc_total_offset => gmtoff , :is_dst => isdst , :abbr_index => abbrind } unless isdst offset [ :utc_offset ] = gmtoff offset [ :std_offset ] = 0 end offsets << offset end abbrev = check_read ( file , charcnt ) offsets . each do | o | abbrev_start = o [ :abbr_index ] raise InvalidZoneinfoFile , "Abbreviation index is out of range in file '#{file.path}'" unless abbrev_start < abbrev . length abbrev_end = abbrev . index ( "\0" , abbrev_start ) raise InvalidZoneinfoFile , "Missing abbreviation null terminator in file '#{file.path}'" unless abbrev_end o [ :abbr ] = RubyCoreSupport . force_encoding ( abbrev [ abbrev_start ... abbrev_end ] , 'UTF-8' ) end transitions . each do | t | if t [ :offset ] < 0 || t [ :offset ] >= offsets . length raise InvalidZoneinfoFile , "Invalid offset referenced by transition in file '#{file.path}'." end end derive_offsets ( transitions , offsets ) derive_offsets ( transitions . reverse , offsets ) offsets . each do | o | if ! o [ :std_offset ] && o [ :is_dst ] o [ :std_offset ] = 3600 o [ :utc_offset ] = o [ :utc_total_offset ] - 3600 end end first = nil offsets . each_with_index do | o , i | if ! o [ :is_dst ] first = i break end end if first offset first , offsets [ first ] [ :utc_offset ] , offsets [ first ] [ :std_offset ] , offsets [ first ] [ :abbr ] . untaint . to_sym end offsets . each_with_index do | o , i | offset i , o [ :utc_offset ] , o [ :std_offset ] , o [ :abbr ] . untaint . to_sym unless i == first end if ! using_64bit && ! RubyCoreSupport . time_supports_negative before_epoch , after_epoch = transitions . partition { | t | t [ :at ] < 0 } if before_epoch . length > 0 && after_epoch . length > 0 && after_epoch . first [ :at ] != 0 last_before = before_epoch . last last_before [ :at ] = 0 transitions = [ last_before ] + after_epoch else transitions = after_epoch end end transitions . each do | t | at = t [ :at ] if at >= MIN_TIMESTAMP && at < MAX_TIMESTAMP time = Time . at ( at ) . utc transition time . year , time . mon , t [ :offset ] , at end end end
Parses a zoneinfo file and intializes the DataTimezoneInfo structures.
Parses a zoneinfo file and intializes the DataTimezoneInfo structures .
# Skip the first 32-bit section and read the header of the second 64-bit section # Derive the offsets from standard time (std_offset). # Assign anything left a standard offset of one hour # Find the first non-dst offset. This is used as the offset for the time # before the first transition. # Filter out transitions that are not supported by Time on this # platform. # Move the last transition before the epoch up to the epoch. This # allows for accurate conversions for all supported timestamps on the # platform. # Ignore transitions that occur outside of a defined window. The # transition index cannot handle a large range of transition times. # # This is primarily intended to ignore the far in the past transition # added in zic 2014c (at timestamp -2**63 in zic 2014c and at the # approximate time of the big bang from zic 2014d).
file
<not_specific>