Skip to content

Commit

Permalink
Merge pull request #540 from benluddy/output-invalid-rfc3339
Browse files Browse the repository at this point in the history
Fix invalid RFC 3339 in TimeTagToAny (unreleased new feature)
  • Loading branch information
fxamacker authored May 26, 2024
2 parents 6017d7f + 77c571a commit 842ac3e
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
16 changes: 14 additions & 2 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -1890,12 +1890,24 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (interface{}, error) { //noli
if tagNum == 1 {
tm = tm.UTC()
}
return tm.Format(time.RFC3339), nil
// Formats to RFC3339 and errors on time.Time values that cannot be
// represented by RFC3339.
text, err := tm.Truncate(time.Second).MarshalText()
if err != nil {
return nil, err
}
return string(text), nil
case TimeTagToRFC3339Nano:
if tagNum == 1 {
tm = tm.UTC()
}
return tm.Format(time.RFC3339Nano), nil
// Formats to RFC3339 with subsecond precision and errors on
// time.Time values that cannot be represented by RFC3339.
text, err := tm.MarshalText()
if err != nil {
return nil, err
}
return string(text), nil
default:
// not reachable
}
Expand Down
41 changes: 36 additions & 5 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8856,10 +8856,11 @@ func TestDecModeInvalidTimeTagToAnyMode(t *testing.T) {

func TestDecModeTimeTagToAny(t *testing.T) {
for _, tc := range []struct {
name string
opts DecOptions
in []byte
want interface{}
name string
opts DecOptions
in []byte
want interface{}
wantErrMessage string
}{
{
name: "Unmarshal tag 0 data to time.Time when TimeTagToAny is not set",
Expand Down Expand Up @@ -8897,6 +8898,30 @@ func TestDecModeTimeTagToAny(t *testing.T) {
in: hexDecode("c1fb41d452d9ec200000"),
want: "2013-03-21T20:04:00.5Z",
},
{
name: "error under TimeTagToRFC3339 when tag 0 contains an invalid RFC3339 timestamp",
opts: DecOptions{TimeTagToAny: TimeTagToRFC3339},
in: hexDecode("c07731303030302D30332D32315432303A30343A30302E355A"), // 0("10000-03-21T20:04:00.5Z")
wantErrMessage: `cbor: cannot set 10000-03-21T20:04:00.5Z for time.Time: parsing time "10000-03-21T20:04:00.5Z" as "2006-01-02T15:04:05Z07:00": cannot parse "0-03-21T20:04:00.5Z" as "-"`,
},
{
name: "error under TimeTagToRFC3339Nano when tag 0 contains an invalid RFC3339 timestamp",
opts: DecOptions{TimeTagToAny: TimeTagToRFC3339Nano},
in: hexDecode("c07731303030302D30332D32315432303A30343A30302E355A"), // 0("10000-03-21T20:04:00.5Z")
wantErrMessage: `cbor: cannot set 10000-03-21T20:04:00.5Z for time.Time: parsing time "10000-03-21T20:04:00.5Z" as "2006-01-02T15:04:05Z07:00": cannot parse "0-03-21T20:04:00.5Z" as "-"`,
},
{
name: "error under TimeTagToRFC3339 when tag 1 represents a time that can't be represented by valid RFC3339",
opts: DecOptions{TimeTagToAny: TimeTagToRFC3339},
in: hexDecode("c11b0000003afff44181"), // 1(253402300801)
wantErrMessage: "Time.MarshalText: year outside of range [0,9999]",
},
{
name: "error under TimeTagToRFC3339Nano when tag 1 represents a time that can't be represented by valid RFC3339",
opts: DecOptions{TimeTagToAny: TimeTagToRFC3339Nano},
in: hexDecode("c11b0000003afff44181"), // 1(253402300801)
wantErrMessage: "Time.MarshalText: year outside of range [0,9999]",
},
} {
t.Run(tc.name, func(t *testing.T) {
dm, err := tc.opts.DecMode()
Expand All @@ -8906,7 +8931,13 @@ func TestDecModeTimeTagToAny(t *testing.T) {

var got interface{}
if err := dm.Unmarshal(tc.in, &got); err != nil {
t.Errorf("unexpected error: %v", err)
if tc.wantErrMessage == "" {
t.Fatalf("unexpected error: %v", err)
} else if gotErrMessage := err.Error(); tc.wantErrMessage != gotErrMessage {
t.Fatalf("want error %q, got %q", tc.wantErrMessage, gotErrMessage)
}
} else if tc.wantErrMessage != "" {
t.Fatalf("got nil error, want %q", tc.wantErrMessage)
}

compareNonFloats(t, tc.in, got, tc.want)
Expand Down

0 comments on commit 842ac3e

Please sign in to comment.