Ejemplo n.º 1
0
 def _get_version(fd):
     """Confirm zoneinfo file magic string, and return version number."""
     if fd.read(4) != 'TZif':
         raise MythTZError(MythTZError.TZ_INVALID_FILE)
     version = fd.read(1)  # read version number
     fd.seek(15, 1)  # skip reserved bytes
     if version == '\0':
         return 1
     else:
         return int(version)  # should be 2
Ejemplo n.º 2
0
    def _get_transition_search(self, dt=None):
        if dt is None:
            dt = _pydatetime.now()
        dt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)

        index = self.__last
        direction = 0
        while True:
            if dt < self._ranges[index][0]:
                if direction == 1:
                    # gap found, use later transition
                    break
                else:
                    index -= 1
                    direction = -1
            elif dt >= self._ranges[index][1]:
                if direction == -1:
                    # gap found, use later transition
                    index += 1
                    break
                else:
                    index += 1
                    direction = 1
            else:
                break

            if index >= len(self._ranges):
                # out of bounds future, use final transition
                index = len(self._ranges) - 1
                break
            elif index < 0:
                # out of bounds past, undefined time frame
                raise MythTZError(MythTZError.TZ_CONVERSION_ERROR,
                                  self.tzname(), dt)

        self.__last = index
        return self._transitions[self._ranges[index][2]]
Ejemplo n.º 3
0
    def _process(self, fd, version=1, skip=False):
        from struct import unpack, calcsize
        if version == 1:
            ttmfmt = '!l'
            lfmt = '!ll'
        elif version == 2:
            ttmfmt = '!q'
            lfmt = '!ql'

        counts = self._Count(*unpack('!llllll', fd.read(24)))
        if skip:
            fd.seek(counts.transitions * (calcsize(ttmfmt)+1) +\
                    counts.types * 6 +\
                    counts.abbrevs +\
                    counts.leap_seconds * calcsize(lfmt) +\
                    counts.std_indicators +\
                    counts.gmt_indicators,\
                    1)
            return

        transitions = []
        for i in range(counts.transitions):  # read in epoch time data
            t = unpack(ttmfmt, fd.read(calcsize(ttmfmt)))[0]
            tt = time.gmtime(t)
            transitions.append([t, tt, None, None, None, None])

        # read in transition type indexes
        types = [None] * counts.transitions
        for i in range(counts.transitions):
            types[i] = t = unpack('!b', fd.read(1))[0]
            if t >= counts.types:
                raise MythTZError(MythTZError.TZ_INVALID_TRANSITION, t,
                                  counts.types - 1)

        # read in type definitions
        typedefs = []
        for i in range(counts.types):
            offset, isdst, _ = unpack('!lbB', fd.read(6))
            typedefs.append([offset, isdst])
        for i in range(counts.transitions):
            offset, isdst = typedefs[types[i]]
            transitions[i][2] = time.gmtime(transitions[i][0] + offset)
            transitions[i][3] = offset
            transitions[i][5] = isdst

        # read in type names
        for i, name in enumerate(fd.read(counts.abbrevs)[:-1].split('\0')):
            for j in range(counts.transitions):
                if types[j] == i:
                    transitions[j][4] = name

        # skip leap second definitions
        fd.seek(counts.leap_seconds + calcsize(lfmt), 1)
        # skip std/wall indicators
        fd.seek(counts.std_indicators, 1)
        # skip utc/local indicators
        fd.seek(counts.gmt_indicators, 1)

        for i in range(counts.transitions):
            transitions[i] = self._Transition(*transitions[i])
        self._transitions = tuple(transitions)
Ejemplo n.º 4
0
    def _process(self, fd, version=1, skip=False):
        from struct import unpack, calcsize
        if version == 1:
            ttmfmt = '!l'
            lfmt = '!ll'
        elif version == 2:
            ttmfmt = '!q'
            lfmt = '!ql'

        counts = self._Count(*unpack('!llllll', fd.read(24)))
        if skip:
            fd.seek(counts.transitions * (calcsize(ttmfmt)+1) +\
                    counts.types * 6 +\
                    counts.abbrevs +\
                    counts.leap_seconds * calcsize(lfmt) +\
                    counts.std_indicators +\
                    counts.gmt_indicators,\
                    1)
            return

        transitions = [None] * counts.transitions
        # First transition which is in range for gmtime. Some zoneinfo
        # files have massively negative leading entries for e.g. the
        # big bang which gmtime() cannot cope with.
        first_modern_transition = None
        i = 0  # assign i, in case the for-loop is not executed:
        for i in range(counts.transitions):  # read in epoch time data
            t = unpack(ttmfmt, fd.read(calcsize(ttmfmt)))[0]

            try:
                tt = time.gmtime(t)
                transitions[i] = ([t, tt, None, None, None, None])
                if first_modern_transition is None:
                    first_modern_transition = i
            except (ValueError, OSError) as e:
                # ValueError is only accepted until we have seen a modern
                # transition.
                if first_modern_transition is not None:
                    raise e

        # Special case if there are no modern transitions, like e.g. UTC timezone:
        if ((i == 0) and first_modern_transition is None):
            first_modern_transition = counts.transitions

        # read in transition type indexes
        types = [None] * counts.transitions
        for i in range(counts.transitions):
            types[i] = t = unpack('!b', fd.read(1))[0]
            if t >= counts.types:
                raise MythTZError(MythTZError.TZ_INVALID_TRANSITION, t,
                                  counts.types - 1)

        # read in type definitions
        typedefs = []
        for i in range(counts.types):
            offset, isdst, _ = unpack('!lbB', fd.read(6))
            typedefs.append([offset, isdst])
        for i in range(first_modern_transition, counts.transitions):
            offset, isdst = typedefs[types[i]]
            transitions[i][2] = time.gmtime(transitions[i][0] + offset)
            transitions[i][3] = offset
            transitions[i][5] = isdst

        # read in type names
        for i, name in enumerate(fd.read(counts.abbrevs)[:-1].split(b'\0')):
            for j in range(first_modern_transition, counts.transitions):
                if types[j] == i:
                    transitions[j][4] = name

        # skip leap second definitions
        fd.seek(counts.leap_seconds + calcsize(lfmt), 1)
        # skip std/wall indicators
        fd.seek(counts.std_indicators, 1)
        # skip utc/local indicators
        fd.seek(counts.gmt_indicators, 1)

        transitions = [
            self._Transition(*x) for x in transitions[first_modern_transition:]
        ]
        self._transitions = tuple(transitions)