Ticket #13299: 0001-python-Handle-massively-negative-initial-zoneinfo-en.patch

File 0001-python-Handle-massively-negative-initial-zoneinfo-en.patch, 4.1 KB (added by ijc, 15 months ago)
  • mythtv/bindings/python/MythTV/utility/dt.py

    From ebd0866ca9bc5cc7332663a125898e91e3836c47 Mon Sep 17 00:00:00 2001
    From: Ian Campbell <ijc@hellion.org.uk>
    Date: Fri, 13 Jul 2018 20:29:52 +0100
    Subject: [PATCH] python: Handle massively negative initial zoneinfo entries.
    
    Some zoneinfo files contain such "big bang hack" entries as a workaround for a
    bug, this was recently reverted upstream but such files are still around in the
    wild (e.g. Ubuntu 14.04, current Debian testing). Some info on this can be
    found in:
    
    https://github.com/eggert/tz/commit/83c119f4d5d48ba37d73e42b0f12da3ae06b6c3f
    
    With this a:
    
        from MythTV import datetime
        import time
        tnow = time.time()
        print datetime.fromtimestamp(tnow).strftime("%Y%m%d%H%M%S %z")
    
    Now produces the correct time. To reproduce I needed to run with
    `TZ=Europe/Vienna` since I am in GMT/BST. Prior to this fix when running in
    during Northern hemisphere daylight savings time (i.e. today) the code would
    produce timezone of +0100 instead of the correct +0200. Similarly with
    `TZ=Americ/Los_Angeles` an incorrect -0800 becomes -0700 with the fix.
    
    The change only ignores initial entries of the bad for, since it would be
    unexpected to see them once we have seen a transition for the "modern era"
    (which I define as "something time.gmtime is happy with").
    ---
     mythtv/bindings/python/MythTV/utility/dt.py | 32 +++++++++++++++++++++--------
     1 file changed, 23 insertions(+), 9 deletions(-)
    
    diff --git a/mythtv/bindings/python/MythTV/utility/dt.py b/mythtv/bindings/python/MythTV/utility/dt.py
    index f688ea24c6..c4c128b1cb 100644
    a b class posixtzinfo( basetzinfo ): 
    158158                    1)
    159159            return
    160160
    161         transitions = []
    162         for i in range(counts.transitions): # read in epoch time data
     161        transitions = [None] * counts.transitions
     162        # First transition which is in range for gmtime. Some zoneinfo
     163        # files have massively negative leading entries for e.g. the
     164        # big bang which gmtime() cannot cope with.
     165        first_modern_transition = None
     166        for i in range(counts.transitions):  # read in epoch time data
    163167            t = unpack(ttmfmt, fd.read(calcsize(ttmfmt)))[0]
    164             tt = time.gmtime(t)
    165             transitions.append([t, tt, None, None, None, None])
     168
     169            try:
     170                tt = time.gmtime(t)
     171                transitions[i] = ([t, tt, None, None, None, None])
     172                if first_modern_transition is None:
     173                    first_modern_transition = i
     174            except ValueError as e:
     175                # ValueError is only accepted until we have seen a modern
     176                # transition.
     177                if first_modern_transition is not None:
     178                    raise e
    166179
    167180        # read in transition type indexes
    168181        types = [None]*counts.transitions
    class posixtzinfo( basetzinfo ): 
    177190        for i in range(counts.types):
    178191            offset, isdst, _ = unpack('!lbB', fd.read(6))
    179192            typedefs.append([offset, isdst])
    180         for i in range(counts.transitions):
    181             offset,isdst = typedefs[types[i]]
     193        for i in range(first_modern_transition, counts.transitions):
     194            offset, isdst = typedefs[types[i]]
    182195            transitions[i][2] = time.gmtime(transitions[i][0] + offset)
    183196            transitions[i][3] = offset
    184197            transitions[i][5] = isdst
    185198
    186199        # read in type names
    187200        for i, name in enumerate(fd.read(counts.abbrevs)[:-1].split('\0')):
    188             for j in range(counts.transitions):
     201            for j in range(first_modern_transition, counts.transitions):
    189202                if types[j] == i:
    190203                    transitions[j][4] = name
    191204
    class posixtzinfo( basetzinfo ): 
    196209        # skip utc/local indicators
    197210        fd.seek(counts.gmt_indicators, 1)
    198211
    199         for i in range(counts.transitions):
    200             transitions[i] = self._Transition(*transitions[i])
     212        transitions = [self._Transition(*x)
     213                       for x
     214                       in transitions[first_modern_transition:]]
    201215        self._transitions = tuple(transitions)
    202216
    203217