Skip to content

Commit

Permalink
Merge pull request #34 from mailgun/maxim/develop
Browse files Browse the repository at this point in the history
Add NewDurationJSON
  • Loading branch information
horkhe authored Oct 2, 2018
2 parents d68f4f6 + 298f12f commit eb40d13
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 17 deletions.
45 changes: 30 additions & 15 deletions clock/duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,39 @@ package clock

import (
"encoding/json"
"fmt"
"time"

"github.com/pkg/errors"
)

type DurationJSON struct {
Duration time.Duration
str string
Duration Duration
}

func NewDurationJSON(v interface{}) (DurationJSON, error) {
switch v := v.(type) {
case Duration:
return DurationJSON{Duration: v}, nil
case float64:
return DurationJSON{Duration: Duration(v)}, nil
case int64:
return DurationJSON{Duration: Duration(v)}, nil
case int:
return DurationJSON{Duration: Duration(v)}, nil
case []byte:
duration, err := ParseDuration(string(v))
if err != nil {
return DurationJSON{}, errors.Wrap(err, "while parsing []byte")
}
return DurationJSON{Duration: duration}, nil
case string:
duration, err := ParseDuration(v)
if err != nil {
return DurationJSON{}, errors.Wrap(err, "while parsing string")
}
return DurationJSON{Duration: duration}, nil
default:
return DurationJSON{}, errors.Errorf("bad type %T", v)
}
}

func (d DurationJSON) MarshalJSON() ([]byte, error) {
Expand All @@ -25,19 +49,10 @@ func (d *DurationJSON) UnmarshalJSON(b []byte) error {
return err
}

switch value := v.(type) {
case float64:
d.Duration = time.Duration(value)
d.str = fmt.Sprintf("%f", value)
case string:
d.Duration, err = time.ParseDuration(value)
d.str = value
default:
return errors.New("invalid duration")
}
*d, err = NewDurationJSON(v)
return err
}

func (d DurationJSON) String() string {
return d.str
return d.Duration.String()
}
79 changes: 79 additions & 0 deletions clock/duration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package clock_test

import (
"encoding/json"
"testing"

"github.com/mailgun/holster/clock"
"github.com/stretchr/testify/suite"
)

type DurationSuite struct {
suite.Suite
}

func TestDurationSuite(t *testing.T) {
suite.Run(t, new(DurationSuite))
}

func (s *DurationSuite) TestNewOk() {
for _, v := range []interface{}{
42 * clock.Second,
int(42000000000),
int64(42000000000),
42000000000.,
"42s",
[]byte("42s"),
} {
d, err := clock.NewDurationJSON(v)
s.Nil(err)
s.Equal(42*clock.Second, d.Duration)
}
}

func (s *DurationSuite) TestNewError() {
for _, tc := range []struct {
v interface{}
errMsg string
}{{
v: "foo",
errMsg: "while parsing string: time: invalid duration foo",
}, {
v: []byte("foo"),
errMsg: "while parsing []byte: time: invalid duration foo",
}, {
v: true,
errMsg: "bad type bool",
}} {
d, err := clock.NewDurationJSON(tc.v)
s.Equal(tc.errMsg, err.Error())
s.Equal(clock.DurationJSON{}, d)
}
}

func (s *DurationSuite) TestUnmarshal() {
for _, v := range []string{
`{"foo": 42000000000}`,
`{"foo": 0.42e11}`,
`{"foo": "42s"}`,
} {
var withDuration struct {
Foo clock.DurationJSON `json:"foo"`
}
err := json.Unmarshal([]byte(v), &withDuration)
s.Nil(err)
s.Equal(42*clock.Second, withDuration.Foo.Duration)
}
}

func (s *DurationSuite) TestMarshalling() {
d, err := clock.NewDurationJSON(42 * clock.Second)
s.Nil(err)
encoded, err := d.MarshalJSON()
s.Nil(err)
var decoded clock.DurationJSON
err = decoded.UnmarshalJSON(encoded)
s.Nil(err)
s.Equal(d, decoded)
s.Equal("42s", decoded.String())
}
3 changes: 2 additions & 1 deletion clock/go19.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// +build go1.9

// This file introduces aliases to allow using of the clock package as a
// drop-in replacement of the standard time package.

// +build go1.9
package clock

import "time"
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.0
2.1.0

0 comments on commit eb40d13

Please sign in to comment.