diff --git a/pkg/api/unversioned/time_proto.go b/pkg/api/unversioned/time_proto.go index 3ffc9a7e04..496d5d98ce 100644 --- a/pkg/api/unversioned/time_proto.go +++ b/pkg/api/unversioned/time_proto.go @@ -47,24 +47,39 @@ func (m *Time) ProtoTime() *Timestamp { } // Size implements the protobuf marshalling interface. -func (m *Time) Size() (n int) { return m.ProtoTime().Size() } +func (m *Time) Size() (n int) { + if m == nil || m.Time.IsZero() { + return 0 + } + return m.ProtoTime().Size() +} // Reset implements the protobuf marshalling interface. func (m *Time) Unmarshal(data []byte) error { + if len(data) == 0 { + m.Time = time.Time{} + return nil + } p := Timestamp{} if err := p.Unmarshal(data); err != nil { return err } - m.Time = time.Unix(p.Seconds, int64(p.Nanos)) + m.Time = time.Unix(p.Seconds, int64(p.Nanos)).Local() return nil } // Marshal implements the protobuf marshalling interface. func (m *Time) Marshal() (data []byte, err error) { + if m == nil || m.Time.IsZero() { + return nil, nil + } return m.ProtoTime().Marshal() } // MarshalTo implements the protobuf marshalling interface. func (m *Time) MarshalTo(data []byte) (int, error) { + if m == nil || m.Time.IsZero() { + return 0, nil + } return m.ProtoTime().MarshalTo(data) } diff --git a/pkg/api/unversioned/time_test.go b/pkg/api/unversioned/time_test.go index 2f4f3696d6..60c61a7378 100644 --- a/pkg/api/unversioned/time_test.go +++ b/pkg/api/unversioned/time_test.go @@ -18,6 +18,7 @@ package unversioned import ( "encoding/json" + "reflect" "testing" "time" @@ -145,3 +146,28 @@ func TestTimeMarshalJSONUnmarshalYAML(t *testing.T) { } } } + +func TestTimeProto(t *testing.T) { + cases := []struct { + input Time + }{ + {Time{}}, + {Date(1998, time.May, 5, 1, 5, 5, 50, time.Local)}, + {Date(1998, time.May, 5, 5, 5, 5, 0, time.Local)}, + } + + for _, c := range cases { + input := c.input + data, err := input.Marshal() + if err != nil { + t.Fatalf("Failed to marshal input: '%v': %v", input, err) + } + time := Time{} + if err := time.Unmarshal(data); err != nil { + t.Fatalf("Failed to unmarshal output: '%v': %v", input, err) + } + if !reflect.DeepEqual(input, time) { + t.Errorf("Marshal->Unmarshal is not idempotent: '%v' vs '%v'", input, time) + } + } +}