diff --git a/rfc2822.go b/rfc2822.go index e511d75e..e02c1123 100644 --- a/rfc2822.go +++ b/rfc2822.go @@ -2,11 +2,12 @@ package mailgun import ( "strconv" - "strings" "time" + + "github.com/pkg/errors" ) -// Mailgun uses RFC2822 format for timestamps everywhere ('Thu, 13 Oct 2011 18:02:00 GMT'), but +// RFC2822Time Mailgun uses RFC2822 format for timestamps everywhere ('Thu, 13 Oct 2011 18:02:00 GMT'), but // by default Go's JSON package uses another format when decoding/encoding timestamps. type RFC2822Time time.Time @@ -35,15 +36,18 @@ func (t *RFC2822Time) UnmarshalJSON(s []byte) error { if err != nil { return err } - if *(*time.Time)(t), err = time.Parse(time.RFC1123, q); err != nil { - if strings.Contains(err.Error(), "extra text") { - if *(*time.Time)(t), err = time.Parse(time.RFC1123Z, q); err != nil { - return err - } - return nil + + var err1 error + *(*time.Time)(t), err1 = time.Parse(time.RFC1123, q) + if err1 != nil { + var err2 error + *(*time.Time)(t), err2 = time.Parse(time.RFC1123Z, q) + if err2 != nil { + // TODO(go1.20): use errors.Join: + return errors.Errorf("%s; %s", err1, err2) } - return err } + return nil } diff --git a/rfc2822_test.go b/rfc2822_test.go new file mode 100644 index 00000000..91348009 --- /dev/null +++ b/rfc2822_test.go @@ -0,0 +1,49 @@ +package mailgun + +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/facebookgo/ensure" +) + +func TestUnmarshalRFC2822Time(t *testing.T) { + type Req struct { + CreatedAt RFC2822Time `json:"created_at"` + } + + tests := []struct { + name string + s string + want Req + wantErr bool + }{ + { + name: "RFC1123", + s: `{"created_at":"Thu, 13 Oct 2011 18:02:00 GMT"}`, + wantErr: false, + want: Req{CreatedAt: RFC2822Time(time.Date(2011, 10, 13, 18, 2, 0, 0, time.UTC))}, + }, + { + name: "RFC1123Z", + s: `{"created_at":"Thu, 13 Oct 2011 18:02:00 +0000"}`, + wantErr: false, + want: Req{CreatedAt: RFC2822Time(time.Date(2011, 10, 13, 18, 2, 0, 0, time.UTC))}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var req Req + err := json.Unmarshal([]byte(tt.s), &req) + if (err != nil) != tt.wantErr { + t.Errorf("error = %v, wantErr %v", err, tt.wantErr) + } + + ensure.True(t, time.Time(tt.want.CreatedAt).Equal(time.Time(req.CreatedAt)), + fmt.Sprintf("want: %s; got: %s", tt.want.CreatedAt, req.CreatedAt)) + }) + } +}