Skip to content

Commit 550ac86

Browse files
committed
Implement timeutil.ParseDateTimeGraceful()
1 parent f545aeb commit 550ac86

File tree

3 files changed

+105
-18
lines changed

3 files changed

+105
-18
lines changed

modules/timeutil/datetime.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"html"
99
"html/template"
10+
"strconv"
1011
"time"
1112
)
1213

@@ -58,3 +59,29 @@ func DateTime(format string, datetime any) template.HTML {
5859
}
5960
panic(fmt.Sprintf("Unsupported format %s", format))
6061
}
62+
63+
func ParseDateTimeGraceful(datetime any) (time.Time, error) {
64+
switch val := datetime.(type) {
65+
case string:
66+
if timestamp, err := strconv.ParseInt(val, 10, 64); err == nil {
67+
return ParseDateTimeGraceful(timestamp)
68+
} else {
69+
t, err := time.Parse(time.RFC3339, val)
70+
if err != nil {
71+
return time.Time{}, err
72+
}
73+
return t, nil
74+
}
75+
case int64:
76+
switch {
77+
case val > 946684800000000: // 2999-12-31 00:00:00 in milliseconds
78+
return time.UnixMicro(val), nil
79+
case val > 946645200000: // 2000-01-01 00:00:00 in milliseconds
80+
return time.UnixMilli(val), nil
81+
default:
82+
return time.Unix(val, 0), nil
83+
}
84+
default:
85+
return time.Time{}, fmt.Errorf("unsupported data type: %T", datetime)
86+
}
87+
}

modules/timeutil/datetime_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,75 @@ func TestDateTime(t *testing.T) {
4343
actual = DateTime("full", refTimeStamp)
4444
assert.EqualValues(t, `<relative-time format="datetime" weekday="" year="numeric" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
4545
}
46+
47+
func TestParseDateTimeGraceful(t *testing.T) {
48+
testData := []struct {
49+
value any
50+
expected any
51+
isFail bool
52+
}{
53+
{
54+
value: "2006-01-02T15:04:05Z",
55+
expected: 1136214245,
56+
},
57+
{
58+
value: "2006-01-02T15:04:05.999Z",
59+
expected: 1136214245,
60+
},
61+
{
62+
value: "2006-01-02T15:04:05-07:00",
63+
expected: 1136239445,
64+
},
65+
{
66+
value: "2006-01-02T15:04:05.999-07:00",
67+
expected: 1136239445,
68+
},
69+
{
70+
value: 1136214245,
71+
expected: 1136214245,
72+
},
73+
{
74+
value: "1136214245",
75+
expected: 1136214245,
76+
},
77+
{
78+
value: 1622040867000,
79+
expected: 1622040867,
80+
},
81+
{
82+
value: "1622040867000",
83+
expected: 1622040867,
84+
},
85+
{
86+
value: "1622040867000",
87+
expected: 1622040867,
88+
},
89+
{
90+
value: 0,
91+
expected: -62135596800,
92+
isFail: true,
93+
},
94+
{
95+
value: nil,
96+
expected: -62135596800,
97+
isFail: true,
98+
},
99+
{
100+
value: "",
101+
expected: -62135596800,
102+
isFail: true,
103+
},
104+
}
105+
106+
for _, testCase := range testData {
107+
actual, err := ParseDateTimeGraceful(testCase.value)
108+
109+
if testCase.isFail == true {
110+
assert.NotNil(t, err)
111+
} else {
112+
assert.Nil(t, err)
113+
}
114+
115+
assert.EqualValues(t, testCase.expected, actual.Unix())
116+
}
117+
}

routers/api/v1/notify/user.go

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ package notify
55

66
import (
77
"net/http"
8-
"strconv"
9-
"time"
108

119
activities_model "code.gitea.io/gitea/models/activities"
1210
"code.gitea.io/gitea/modules/context"
1311
"code.gitea.io/gitea/modules/structs"
12+
"code.gitea.io/gitea/modules/timeutil"
1413
"code.gitea.io/gitea/services/convert"
1514
)
1615

@@ -131,23 +130,12 @@ func ReadNotifications(ctx *context.APIContext) {
131130
lastRead := int64(0)
132131
qLastRead := ctx.FormTrim("last_read_at")
133132
if len(qLastRead) > 0 {
134-
var tmpLastRead time.Time
135-
136-
// If qLastRead consists solely digits then parse it as a timestamp
137-
if _, err := strconv.Atoi(qLastRead); err == nil {
138-
timestamp, err := strconv.ParseInt(qLastRead, 10, 64)
139-
if err != nil {
140-
ctx.InternalServerError(err)
141-
return
142-
}
143-
tmpLastRead = time.Unix(timestamp, 0)
144-
} else {
145-
tmpLastRead, err = time.Parse(time.RFC3339, qLastRead)
146-
if err != nil {
147-
ctx.InternalServerError(err)
148-
return
149-
}
133+
tmpLastRead, err := timeutil.ParseDateTimeGraceful(qLastRead)
134+
if err != nil {
135+
ctx.InternalServerError(err)
136+
return
150137
}
138+
151139
if !tmpLastRead.IsZero() {
152140
lastRead = tmpLastRead.Unix()
153141
}

0 commit comments

Comments
 (0)