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 ):
|
| 158 | 158 | 1) |
| 159 | 159 | return |
| 160 | 160 | |
| 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 |
| 163 | 167 | 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 |
| 166 | 179 | |
| 167 | 180 | # read in transition type indexes |
| 168 | 181 | types = [None]*counts.transitions |
| … |
… |
class posixtzinfo( basetzinfo ):
|
| 177 | 190 | for i in range(counts.types): |
| 178 | 191 | offset, isdst, _ = unpack('!lbB', fd.read(6)) |
| 179 | 192 | 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]] |
| 182 | 195 | transitions[i][2] = time.gmtime(transitions[i][0] + offset) |
| 183 | 196 | transitions[i][3] = offset |
| 184 | 197 | transitions[i][5] = isdst |
| 185 | 198 | |
| 186 | 199 | # read in type names |
| 187 | 200 | 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): |
| 189 | 202 | if types[j] == i: |
| 190 | 203 | transitions[j][4] = name |
| 191 | 204 | |
| … |
… |
class posixtzinfo( basetzinfo ):
|
| 196 | 209 | # skip utc/local indicators |
| 197 | 210 | fd.seek(counts.gmt_indicators, 1) |
| 198 | 211 | |
| 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:]] |
| 201 | 215 | self._transitions = tuple(transitions) |
| 202 | 216 | |
| 203 | 217 | |