Skip to content

Commit

Permalink
simplify marshal/ummarshal logic, make parser stricter, update tests,…
Browse files Browse the repository at this point in the history
… fix readme (#5)
  • Loading branch information
sosodev authored Apr 28, 2024
1 parent 21da944 commit 74537b7
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 14 deletions.
27 changes: 16 additions & 11 deletions duration.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package duration

import (
"encoding/json"
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"
"unicode"
)
Expand Down Expand Up @@ -47,6 +49,10 @@ var (
// Parse attempts to parse the given duration string into a *Duration,
// if parsing fails an error is returned instead
func Parse(d string) (*Duration, error) {
if !strings.Contains(d, "P") {
return nil, ErrUnexpectedInput
}

state := parsingPeriod
duration := &Duration{}
num := ""
Expand Down Expand Up @@ -277,25 +283,24 @@ func (duration *Duration) String() string {
return d
}

// MarshalJSON satisfies the Marshaler interface by return a valid JSON string representation of the duration
func (duration Duration) MarshalJSON() ([]byte, error) {
return []byte("\"" + duration.String() + "\""), nil
return json.Marshal(duration.String())
}

// UnmarshalJSON satisfies the Unmarshaler interface by return a valid JSON string representation of the duration
func (duration *Duration) UnmarshalJSON(source []byte) error {
strVal := string(source)
if len(strVal) < 2 {
return fmt.Errorf("invalid ISO 8601 duration: %s", strVal)
}
strVal = strVal[1 : len(strVal)-1]

if strVal == "null" {
return nil
durationString := ""
err := json.Unmarshal(source, &durationString)
if err != nil {
return err
}

parsed, err := Parse(strVal)
parsed, err := Parse(durationString)
if err != nil {
return fmt.Errorf("invalid ISO 8601 duration: %s", strVal)
return fmt.Errorf("failed to parse duration: %w", err)
}

*duration = *parsed
return nil
}
10 changes: 8 additions & 2 deletions duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ func TestParse(t *testing.T) {
want *Duration
wantErr bool
}{
{
name: "invalid-duration-1",
args: args{d: "T0S"},
want: nil,
wantErr: true,
},
{
name: "period-only",
args: args{d: "P4Y"},
Expand All @@ -27,7 +33,7 @@ func TestParse(t *testing.T) {
},
{
name: "time-only-decimal",
args: args{d: "T2.5S"},
args: args{d: "PT2.5S"},
want: &Duration{
Seconds: 2.5,
},
Expand Down Expand Up @@ -245,7 +251,7 @@ func TestDuration_String(t *testing.T) {
t.Errorf("expected: %s, got: %s", "P3Y6M4DT12H30M33.3333S", duration.String())
}

smallDuration, err := Parse("T0.0000000000001S")
smallDuration, err := Parse("PT0.0000000000001S")
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func main() {
fmt.Println(d.Minutes) // 30
fmt.Println(d.Seconds) // 5.5

d, err = duration.Parse("T33.3S")
d, err = duration.Parse("PT33.3S")
if err != nil {
panic(err)
}
Expand Down

0 comments on commit 74537b7

Please sign in to comment.