From af9f1c24c494ca374cdfe0364f1ebe1fb35d19fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Borgstr=C3=B6m?= Date: Sun, 19 Apr 2015 22:42:52 +0200 Subject: [PATCH] Fix parsing of iso8601 timestamps with zero microseconds Closes #282 --- CHANGES | 6 ++++++ attic/archive.py | 3 +-- attic/helpers.py | 8 ++++++++ attic/testsuite/helpers.py | 9 ++++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 6e64c5807..9ed6944c9 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,12 @@ Attic Changelog Here you can see the full list of changes between each Attic release. +Version 0.16 +------------ + +(bugfix release, released on X) +- Fix parsing of iso 8601 timestamps with zero microseconds (#282) + Version 0.15 ------------ diff --git a/attic/archive.py b/attic/archive.py index d78a7fdb3..f5726ea27 100644 --- a/attic/archive.py +++ b/attic/archive.py @@ -163,8 +163,7 @@ class Archive: @property def ts(self): """Timestamp of archive creation in UTC""" - t, f = self.metadata[b'time'].split('.', 1) - return datetime.strptime(t, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) + timedelta(seconds=float('.' + f)) + return parse_timestamp(self.metadata[b'time']) def __repr__(self): return 'Archive(%r)' % self.name diff --git a/attic/helpers.py b/attic/helpers.py index 646ba2571..2e380cd68 100644 --- a/attic/helpers.py +++ b/attic/helpers.py @@ -185,6 +185,14 @@ def to_localtime(ts): return datetime(*time.localtime((ts - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds())[:6]) +def parse_timestamp(timestamp): + """Parse a ISO 8601 timestamp string""" + if '.' in timestamp: # microseconds might not be pressent + return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f').replace(tzinfo=timezone.utc) + else: + return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) + + def update_excludes(args): """Merge exclude patterns from files with those on command line. Empty lines and lines starting with '#' are ignored, but whitespace diff --git a/attic/testsuite/helpers.py b/attic/testsuite/helpers.py index e8c9ee402..0b5a75836 100644 --- a/attic/testsuite/helpers.py +++ b/attic/testsuite/helpers.py @@ -5,7 +5,7 @@ import os import tempfile import unittest from attic.helpers import adjust_patterns, exclude_path, Location, format_timedelta, IncludePattern, ExcludePattern, make_path_safe, UpgradableLock, prune_within, prune_split, to_localtime, \ - StableDict, int_to_bigint, bigint_to_int + StableDict, int_to_bigint, bigint_to_int, parse_timestamp from attic.testsuite import AtticTestCase import msgpack @@ -209,3 +209,10 @@ class StableDictTestCase(AtticTestCase): d = StableDict(foo=1, bar=2, boo=3, baz=4) self.assert_equal(list(d.items()), [('bar', 2), ('baz', 4), ('boo', 3), ('foo', 1)]) self.assert_equal(hashlib.md5(msgpack.packb(d)).hexdigest(), 'fc78df42cd60691b3ac3dd2a2b39903f') + + +class TestParseTimestamp(AtticTestCase): + + def test(self): + self.assert_equal(parse_timestamp('2015-04-19T20:25:00.226410'), datetime(2015, 4, 19, 20, 25, 0, 226410, timezone.utc)) + self.assert_equal(parse_timestamp('2015-04-19T20:25:00'), datetime(2015, 4, 19, 20, 25, 0, 0, timezone.utc))