From 4ac4f00378f403715e68ae8827a8b1d8e9addf4a Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 14 Sep 2015 05:33:34 +0900 Subject: [PATCH] MarshalText, UnmarshalText for Time --- time.go | 22 +++++++++++++++++++++- time_test.go | 29 ++++++++++++++++++++++++++++- zero/time.go | 21 +++++++++++++++++++++ zero/time_test.go | 30 +++++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/time.go b/time.go index de1f5b3..a4d8439 100644 --- a/time.go +++ b/time.go @@ -66,7 +66,7 @@ func (t Time) MarshalJSON() ([]byte, error) { if !t.Valid { return []byte("null"), nil } - return json.Marshal(t.Time) + return t.Time.MarshalJSON() } // UnmarshalJSON implements json.Unmarshaler. @@ -100,6 +100,26 @@ func (t *Time) UnmarshalJSON(data []byte) error { return err } +func (t Time) MarshalText() ([]byte, error) { + if !t.Valid { + return []byte("null"), nil + } + return t.Time.MarshalText() +} + +func (t *Time) UnmarshalText(text []byte) error { + str := string(text) + if str == "" || str == "null" { + t.Valid = false + return nil + } + if err := t.Time.UnmarshalText(text); err != nil { + return err + } + t.Valid = true + return nil +} + // SetValid changes this Time's value and sets it to be non-null. func (t *Time) SetValid(v time.Time) { t.Time = v diff --git a/time_test.go b/time_test.go index 6e1b432..e3c0bfd 100644 --- a/time_test.go +++ b/time_test.go @@ -16,7 +16,7 @@ var ( badObject = []byte(`{"hello": "world"}`) ) -func TestUnmarshalTimeString(t *testing.T) { +func TestUnmarshalTimeJSON(t *testing.T) { var ti Time err := json.Unmarshal(timeJSON, &ti) maybePanic(err) @@ -59,6 +59,33 @@ func TestUnmarshalTimeString(t *testing.T) { assertNullTime(t, wrongType, "wrong type object json") } +func TestUnmarshalTimeText(t *testing.T) { + ti := TimeFrom(timeValue) + txt, err := ti.MarshalText() + maybePanic(err) + assertJSONEquals(t, txt, timeString, "marshal text") + + var unmarshal Time + err = unmarshal.UnmarshalText(txt) + maybePanic(err) + assertTime(t, unmarshal, "unmarshal text") + + var null Time + err = null.UnmarshalText(nullJSON) + maybePanic(err) + assertNullTime(t, null, "unmarshal null text") + txt, err = null.MarshalText() + maybePanic(err) + assertJSONEquals(t, txt, string(nullJSON), "marshal null text") + + var invalid Time + err = invalid.UnmarshalText([]byte("hello world")) + if err == nil { + t.Error("expected error") + } + assertNullTime(t, invalid, "bad string") +} + func TestMarshalTime(t *testing.T) { ti := TimeFrom(timeValue) data, err := json.Marshal(ti) diff --git a/zero/time.go b/zero/time.go index 7af26c2..0e842ba 100644 --- a/zero/time.go +++ b/zero/time.go @@ -107,6 +107,27 @@ func (t *Time) UnmarshalJSON(data []byte) error { } } +func (t Time) MarshalText() ([]byte, error) { + ti := t.Time + if !t.Valid { + ti = time.Time{} + } + return ti.MarshalText() +} + +func (t *Time) UnmarshalText(text []byte) error { + str := string(text) + if str == "" || str == "null" { + t.Valid = false + return nil + } + if err := t.Time.UnmarshalText(text); err != nil { + return err + } + t.Valid = true + return nil +} + // SetValid changes this Time's value and // sets it to be non-null. func (t *Time) SetValid(v time.Time) { diff --git a/zero/time_test.go b/zero/time_test.go index b1bbe78..fa1dd9a 100644 --- a/zero/time_test.go +++ b/zero/time_test.go @@ -9,6 +9,7 @@ import ( var ( timeString = "2012-12-21T21:21:21Z" timeJSON = []byte(`"` + timeString + `"`) + zeroTimeStr = "0001-01-01T00:00:00Z" zeroTimeJSON = []byte(`"0001-01-01T00:00:00Z"`) blankTimeJSON = []byte(`null`) timeValue, _ = time.Parse(time.RFC3339, timeString) @@ -17,7 +18,7 @@ var ( badObject = []byte(`{"hello": "world"}`) ) -func TestUnmarshalTimeString(t *testing.T) { +func TestUnmarshalTimeJSON(t *testing.T) { var ti Time err := json.Unmarshal(timeObject, &ti) maybePanic(err) @@ -89,6 +90,33 @@ func TestMarshalTime(t *testing.T) { assertJSONEquals(t, data, string(zeroTimeJSON), "empty json marshal") } +func TestUnmarshalTimeText(t *testing.T) { + ti := TimeFrom(timeValue) + txt, err := ti.MarshalText() + maybePanic(err) + assertJSONEquals(t, txt, timeString, "marshal text") + + var unmarshal Time + err = unmarshal.UnmarshalText(txt) + maybePanic(err) + assertTime(t, unmarshal, "unmarshal text") + + var null Time + err = null.UnmarshalText(nullJSON) + maybePanic(err) + assertNullTime(t, null, "unmarshal null text") + txt, err = null.MarshalText() + maybePanic(err) + assertJSONEquals(t, txt, zeroTimeStr, "marshal null text") + + var invalid Time + err = invalid.UnmarshalText([]byte("hello world")) + if err == nil { + t.Error("expected error") + } + assertNullTime(t, invalid, "bad string") +} + func TestTimeFrom(t *testing.T) { ti := TimeFrom(timeValue) assertTime(t, ti, "TimeFrom() time.Time")