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]
