Skip to content

Q: Time Format "unix" #170

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
lmittmann opened this issue Apr 16, 2025 · 7 comments
Closed

Q: Time Format "unix" #170

lmittmann opened this issue Apr 16, 2025 · 7 comments

Comments

@lmittmann
Copy link

lmittmann commented Apr 16, 2025

Is it really intended, that the time format unix encodes a time.Time with nanoseconds as a float? I would have expected and int.

func TestTime(t *testing.T) {
	type times struct {
		Time  time.Time `json:"time,format:unix"`
		Time2 time.Time `json:"time2,format:unixmilli"`
		Time3 time.Time `json:"time3,format:unixmicro"`
		Time4 time.Time `json:"time4,format:unixnano"`
	}

	enc, err := json.Marshal(times{
		Time:  time.Unix(123, 123),
		Time2: time.Unix(123, 123),
		Time3: time.Unix(123, 123),
		Time4: time.Unix(123, 123),
	})
	if err != nil {
		t.Fatal(err)
	}
	t.Log(string(enc))
	// Output: {"time":123.000000123,"time2":123000.000123,"time3":123000000.123,"time4":123000000123}
}
@dsnet
Copy link
Collaborator

dsnet commented Apr 16, 2025

Hi, thanks for question.

It's outputting the Unix timestamp in seconds. How else would you expect it to represent sub-second precision if it were an integer?

@dsnet
Copy link
Collaborator

dsnet commented Apr 16, 2025

Note that if you round to the nearest second, then the sub-second fraction is missing, making it equivalent to a JSON integer.

@lmittmann
Copy link
Author

My expectation was, that I get only the seconds (as int). Basically the same as if I call https://pkg.go.dev/time#Time.Unix, or https://pkg.go.dev/time#Time.UnixMilli, ...

// My expectation {"time":123,"time2":123000,"time3":123000000,"time4":123000000123}

@dsnet
Copy link
Collaborator

dsnet commented Apr 16, 2025

With the current semantics, you could accomplish what you expect by first calling Round(time.Second), but with what you're proposing, I'm not sure how someone would be able to obtain a high-precision timestamp since information would always be lost. It seems that more precision by default is also the safer option.

@lmittmann
Copy link
Author

Rounding every time before marshaling seems impractical. For what it's worth, with json/v2 it is straight forward to get my expected behavior via a custom option.

I'm not sure how someone would be able to obtain a high-precision timestamp since information would always be lost. It seems that more precision by default is also the safer option.

I disagree. If one needs high precision there is high precision formats like format:unixnano, if one needs less precision there could be format:unix with only the seconds. The current implementation does not give an option to choose between the precision needed, as each format has nonosecond precision.

Additionally there are the matching time.Time methods, that only expose a time down to it's respective precision. I would expect the same behavior from the json/v2 package.

time.Time json/v2 format
Unix() int64 format:unix
UnixMilli() int64 format:unixmilli
UnixMicro() int64 format:unixmicro
UnixNano() int64 format:unixnano

@dsnet
Copy link
Collaborator

dsnet commented Apr 17, 2025

I understand what you're saying, but there's a difference between the format (i.e., the representation of a timestamp as a number with the units of seconds) versus the precision, as those are somewhat orthogonal concerns.

This is going beyond a question now and into the territory of a proposal where we can benefit from wider discussion. I recommend you file a proposal at https://github.com/golang/go/issues and tag golang/go#71497 as the parent issue. Thanks.

@dsnet dsnet closed this as completed Apr 17, 2025
@lmittmann
Copy link
Author

I created the proposal golang/go#73486.

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

No branches or pull requests

2 participants