Skip to content

time | encoding/json: time value not the same after encoding/decoding #17875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pierrre opened this issue Nov 10, 2016 · 3 comments
Closed

time | encoding/json: time value not the same after encoding/decoding #17875

pierrre opened this issue Nov 10, 2016 · 3 comments

Comments

@pierrre
Copy link

pierrre commented Nov 10, 2016

What version of Go are you using (go version)?

go1.7.3 linux/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/pierre/Go"
GORACE=""
GOROOT="/home/pierre/.gimme/versions/go1.7.3.src"
GOTOOLDIR="/home/pierre/.gimme/versions/go1.7.3.src/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build879209547=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"

What did you do?

My code

func TestTime(t *testing.T) {
	type A struct {
		T time.Time
	}
	v1 := A{
		T: time.Now(),
	}
	b, err := json.Marshal(v1)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(string(b))
	var v2 A
	err = json.Unmarshal(b, &v2)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(reflect.DeepEqual(v1, v2))
	t.Logf("%s %#v %s", v1.T, v1.T, v1.T.Location())
	t.Logf("%s %#v %s", v2.T, v2.T, v2.T.Location())
}

What did you expect to see?

On my local computer (I live in France)

	http_test.go:28: {"T":"2016-11-10T15:22:49.975623925+01:00"}
	http_test.go:34: true
	http_test.go:35: 2016-11-10 15:22:49.975623925 +0100 CET time.Time{sec:63614384569, nsec:975623925, loc:(*time.Location)(0x9bfc60)} Local
	http_test.go:36: 2016-11-10 15:22:49.975623925 +0100 CET time.Time{sec:63614384569, nsec:975623925, loc:(*time.Location)(0x9bfc60)} Local

What did you see instead?

On Travis CI

	http_test.go:28: {"T":"2016-11-10T14:15:29.853905878Z"}
	http_test.go:34: false
	http_test.go:35: 2016-11-10 14:15:29.853905878 +0000 UTC time.Time{sec:63614384129, nsec:853905878, loc:(*time.Location)(0x9c5aa0)} Local
	http_test.go:36: 2016-11-10 14:15:29.853905878 +0000 UTC time.Time{sec:63614384129, nsec:853905878, loc:(*time.Location)(0x9adda0)} UTC

The locations in the time are not equal.

Is it expected ?
Is it a bug ?
What should I do instead ? (I want my 2 structs to be equal with reflect.DeepEqual())

@quentinmit
Copy link
Contributor

This is working as intended. You need to use t1.Equal(t2) to compare times. reflect.DeepEqual and the == operator do not work.

@pierrre
Copy link
Author

pierrre commented Nov 10, 2016

Thank you for your answer.

Unfortunately it will be very difficult to me to use time.Time.Equal(), because my struct (in my real code) has several fields.
reflect.DeepEqual() is more convenient. (I want to compare all the struct values)

Is it possible to change reflect.DeepEqual to make it use time.Time.Equal() ?
I understand perfectly if you don't want to do it.

Do you know a third party library that support it ?

Is comparing JSON encoded values a valid alternative ?
Is the JSON encoding deterministic ? (fields order)

In the mean time I found a "fix" for my code:
I force the time's location with .In(time.UTC).

@bradfitz
Copy link
Contributor

For questions about Go, see https://golang.org/wiki/Questions

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants