From ed23d71ff86a68b4a969a166dcc7b588ddc1f84e Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Wed, 2 Sep 2020 13:50:01 -0400 Subject: [PATCH] cephfs admin: add TimeStamp type for JSON unmarshaling The date & time format used by ceph differs from the default used by Go for time.Time types. Define a new type, embedding time.Time, that can parse and expressing date+time strings the ceph way. Signed-off-by: John Mulligan --- cephfs/admin/timestamp.go | 39 ++++++++++++++++++++++++++++++ cephfs/admin/timestamp_test.go | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 cephfs/admin/timestamp.go create mode 100644 cephfs/admin/timestamp_test.go diff --git a/cephfs/admin/timestamp.go b/cephfs/admin/timestamp.go new file mode 100644 index 0000000..424fab6 --- /dev/null +++ b/cephfs/admin/timestamp.go @@ -0,0 +1,39 @@ +// +build !luminous,!mimic + +package admin + +import ( + "encoding/json" + "time" +) + +// golang's date parsing approach is rather bizarre +var cephTSLayout = "2006-01-02 15:04:05" + +// TimeStamp abstracts some of the details about date+time stamps +// returned by ceph via JSON. +type TimeStamp struct { + time.Time +} + +// String returns a string representing the date+time as presented +// by ceph. +func (ts TimeStamp) String() string { + return ts.Format(cephTSLayout) +} + +// UnmarshalJSON implements the json Unmarshaler interface. +func (ts *TimeStamp) UnmarshalJSON(b []byte) error { + var raw string + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + // AFAICT, ceph always returns the time in UTC so Parse, as opposed to + // ParseInLocation, is appropriate here. + t, err := time.Parse(cephTSLayout, raw) + if err != nil { + return err + } + *ts = TimeStamp{t} + return nil +} diff --git a/cephfs/admin/timestamp_test.go b/cephfs/admin/timestamp_test.go new file mode 100644 index 0000000..84be586 --- /dev/null +++ b/cephfs/admin/timestamp_test.go @@ -0,0 +1,44 @@ +// +build !luminous,!mimic + +package admin + +import ( + "encoding/json" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestTimeStampUnmarshal(t *testing.T) { + t.Run("valid", func(t *testing.T) { + j1 := []byte(`"2020-01-03 18:03:21"`) + var ts TimeStamp + err := json.Unmarshal(j1, &ts) + assert.NoError(t, err) + assert.Equal(t, 2020, ts.Year()) + assert.Equal(t, time.Month(1), ts.Month()) + assert.Equal(t, 3, ts.Day()) + }) + t.Run("badType", func(t *testing.T) { + j1 := []byte(`["2020-01-03 18:03:21"]`) + var ts TimeStamp + err := json.Unmarshal(j1, &ts) + assert.Error(t, err) + }) + t.Run("badValue", func(t *testing.T) { + j1 := []byte(`"just another manic monday"`) + var ts TimeStamp + err := json.Unmarshal(j1, &ts) + assert.Error(t, err) + }) +} + +func TestTimeStampString(t *testing.T) { + s := "2020-11-06 11:33:56" + ti, err := time.Parse(cephTSLayout, s) + if assert.NoError(t, err) { + ts := TimeStamp{ti} + assert.Equal(t, s, ts.String()) + } +}