Skip to content

Commit

Permalink
Add MarshalText and UnmarshalText for Duration
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Loibl <mail@matthiasloibl.com>

This is mostly needed for https://github.com/alecthomas/kong.
Furthermore it should be useful for others too, as it implements stdlib
interfaces.
  • Loading branch information
metalmatze committed Feb 9, 2021
1 parent 1537f7d commit ee8cd20
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
12 changes: 12 additions & 0 deletions model/time.go
Expand Up @@ -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
Expand Down
73 changes: 73 additions & 0 deletions model/time_test.go
Expand Up @@ -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",
Expand Down

0 comments on commit ee8cd20

Please sign in to comment.