PROTON-1955: [go] incorrect conversion between Go time and AMQP time

Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/ccaeaa0c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/ccaeaa0c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/ccaeaa0c

Branch: refs/heads/master
Commit: ccaeaa0cbcc1364b3265984ef15f5d92c6087793
Parents: 32c7036
Author: Alan Conway <[email protected]>
Authored: Fri Oct 5 15:38:48 2018 -0400
Committer: Alan Conway <[email protected]>
Committed: Thu Oct 11 15:14:15 2018 -0400

----------------------------------------------------------------------
 go/src/qpid.apache.org/amqp/marshal.go    |  2 +-
 go/src/qpid.apache.org/amqp/types.go      | 26 ++++++++++++++++--------
 go/src/qpid.apache.org/amqp/types_test.go | 28 +++++++++++++++++++++++++-
 go/src/qpid.apache.org/amqp/unmarshal.go  |  4 ++--
 4 files changed, 48 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ccaeaa0c/go/src/qpid.apache.org/amqp/marshal.go
----------------------------------------------------------------------
diff --git a/go/src/qpid.apache.org/amqp/marshal.go 
b/go/src/qpid.apache.org/amqp/marshal.go
index 99584a2..d846993 100644
--- a/go/src/qpid.apache.org/amqp/marshal.go
+++ b/go/src/qpid.apache.org/amqp/marshal.go
@@ -224,7 +224,7 @@ func marshal(i interface{}, data *C.pn_data_t) {
 
                // Other simple types
        case time.Time:
-               C.pn_data_put_timestamp(data, 
C.pn_timestamp_t(v.UnixNano()/1000))
+               C.pn_data_put_timestamp(data, pnTime(v))
        case UUID:
                C.pn_data_put_uuid(data, *(*C.pn_uuid_t)(unsafe.Pointer(&v[0])))
        case Char:

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ccaeaa0c/go/src/qpid.apache.org/amqp/types.go
----------------------------------------------------------------------
diff --git a/go/src/qpid.apache.org/amqp/types.go 
b/go/src/qpid.apache.org/amqp/types.go
index a1fe2ac..04226ff 100644
--- a/go/src/qpid.apache.org/amqp/types.go
+++ b/go/src/qpid.apache.org/amqp/types.go
@@ -163,19 +163,29 @@ func (l List) GoString() string {
 }
 
 // pnTime converts Go time.Time to Proton millisecond Unix time.
+// Take care to convert zero values to zero values.
 func pnTime(t time.Time) C.pn_timestamp_t {
-       secs := t.Unix()
-       // Note: sub-second accuracy is not guaranteed if the Unix time in
-       // nanoseconds cannot be represented by an int64 (sometime around year 
2260)
-       msecs := (t.UnixNano() % int64(time.Second)) / int64(time.Millisecond)
-       return C.pn_timestamp_t(secs*1000 + msecs)
+       if t.IsZero() {
+               return C.pn_timestamp_t(0)
+       }
+       return C.pn_timestamp_t(t.UnixNano() / int64(time.Millisecond))
 }
 
 // goTime converts a pn_timestamp_t to a Go time.Time.
+// Take care to convert zero values to zero values.
 func goTime(t C.pn_timestamp_t) time.Time {
-       secs := int64(t) / 1000
-       nsecs := (int64(t) % 1000) * int64(time.Millisecond)
-       return time.Unix(secs, nsecs)
+       if t == 0 {
+               return time.Time{}
+       }
+       return time.Unix(0, int64(t)*int64(time.Millisecond))
+}
+
+func pnDuration(d time.Duration) C.pn_millis_t {
+       return (C.pn_millis_t)(d / (time.Millisecond))
+}
+
+func goDuration(d C.pn_millis_t) time.Duration {
+       return time.Duration(d) * time.Millisecond
 }
 
 func goBytes(cBytes C.pn_bytes_t) (bytes []byte) {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ccaeaa0c/go/src/qpid.apache.org/amqp/types_test.go
----------------------------------------------------------------------
diff --git a/go/src/qpid.apache.org/amqp/types_test.go 
b/go/src/qpid.apache.org/amqp/types_test.go
index 994a3cd..d7e54f1 100644
--- a/go/src/qpid.apache.org/amqp/types_test.go
+++ b/go/src/qpid.apache.org/amqp/types_test.go
@@ -28,7 +28,7 @@ import (
 
 func checkEqual(want interface{}, got interface{}) error {
        if !reflect.DeepEqual(want, got) {
-               return fmt.Errorf("%#v != %#v", want, got)
+               return fmt.Errorf("(%T)%#v != (%T)%#v", want, want, got, got)
        }
        return nil
 }
@@ -200,3 +200,29 @@ func TestDescribed(t *testing.T) {
                t.Error(err)
        }
 }
+
+func TestTimeConversion(t *testing.T) {
+       pt := pnTime(timeValue)
+       if err := checkEqual(timeValue, goTime(pt)); err != nil {
+               t.Error(err)
+       }
+       if err := checkEqual(pt, pnTime(goTime(pt))); err != nil {
+               t.Error(err)
+       }
+       ut := time.Unix(123, 456*1000000)
+       if err := checkEqual(123456, int(pnTime(ut))); err != nil {
+               t.Error(err)
+       }
+       if err := checkEqual(ut, goTime(123456)); err != nil {
+               t.Error(err)
+       }
+
+       // Preserve zero values
+       var tz time.Time
+       if err := checkEqual(0, int(pnTime(tz))); err != nil {
+               t.Error(err)
+       }
+       if err := checkEqual(tz, goTime(pnTime(tz))); err != nil {
+               t.Error(err)
+       }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ccaeaa0c/go/src/qpid.apache.org/amqp/unmarshal.go
----------------------------------------------------------------------
diff --git a/go/src/qpid.apache.org/amqp/unmarshal.go 
b/go/src/qpid.apache.org/amqp/unmarshal.go
index 2c6e3f1..054f115 100644
--- a/go/src/qpid.apache.org/amqp/unmarshal.go
+++ b/go/src/qpid.apache.org/amqp/unmarshal.go
@@ -487,7 +487,7 @@ func unmarshal(v interface{}, data *C.pn_data_t) {
 
        case *time.Time:
                panicUnless(pnType == C.PN_TIMESTAMP, data, v)
-               *v = time.Unix(0, int64(C.pn_data_get_timestamp(data))*1000)
+               *v = goTime(C.pn_data_get_timestamp(data))
 
        case *UUID:
                panicUnless(pnType == C.PN_UUID, data, v)
@@ -566,7 +566,7 @@ func getInterface(data *C.pn_data_t, vp *interface{}) {
        case C.PN_SYMBOL:
                *vp = Symbol(goString(C.pn_data_get_symbol(data)))
        case C.PN_TIMESTAMP:
-               *vp = time.Unix(0, int64(C.pn_data_get_timestamp(data))*1000)
+               *vp = goTime(C.pn_data_get_timestamp(data))
        case C.PN_UUID:
                var u UUID
                unmarshal(&u, data)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to