Skip to content

Commit

Permalink
Marshal MicroTime to json and proto at the same precision
Browse files Browse the repository at this point in the history
Kubernetes-commit: 519e0d0a94b02ba32701afeaad5a388777836d62
  • Loading branch information
haoruan authored and k8s-publishing-bot committed Aug 19, 2022
1 parent cf171ba commit b4db414
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
10 changes: 8 additions & 2 deletions pkg/apis/meta/v1/micro_time_proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ func (m *MicroTime) ProtoMicroTime() *Timestamp {
if m == nil {
return &Timestamp{}
}

// truncate precision to microseconds to match JSON marshaling/unmarshaling
truncatedNanoseconds := time.Duration(m.Time.Nanosecond()).Truncate(time.Microsecond)
return &Timestamp{
Seconds: m.Time.Unix(),
Nanos: int32(m.Time.Nanosecond()),
Nanos: int32(truncatedNanoseconds),
}
}

Expand All @@ -51,7 +54,10 @@ func (m *MicroTime) Unmarshal(data []byte) error {
if err := p.Unmarshal(data); err != nil {
return err
}
m.Time = time.Unix(p.Seconds, int64(p.Nanos)).Local()

// truncate precision to microseconds to match JSON marshaling/unmarshaling
truncatedNanoseconds := time.Duration(p.Nanos).Truncate(time.Microsecond)
m.Time = time.Unix(p.Seconds, int64(truncatedNanoseconds)).Local()
return nil
}

Expand Down
67 changes: 66 additions & 1 deletion pkg/apis/meta/v1/micro_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func TestMicroTimeProto(t *testing.T) {
input MicroTime
}{
{MicroTime{}},
{DateMicro(1998, time.May, 5, 1, 5, 5, 50, time.Local)},
{DateMicro(1998, time.May, 5, 1, 5, 5, 1000, time.Local)},
{DateMicro(1998, time.May, 5, 5, 5, 5, 0, time.Local)},
}

Expand Down Expand Up @@ -253,3 +253,68 @@ func TestMicroTimeIsZero(t *testing.T) {
})
}
}

func TestMicroTimeUnmarshalJSONAndProtoEqual(t *testing.T) {
cases := []struct {
name string
input MicroTime
result bool
}{
{"nanosecond level precision", UnixMicro(123, 123123123), true},
{"microsecond level precision", UnixMicro(123, 123123000), true},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
jsonData, err := c.input.MarshalJSON()
if err != nil {
t.Fatalf("Failed to marshal input to JSON: '%v': %v", c.input, err)
}

protoData, err := c.input.Marshal()
if err != nil {
t.Fatalf("Failed to marshal input to proto: '%v': %v", c.input, err)
}

var tJSON, tProto MicroTime
if err = tJSON.UnmarshalJSON(jsonData); err != nil {
t.Fatalf("Failed to unmarshal JSON: '%v': %v", jsonData, err)
}
if err = tProto.Unmarshal(protoData); err != nil {
t.Fatalf("Failed to unmarshal proto: '%v': %v", protoData, err)
}

result := tJSON.Equal(&tProto)
if result != c.result {
t.Errorf("Failed equality test for '%v': expected %+v, got %+v", c.input, c.result, result)
}
})
}
}

func TestMicroTimeProtoUnmarshalRaw(t *testing.T) {
cases := []struct {
name string
input []byte
expected MicroTime
}{
// input is generated by Timestamp{123, 123123123}.Marshal()
{"nanosecond level precision", []byte{8, 123, 16, 179, 235, 218, 58}, UnixMicro(123, 123123000)},
// input is generated by Timestamp{123, 123123000}.Marshal()
{"microsecond level precision", []byte{8, 123, 16, 184, 234, 218, 58}, UnixMicro(123, 123123000)},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
var actual MicroTime
if err := actual.Unmarshal(c.input); err != nil {
t.Fatalf("Failed to unmarshal proto: '%v': %v", c.input, err)
}

if !actual.Equal(&c.expected) {
t.Errorf("Failed unmarshal from nanosecond-precise raw for '%v': expected %+v, got %+v", c.input, c.expected, actual)
}
})
}

}

0 comments on commit b4db414

Please sign in to comment.