From ee8cd207c8a4e82f57db368233af561f70c23f33 Mon Sep 17 00:00:00 2001 From: Matthias Loibl Date: Mon, 8 Feb 2021 17:19:52 +0100 Subject: [PATCH] Add MarshalText and UnmarshalText for Duration Signed-off-by: Matthias Loibl This is mostly needed for https://github.com/alecthomas/kong. Furthermore it should be useful for others too, as it implements stdlib interfaces. --- model/time.go | 12 ++++++++ model/time_test.go | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/model/time.go b/model/time.go index c40e6403..77b82b2b 100644 --- a/model/time.go +++ b/model/time.go @@ -254,6 +254,18 @@ func (d Duration) String() string { return r } +// MarshalText implements the encoding.TextMarshaler interface. +func (d *Duration) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (d *Duration) UnmarshalText(text []byte) error { + var err error + *d, err = ParseDuration(string(text)) + return err +} + // MarshalYAML implements the yaml.Marshaler interface. func (d Duration) MarshalYAML() (interface{}, error) { return d.String(), nil diff --git a/model/time_test.go b/model/time_test.go index d9c67891..14fb9eb9 100644 --- a/model/time_test.go +++ b/model/time_test.go @@ -157,6 +157,79 @@ func TestParseDuration(t *testing.T) { } } +func TestDuration_UnmarshalText(t *testing.T) { + var cases = []struct { + in string + out time.Duration + + expectedString string + }{ + { + in: "0", + out: 0, + expectedString: "0s", + }, { + in: "0w", + out: 0, + expectedString: "0s", + }, { + in: "0s", + out: 0, + }, { + in: "324ms", + out: 324 * time.Millisecond, + }, { + in: "3s", + out: 3 * time.Second, + }, { + in: "5m", + out: 5 * time.Minute, + }, { + in: "1h", + out: time.Hour, + }, { + in: "4d", + out: 4 * 24 * time.Hour, + }, { + in: "4d1h", + out: 4*24*time.Hour + time.Hour, + }, { + in: "14d", + out: 14 * 24 * time.Hour, + expectedString: "2w", + }, { + in: "3w", + out: 3 * 7 * 24 * time.Hour, + }, { + in: "3w2d1h", + out: 3*7*24*time.Hour + 2*24*time.Hour + time.Hour, + expectedString: "23d1h", + }, { + in: "10y", + out: 10 * 365 * 24 * time.Hour, + }, + } + + for _, c := range cases { + var d Duration + err := d.UnmarshalText([]byte(c.in)) + if err != nil { + t.Errorf("Unexpected error on input %q", c.in) + } + if time.Duration(d) != c.out { + t.Errorf("Expected %v but got %v", c.out, d) + } + expectedString := c.expectedString + if c.expectedString == "" { + expectedString = c.in + } + text, _ := d.MarshalText() // MarshalText returns hardcoded nil + if string(text) != expectedString { + t.Errorf("Expected duration string %q but got %q", c.in, d.String()) + } + } +} + func TestParseBadDuration(t *testing.T) { var cases = []string{ "1",