| Viewing file:  tzfile.py (4.82 KB)      -rwxr-xr-x Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
#!/usr/libexec/platform-python'''
 $Id: tzfile.py,v 1.8 2004/06/03 00:15:24 zenzen Exp $
 '''
 
 try:
 from cStringIO import StringIO
 except ImportError:
 from io import StringIO
 from datetime import datetime, timedelta
 from struct import unpack, calcsize
 
 from pytz.tzinfo import StaticTzInfo, DstTzInfo, memorized_ttinfo
 from pytz.tzinfo import memorized_datetime, memorized_timedelta
 
 def _byte_string(s):
 """Cast a string or byte string to an ASCII byte string."""
 return s.encode('ASCII')
 
 _NULL = _byte_string('\0')
 
 def _std_string(s):
 """Cast a string or byte string to an ASCII string."""
 return str(s.decode('ASCII'))
 
 def build_tzinfo(zone, fp):
 head_fmt = '>4s c 15x 6l'
 head_size = calcsize(head_fmt)
 (magic, format, ttisgmtcnt, ttisstdcnt,leapcnt, timecnt,
 typecnt, charcnt) =  unpack(head_fmt, fp.read(head_size))
 
 # Make sure it is a tzfile(5) file
 assert magic == _byte_string('TZif'), 'Got magic %s' % repr(magic)
 
 # Read out the transition times, localtime indices and ttinfo structures.
 data_fmt = '>%(timecnt)dl %(timecnt)dB %(ttinfo)s %(charcnt)ds' % dict(
 timecnt=timecnt, ttinfo='lBB'*typecnt, charcnt=charcnt)
 data_size = calcsize(data_fmt)
 data = unpack(data_fmt, fp.read(data_size))
 
 # make sure we unpacked the right number of values
 assert len(data) == 2 * timecnt + 3 * typecnt + 1
 transitions = [memorized_datetime(trans)
 for trans in data[:timecnt]]
 lindexes = list(data[timecnt:2 * timecnt])
 ttinfo_raw = data[2 * timecnt:-1]
 tznames_raw = data[-1]
 del data
 
 # Process ttinfo into separate structs
 ttinfo = []
 tznames = {}
 i = 0
 while i < len(ttinfo_raw):
 # have we looked up this timezone name yet?
 tzname_offset = ttinfo_raw[i+2]
 if tzname_offset not in tznames:
 nul = tznames_raw.find(_NULL, tzname_offset)
 if nul < 0:
 nul = len(tznames_raw)
 tznames[tzname_offset] = _std_string(
 tznames_raw[tzname_offset:nul])
 ttinfo.append((ttinfo_raw[i],
 bool(ttinfo_raw[i+1]),
 tznames[tzname_offset]))
 i += 3
 
 # Now build the timezone object
 if len(ttinfo) ==1 or len(transitions) == 0:
 ttinfo[0][0], ttinfo[0][2]
 cls = type(zone, (StaticTzInfo,), dict(
 zone=zone,
 _utcoffset=memorized_timedelta(ttinfo[0][0]),
 _tzname=ttinfo[0][2]))
 else:
 # Early dates use the first standard time ttinfo
 i = 0
 while ttinfo[i][1]:
 i += 1
 if ttinfo[i] == ttinfo[lindexes[0]]:
 transitions[0] = datetime.min
 else:
 transitions.insert(0, datetime.min)
 lindexes.insert(0, i)
 
 # calculate transition info
 transition_info = []
 for i in range(len(transitions)):
 inf = ttinfo[lindexes[i]]
 utcoffset = inf[0]
 if not inf[1]:
 dst = 0
 else:
 for j in range(i-1, -1, -1):
 prev_inf = ttinfo[lindexes[j]]
 if not prev_inf[1]:
 break
 dst = inf[0] - prev_inf[0] # dst offset
 
 # Bad dst? Look further. DST > 24 hours happens when
 # a timzone has moved across the international dateline.
 if dst <= 0 or dst > 3600*3:
 for j in range(i+1, len(transitions)):
 stdinf = ttinfo[lindexes[j]]
 if not stdinf[1]:
 dst = inf[0] - stdinf[0]
 if dst > 0:
 break # Found a useful std time.
 
 tzname = inf[2]
 
 # Round utcoffset and dst to the nearest minute or the
 # datetime library will complain. Conversions to these timezones
 # might be up to plus or minus 30 seconds out, but it is
 # the best we can do.
 utcoffset = int((utcoffset + 30) // 60) * 60
 dst = int((dst + 30) // 60) * 60
 transition_info.append(memorized_ttinfo(utcoffset, dst, tzname))
 
 cls = type(zone, (DstTzInfo,), dict(
 zone=zone,
 _utc_transition_times=transitions,
 _transition_info=transition_info))
 
 return cls()
 
 if __name__ == '__main__':
 import os.path
 from pprint import pprint
 # Patched in Debian, use the system zoninfo from the tzdata package
 base = '/usr/share/zoneinfo'
 tz = build_tzinfo('Australia/Melbourne',
 open(os.path.join(base,'Australia','Melbourne'), 'rb'))
 tz = build_tzinfo('US/Eastern',
 open(os.path.join(base,'US','Eastern'), 'rb'))
 pprint(tz._utc_transition_times)
 #print tz.asPython(4)
 #print tz.transitions_mapping
 
 |