[chore] Serialize times as UTC ISO8601 instead of RFC3339 (#602)

* add time util to mimic utc ISO8601

* use ISO8601 when serializing to frontend

* update test notification
This commit is contained in:
tobi 2022-05-24 18:21:27 +02:00 committed by GitHub
parent 196d542e4a
commit a54efa09f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 10 deletions

View File

@ -44,7 +44,7 @@ func (suite *NotificationTestSuite) TestStreamNotification() {
notification := &apimodel.Notification{ notification := &apimodel.Notification{
ID: "01FH57SJCMDWQGEAJ0X08CE3WV", ID: "01FH57SJCMDWQGEAJ0X08CE3WV",
Type: "follow", Type: "follow",
CreatedAt: "2021-10-04T10:52:36+02:00", CreatedAt: "2021-10-04T08:52:36Z",
Account: followAccountAPIModel, Account: followAccountAPIModel,
} }
@ -52,7 +52,7 @@ func (suite *NotificationTestSuite) TestStreamNotification() {
suite.NoError(err) suite.NoError(err)
msg := <-openStream.Messages msg := <-openStream.Messages
suite.Equal(`{"id":"01FH57SJCMDWQGEAJ0X08CE3WV","type":"follow","created_at":"2021-10-04T10:52:36+02:00","account":{"id":"01F8MH5ZK5VRH73AKHQM6Y9VNX","username":"foss_satan","acct":"foss_satan@fossbros-anonymous.io","display_name":"big gerald","locked":false,"bot":false,"created_at":"2021-09-26T12:52:36+02:00","note":"i post about like, i dunno, stuff, or whatever!!!!","url":"http://fossbros-anonymous.io/@foss_satan","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":0,"following_count":0,"statuses_count":1,"last_status_at":"2021-09-20T10:40:37Z","emojis":[],"fields":[]}}`, msg.Payload) suite.Equal(`{"id":"01FH57SJCMDWQGEAJ0X08CE3WV","type":"follow","created_at":"2021-10-04T08:52:36Z","account":{"id":"01F8MH5ZK5VRH73AKHQM6Y9VNX","username":"foss_satan","acct":"foss_satan@fossbros-anonymous.io","display_name":"big gerald","locked":false,"bot":false,"created_at":"2021-09-26T10:52:36Z","note":"i post about like, i dunno, stuff, or whatever!!!!","url":"http://fossbros-anonymous.io/@foss_satan","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":0,"following_count":0,"statuses_count":1,"last_status_at":"2021-09-20T10:40:37Z","emojis":[],"fields":[]}}`, msg.Payload)
} }
func TestNotificationTestSuite(t *testing.T) { func TestNotificationTestSuite(t *testing.T) {

View File

@ -22,7 +22,6 @@ import (
"context" "context"
"fmt" "fmt"
"strings" "strings"
"time"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -31,6 +30,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/util"
) )
func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmodel.Account) (*model.Account, error) { func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmodel.Account) (*model.Account, error) {
@ -93,7 +93,7 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
var lastStatusAt string var lastStatusAt string
lastPosted, err := c.db.GetAccountLastPosted(ctx, a.ID) lastPosted, err := c.db.GetAccountLastPosted(ctx, a.ID)
if err == nil && !lastPosted.IsZero() { if err == nil && !lastPosted.IsZero() {
lastStatusAt = lastPosted.Format(time.RFC3339) lastStatusAt = util.FormatISO8601(lastPosted)
} }
// set account avatar fields if available // set account avatar fields if available
@ -140,7 +140,7 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
Value: f.Value, Value: f.Value,
} }
if !f.VerifiedAt.IsZero() { if !f.VerifiedAt.IsZero() {
mField.VerifiedAt = f.VerifiedAt.Format(time.RFC3339) mField.VerifiedAt = util.FormatISO8601(f.VerifiedAt)
} }
fields = append(fields, mField) fields = append(fields, mField)
} }
@ -169,7 +169,7 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
DisplayName: a.DisplayName, DisplayName: a.DisplayName,
Locked: a.Locked, Locked: a.Locked,
Bot: a.Bot, Bot: a.Bot,
CreatedAt: a.CreatedAt.Format(time.RFC3339), CreatedAt: util.FormatISO8601(a.CreatedAt),
Note: a.Note, Note: a.Note,
URL: a.URL, URL: a.URL,
Avatar: aviURL, Avatar: aviURL,
@ -209,7 +209,7 @@ func (c *converter) AccountToAPIAccountBlocked(ctx context.Context, a *gtsmodel.
Acct: acct, Acct: acct,
DisplayName: a.DisplayName, DisplayName: a.DisplayName,
Bot: a.Bot, Bot: a.Bot,
CreatedAt: a.CreatedAt.Format(time.RFC3339), CreatedAt: util.FormatISO8601(a.CreatedAt),
URL: a.URL, URL: a.URL,
Suspended: suspended, Suspended: suspended,
}, nil }, nil
@ -511,7 +511,7 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r
apiStatus := &model.Status{ apiStatus := &model.Status{
ID: s.ID, ID: s.ID,
CreatedAt: s.CreatedAt.Format(time.RFC3339), CreatedAt: util.FormatISO8601(s.CreatedAt),
InReplyToID: s.InReplyToID, InReplyToID: s.InReplyToID,
InReplyToAccountID: s.InReplyToAccountID, InReplyToAccountID: s.InReplyToAccountID,
Sensitive: s.Sensitive, Sensitive: s.Sensitive,
@ -695,7 +695,7 @@ func (c *converter) NotificationToAPINotification(ctx context.Context, n *gtsmod
return &model.Notification{ return &model.Notification{
ID: n.ID, ID: n.ID,
Type: string(n.NotificationType), Type: string(n.NotificationType),
CreatedAt: n.CreatedAt.Format(time.RFC3339), CreatedAt: util.FormatISO8601(n.CreatedAt),
Account: apiAccount, Account: apiAccount,
Status: apiStatus, Status: apiStatus,
}, nil }, nil
@ -714,7 +714,7 @@ func (c *converter) DomainBlockToAPIDomainBlock(ctx context.Context, b *gtsmodel
domainBlock.PrivateComment = b.PrivateComment domainBlock.PrivateComment = b.PrivateComment
domainBlock.SubscriptionID = b.SubscriptionID domainBlock.SubscriptionID = b.SubscriptionID
domainBlock.CreatedBy = b.CreatedByAccountID domainBlock.CreatedBy = b.CreatedByAccountID
domainBlock.CreatedAt = b.CreatedAt.Format(time.RFC3339) domainBlock.CreatedAt = util.FormatISO8601(b.CreatedAt)
} }
return domainBlock, nil return domainBlock, nil

30
internal/util/time.go Normal file
View File

@ -0,0 +1,30 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package util
import "time"
// ISO8601 is a formatter for serializing times that forces ISO8601 behavior.
const ISO8601 = "2006-01-02T15:04:05Z"
// FormatISO8601 converts the given time to UTC and then formats it
// using the ISO8601 const, which the Mastodon API is able to understand.
func FormatISO8601(t time.Time) string {
return t.UTC().Format(ISO8601)
}

View File

@ -0,0 +1,53 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package util_test
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/testrig"
)
type TimeSuite struct {
suite.Suite
}
func (suite *TimeSuite) TestISO8601Format1() {
testTime := testrig.TimeMustParse("2022-05-17T13:10:59Z")
testTimeString := util.FormatISO8601(testTime)
suite.Equal("2022-05-17T13:10:59Z", testTimeString)
}
func (suite *TimeSuite) TestISO8601Format2() {
testTime := testrig.TimeMustParse("2022-05-09T07:34:35+02:00")
testTimeString := util.FormatISO8601(testTime)
suite.Equal("2022-05-09T05:34:35Z", testTimeString)
}
func (suite *TimeSuite) TestISO8601Format3() {
testTime := testrig.TimeMustParse("2021-10-04T10:52:36+02:00")
testTimeString := util.FormatISO8601(testTime)
suite.Equal("2021-10-04T08:52:36Z", testTimeString)
}
func TestTimeSuite(t *testing.T) {
suite.Run(t, &TimeSuite{})
}