From: Rob Browning Date: Sat, 5 Dec 2015 19:41:36 +0000 (-0600) Subject: Fix utc_offset_str for fractional TZs X-Git-Tag: 0.28-rc1~65 X-Git-Url: https://arthur.barton.de/gitweb/?p=bup.git;a=commitdiff_plain;h=f25ef2e868f85ca19bfce314081c956ade9c10ef Fix utc_offset_str for fractional TZs Previously, for fractional offsets like TZ=FOO+3:3 (where the offset is not an integer number of hours), utc_offset_str() would return a large, incorrect integer value. Adjust it to handle arbitrary offsets, and document that it truncates any fractional seconds of the offset. Before this fix, whenever bup was operating with a fractional offset (e.g. TZ=Australia/Adelaide), it wrote commits (i.e. saves) that it won't be able to read. Attempts to read them will fail with "Exception: cannot parse commit". Thanks to David Kettler for reporting the problem, and proposing an alternate fix. Reviewed-by: David Kettler Tested-by: David Kettler [rlb@defaultvalue.org: changed / to // for Python 3 compat] Signed-off-by: Rob Browning Tested-by: Rob Browning --- diff --git a/lib/bup/helpers.py b/lib/bup/helpers.py index e7fbc5b..3427e03 100644 --- a/lib/bup/helpers.py +++ b/lib/bup/helpers.py @@ -1049,10 +1049,15 @@ if _localtime: def localtime(time): return bup_time(*_helpers.localtime(time)) def utc_offset_str(t): - 'Return the local offset from UTC as "+hhmm" or "-hhmm" for time t.' + """Return the local offset from UTC as "+hhmm" or "-hhmm" for time t. + If the current UTC offset does not represent an integer number + of minutes, the fractional component will be truncated.""" off = localtime(t).tm_gmtoff - hrs = off / 60 / 60 - return "%+03d%02d" % (hrs, abs(off - (hrs * 60 * 60))) + # Note: // doesn't truncate like C for negative values, it rounds down. + offmin = abs(off) // 60 + m = offmin % 60 + h = (offmin - m) // 60 + return "%+03d%02d" % (-h if off < 0 else h, m) def to_py_time(x): if isinstance(x, time.struct_time): return x diff --git a/lib/bup/t/thelpers.py b/lib/bup/t/thelpers.py index 79eb4af..10ebce1 100644 --- a/lib/bup/t/thelpers.py +++ b/lib/bup/t/thelpers.py @@ -179,3 +179,33 @@ def test_atomically_replaced_file(): if wvfailure_count() == initial_failures: subprocess.call(['rm', '-rf', tmpdir]) + + +@wvtest +def test_utc_offset_str(): + tz = os.environ.get('TZ') + try: + os.environ['TZ'] = 'FOO+0:00' + WVPASSEQ(utc_offset_str(0), '+0000') + os.environ['TZ'] = 'FOO+1:00' + WVPASSEQ(utc_offset_str(0), '-0100') + os.environ['TZ'] = 'FOO-1:00' + WVPASSEQ(utc_offset_str(0), '+0100') + os.environ['TZ'] = 'FOO+3:3' + WVPASSEQ(utc_offset_str(0), '-0303') + os.environ['TZ'] = 'FOO-3:3' + WVPASSEQ(utc_offset_str(0), '+0303') + # Offset is not an integer number of minutes + os.environ['TZ'] = 'FOO+3:3:3' + WVPASSEQ(utc_offset_str(1), '-0303') + os.environ['TZ'] = 'FOO-3:3:3' + WVPASSEQ(utc_offset_str(1), '+0303') + WVPASSEQ(utc_offset_str(314159), '+0303') + finally: + if tz: + os.environ['TZ'] = tz + else: + try: + del os.environ['TZ'] + except KeyError: + pass