diff --git a/swift/common/utils/timestamp.py b/swift/common/utils/timestamp.py index 02f11bd4e7..60c942ed08 100644 --- a/swift/common/utils/timestamp.py +++ b/swift/common/utils/timestamp.py @@ -89,7 +89,7 @@ class Timestamp(object): timestamp = timestamp.decode('ascii') if isinstance(timestamp, str): base, base_offset = timestamp.partition('_')[::2] - self.timestamp = float(base) + float_timestamp = float(base) if '_' in base_offset: raise ValueError('invalid literal for int() with base 16: ' '%r' % base_offset) @@ -98,7 +98,7 @@ class Timestamp(object): else: self.offset = 0 else: - self.timestamp = float(timestamp) + float_timestamp = float(timestamp) self.offset = getattr(timestamp, 'offset', 0) # increment offset if offset>= 0: @@ -107,14 +107,15 @@ class Timestamp(object): raise ValueError('offset must be non-negative') if self.offset> MAX_OFFSET: raise ValueError('offset must be smaller than %d' % MAX_OFFSET) - self.raw = int(round(self.timestamp / PRECISION)) + self.raw = int(round(float_timestamp / PRECISION)) # add delta if delta: self.raw = self.raw + delta if self.raw <= 0: raise ValueError( 'delta must be greater than %d' % (-1 * self.raw)) - self.timestamp = float(self.raw * PRECISION) + + self.timestamp = round(float(self.raw * PRECISION), 5) if check_bounds: if self.timestamp < 0: raise ValueError('timestamp cannot be negative') diff --git a/test/unit/common/middleware/s3api/test_utils.py b/test/unit/common/middleware/s3api/test_utils.py index 01cc07117f..9a6b282a3b 100644 --- a/test/unit/common/middleware/s3api/test_utils.py +++ b/test/unit/common/middleware/s3api/test_utils.py @@ -121,14 +121,19 @@ class TestS3Timestamp(unittest.TestCase): # integer ts = utils.S3Timestamp(1) self.assertEqual(expected, ts.s3xmlformat) + # microseconds digits are not included in Timestamp.normal so do not + # cause the timestamp to be rounded up + ts = utils.S3Timestamp(1.000001) + self.assertEqual(expected, ts.s3xmlformat) + # milliseconds unit should be rounded up expected = '1970-01-01T00:00:02.000Z' ts = utils.S3Timestamp(1.1) self.assertEqual(expected, ts.s3xmlformat) - # float (microseconds) should be floored too - ts = utils.S3Timestamp(1.000001) + # float (deca-microseconds) should be rounded up too + ts = utils.S3Timestamp(1.000010) self.assertEqual(expected, ts.s3xmlformat) - # Bigger float (milliseconds) should be floored too + # Bigger float (milliseconds) should be rounded up too ts = utils.S3Timestamp(1.9) self.assertEqual(expected, ts.s3xmlformat) diff --git a/test/unit/common/utils/test_timestamp.py b/test/unit/common/utils/test_timestamp.py index 54e2942c3a..91a7d3e998 100644 --- a/test/unit/common/utils/test_timestamp.py +++ b/test/unit/common/utils/test_timestamp.py @@ -151,10 +151,13 @@ class TestTimestamp(unittest.TestCase): def test_ceil(self): self.assertEqual(0.0, timestamp.Timestamp(0).ceil()) self.assertEqual(1.0, timestamp.Timestamp(0.00001).ceil()) - self.assertEqual(1.0, timestamp.Timestamp(0.000001).ceil()) + self.assertEqual(0.0, timestamp.Timestamp(0.000001).ceil()) + self.assertEqual(1.0, timestamp.Timestamp(0.000006).ceil()) self.assertEqual(12345678.0, timestamp.Timestamp(12345678.0).ceil()) - self.assertEqual(12345679.0, + self.assertEqual(12345678.0, timestamp.Timestamp(12345678.000001).ceil()) + self.assertEqual(12345679.0, + timestamp.Timestamp(12345678.000006).ceil()) def test_not_equal(self): ts = '1402436408.91203_0000000000000001' @@ -311,11 +314,17 @@ class TestTimestamp(unittest.TestCase): expected = 140243640891203 ts = timestamp.Timestamp(1402436408.91203) self.assertEqual(expected, ts.raw) + self.assertEqual('1402436408.91203', ts.normal) # 'raw' does not include offset ts = timestamp.Timestamp(1402436408.91203, 0xf0) self.assertEqual(expected, ts.raw) + expected = 175507756652338 + ts = timestamp.Timestamp(1755077566.523385) + self.assertEqual(expected, ts.raw) + self.assertEqual('1755077566.52338', ts.normal) + def test_delta(self): def _assertWithinBounds(expected, timestamp): tolerance = 0.00001 @@ -780,6 +789,23 @@ class TestTimestamp(unittest.TestCase): self.assertEqual(caught.exception.args[0], 'Cannot invert timestamps with offsets') + def test_inversion_reversibility(self): + ts = timestamp.Timestamp(1755077566.523385) + inv = ~ts + inv_inv = ~inv + self.assertEqual(ts, inv_inv) + self.assertEqual(ts.normal, inv_inv.normal) + + inv_inv_inv = ~inv_inv + self.assertEqual(inv, inv_inv_inv) + self.assertEqual(inv.normal, inv_inv_inv.normal) + + ts = timestamp.Timestamp.now() + inv = ~ts + inv_inv = ~inv + self.assertEqual(ts, inv_inv) + self.assertEqual(ts.normal, inv_inv.normal) + class TestTimestampEncoding(unittest.TestCase):

AltStyle によって変換されたページ (->オリジナル) /