summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qpid/python/qpid/codec010.py11
-rw-r--r--qpid/python/qpid/datatypes.py50
-rw-r--r--qpid/python/qpid/spec010.py6
-rw-r--r--qpid/python/tests/codec010.py36
-rw-r--r--qpid/python/tests/datatypes.py32
5 files changed, 120 insertions, 15 deletions
diff --git a/qpid/python/qpid/codec010.py b/qpid/python/qpid/codec010.py
index c2ea7ed512..f34025ef17 100644
--- a/qpid/python/qpid/codec010.py
+++ b/qpid/python/qpid/codec010.py
@@ -17,8 +17,9 @@
# under the License.
#
+import datetime
from packer import Packer
-from datatypes import serial, RangedSet, Struct
+from datatypes import serial, timestamp, RangedSet, Struct
class CodecException(Exception): pass
@@ -103,9 +104,11 @@ class Codec(Packer):
self.pack("!q", n)
def read_datetime(self):
- return self.read_uint64()
- def write_datetime(self, n):
- self.write_uint64(n)
+ return timestamp(self.read_uint64())
+ def write_datetime(self, t):
+ if isinstance(t, datetime.datetime):
+ t = timestamp(t)
+ self.write_uint64(t)
def read_double(self):
return self.unpack("!d")
diff --git a/qpid/python/qpid/datatypes.py b/qpid/python/qpid/datatypes.py
index 7150caded2..38fc163dd9 100644
--- a/qpid/python/qpid/datatypes.py
+++ b/qpid/python/qpid/datatypes.py
@@ -17,7 +17,7 @@
# under the License.
#
-import threading, struct
+import threading, struct, datetime, time
class Struct:
@@ -296,3 +296,51 @@ class UUID:
def __repr__(self):
return "UUID(%r)" % str(self)
+
+class timestamp(float):
+
+ def __new__(cls, obj=None):
+ if obj is None:
+ obj = time.time()
+ elif isinstance(obj, datetime.datetime):
+ obj = time.mktime(obj.timetuple()) + 1e-6 * obj.microsecond
+ return super(timestamp, cls).__new__(cls, obj)
+
+ def datetime(self):
+ return datetime.datetime.fromtimestamp(self)
+
+ def __add__(self, other):
+ if isinstance(other, datetime.timedelta):
+ return timestamp(self.datetime() + other)
+ else:
+ return timestamp(float(self) + other)
+
+ def __sub__(self, other):
+ if isinstance(other, datetime.timedelta):
+ return timestamp(self.datetime() - other)
+ else:
+ return timestamp(float(self) - other)
+
+ def __radd__(self, other):
+ if isinstance(other, datetime.timedelta):
+ return timestamp(self.datetime() + other)
+ else:
+ return timestamp(other + float(self))
+
+ def __rsub__(self, other):
+ if isinstance(other, datetime.timedelta):
+ return timestamp(self.datetime() - other)
+ else:
+ return timestamp(other - float(self))
+
+ def __neg__(self):
+ return timestamp(-float(self))
+
+ def __pos__(self):
+ return self
+
+ def __abs__(self):
+ return timestamp(abs(float(self)))
+
+ def __repr__(self):
+ return "timestamp(%r)" % float(self)
diff --git a/qpid/python/qpid/spec010.py b/qpid/python/qpid/spec010.py
index 23966e6176..cbc85a5e8b 100644
--- a/qpid/python/qpid/spec010.py
+++ b/qpid/python/qpid/spec010.py
@@ -17,7 +17,7 @@
# under the License.
#
-import os, cPickle, datatypes
+import os, cPickle, datatypes, datetime
from codec010 import StringCodec
from util import mtime, fill
@@ -477,7 +477,9 @@ class Spec(Node):
None.__class__: "void",
list: "list",
tuple: "list",
- dict: "map"
+ dict: "map",
+ datatypes.timestamp: "datetime",
+ datetime.datetime: "datetime"
}
def __init__(self, major, minor, port, children):
diff --git a/qpid/python/tests/codec010.py b/qpid/python/tests/codec010.py
index bbe894b7b3..5f9f853744 100644
--- a/qpid/python/tests/codec010.py
+++ b/qpid/python/tests/codec010.py
@@ -17,22 +17,27 @@
# under the License.
#
+import time
+
from unittest import TestCase
from qpid.spec010 import load
from qpid.codec010 import StringCodec
from qpid.testlib import testrunner
+from qpid.datatypes import timestamp
class CodecTest(TestCase):
def setUp(self):
self.spec = load(testrunner.get_spec_file("amqp.0-10.xml"))
- def check(self, type, value):
+ def check(self, type, value, compare=True):
t = self.spec[type]
sc = StringCodec(self.spec)
t.encode(sc, value)
decoded = t.decode(sc)
- assert decoded == value, "%s, %s" % (decoded, value)
+ if compare:
+ assert decoded == value, "%s, %s" % (decoded, value)
+ return decoded
def testMapString(self):
self.check("map", {"string": "this is a test"})
@@ -43,6 +48,15 @@ class CodecTest(TestCase):
def testMapLong(self):
self.check("map", {"long": 2**32})
+ def testMapTimestamp(self):
+ decoded = self.check("map", {"timestamp": timestamp(0)})
+ assert isinstance(decoded["timestamp"], timestamp)
+
+ def testMapDatetime(self):
+ decoded = self.check("map", {"datetime": timestamp(0).datetime()}, compare=False)
+ assert isinstance(decoded["datetime"], timestamp)
+ assert decoded["datetime"] == 0.0
+
def testMapNone(self):
self.check("map", {"none": None})
@@ -53,12 +67,14 @@ class CodecTest(TestCase):
self.check("map", {"list": [1, "two", 3.0, -4]})
def testMapAll(self):
- self.check("map", {"string": "this is a test",
- "int": 3,
- "long": 2**32,
- "none": None,
- "map": {"string": "nested map"},
- "list": [1, "two", 3.0, -4]})
+ decoded = self.check("map", {"string": "this is a test",
+ "int": 3,
+ "long": 2**32,
+ "timestamp": timestamp(0),
+ "none": None,
+ "map": {"string": "nested map"},
+ "list": [1, "two", 3.0, -4]})
+ assert isinstance(decoded["timestamp"], timestamp)
def testMapEmpty(self):
self.check("map", {})
@@ -90,3 +106,7 @@ class CodecTest(TestCase):
def testInt16(self):
self.check("int16", 3)
self.check("int16", -3)
+
+ def testDatetime(self):
+ self.check("datetime", timestamp(0))
+ self.check("datetime", timestamp(long(time.time())))
diff --git a/qpid/python/tests/datatypes.py b/qpid/python/tests/datatypes.py
index ef98e81da0..4b9e1bcc78 100644
--- a/qpid/python/tests/datatypes.py
+++ b/qpid/python/tests/datatypes.py
@@ -223,3 +223,35 @@ class MessageTest(TestCase):
assert m.get("fragment_properties") is None
assert m.get("message_properties") == self.mp
assert m.get("delivery_properties") == self.dp
+
+class TimestampTest(TestCase):
+
+ def check(self, expected, *values):
+ for v in values:
+ assert isinstance(v, timestamp)
+ assert v == expected
+ assert v == timestamp(expected)
+
+ def testAdd(self):
+ self.check(4.0,
+ timestamp(2.0) + 2.0,
+ 2.0 + timestamp(2.0))
+
+ def testSub(self):
+ self.check(2.0,
+ timestamp(4.0) - 2.0,
+ 4.0 - timestamp(2.0))
+
+ def testNeg(self):
+ self.check(-4.0, -timestamp(4.0))
+
+ def testPos(self):
+ self.check(+4.0, +timestamp(4.0))
+
+ def testAbs(self):
+ self.check(4.0, abs(timestamp(-4.0)))
+
+ def testConversion(self):
+ dt = timestamp(0).datetime()
+ t = timestamp(dt)
+ assert t == 0