Skip to content

Commit 3ebd397

Browse files
author
Julien Pivotto
authored
Merge pull request #280 from 56quarters/duration-json
Add methods to model.Duration for JSON marshalling and unmarshalling
2 parents 47ee79a + 745afa4 commit 3ebd397

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

model/time.go

+20
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package model
1515

1616
import (
17+
"encoding/json"
1718
"fmt"
1819
"math"
1920
"regexp"
@@ -254,6 +255,25 @@ func (d Duration) String() string {
254255
return r
255256
}
256257

258+
// MarshalJSON implements the json.Marshaler interface.
259+
func (d Duration) MarshalJSON() ([]byte, error) {
260+
return json.Marshal(d.String())
261+
}
262+
263+
// UnmarshalJSON implements the json.Unmarshaler interface.
264+
func (d *Duration) UnmarshalJSON(bytes []byte) error {
265+
var s string
266+
if err := json.Unmarshal(bytes, &s); err != nil {
267+
return err
268+
}
269+
dur, err := ParseDuration(s)
270+
if err != nil {
271+
return err
272+
}
273+
*d = dur
274+
return nil
275+
}
276+
257277
// MarshalText implements the encoding.TextMarshaler interface.
258278
func (d *Duration) MarshalText() ([]byte, error) {
259279
return []byte(d.String()), nil

model/time_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package model
1515

1616
import (
17+
"encoding/json"
1718
"strconv"
1819
"testing"
1920
"time"
@@ -230,6 +231,82 @@ func TestDuration_UnmarshalText(t *testing.T) {
230231
}
231232
}
232233

234+
func TestDuration_UnmarshalJSON(t *testing.T) {
235+
var cases = []struct {
236+
in string
237+
out time.Duration
238+
239+
expectedString string
240+
}{
241+
{
242+
in: `"0"`,
243+
out: 0,
244+
expectedString: `"0s"`,
245+
}, {
246+
in: `"0w"`,
247+
out: 0,
248+
expectedString: `"0s"`,
249+
}, {
250+
in: `"0s"`,
251+
out: 0,
252+
}, {
253+
in: `"324ms"`,
254+
out: 324 * time.Millisecond,
255+
}, {
256+
in: `"3s"`,
257+
out: 3 * time.Second,
258+
}, {
259+
in: `"5m"`,
260+
out: 5 * time.Minute,
261+
}, {
262+
in: `"1h"`,
263+
out: time.Hour,
264+
}, {
265+
in: `"4d"`,
266+
out: 4 * 24 * time.Hour,
267+
}, {
268+
in: `"4d1h"`,
269+
out: 4*24*time.Hour + time.Hour,
270+
}, {
271+
in: `"14d"`,
272+
out: 14 * 24 * time.Hour,
273+
expectedString: `"2w"`,
274+
}, {
275+
in: `"3w"`,
276+
out: 3 * 7 * 24 * time.Hour,
277+
}, {
278+
in: `"3w2d1h"`,
279+
out: 3*7*24*time.Hour + 2*24*time.Hour + time.Hour,
280+
expectedString: `"23d1h"`,
281+
}, {
282+
in: `"10y"`,
283+
out: 10 * 365 * 24 * time.Hour,
284+
},
285+
}
286+
287+
for _, c := range cases {
288+
var d Duration
289+
err := json.Unmarshal([]byte(c.in), &d)
290+
if err != nil {
291+
t.Errorf("Unexpected error on input %q", c.in)
292+
}
293+
if time.Duration(d) != c.out {
294+
t.Errorf("Expected %v but got %v", c.out, d)
295+
}
296+
expectedString := c.expectedString
297+
if c.expectedString == "" {
298+
expectedString = c.in
299+
}
300+
bytes, err := json.Marshal(d)
301+
if err != nil {
302+
t.Errorf("Unexpected error on marshal of %v: %s", d, err)
303+
}
304+
if string(bytes) != expectedString {
305+
t.Errorf("Expected duration string %q but got %q", c.in, d.String())
306+
}
307+
}
308+
}
309+
233310
func TestParseBadDuration(t *testing.T) {
234311
var cases = []string{
235312
"1",

0 commit comments

Comments
 (0)