Skip to content

Commit 84fee8a

Browse files
authored
fix(ZenTao): add support for non-date string handling in UnmarshalJSON and introduce related tests (#8589)
* fix(jira): update epic collector to use new API endpoint and include all fields * fix(jira): enhance epic collector to dynamically select API endpoint based on JIRA version * fix(jira): update epic collector to use correct API endpoint for JIRA Cloud and Server versions * fix(jira): refactor epic collector to streamline API endpoint selection and enhance error handling * fix(jira): fix type for Jira issue descriptions * refactor(jira): update comment and worklog models to use FlexibleDescription type for comments * docs(jira): add ADF reference for FlexibleDescription type in issue model * refactor(migrations): enhance file meta migration to check column existence and nullability before modification * feat(gitextractor): add support for excluding file extensions in commit stats * fix(ZenTao): add support for non-date string handling in UnmarshalJSON and introduce related tests * Revert "feat(gitextractor): add support for excluding file extensions in commit stats" This reverts commit 71b27ba. * refactor(api): instantiate team and user objects directly in CreateTeam and CreateUser methods
1 parent 0d753c4 commit 84fee8a

File tree

4 files changed

+149
-4
lines changed

4 files changed

+149
-4
lines changed

backend/core/models/common/iso8601time.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ func (jt *Iso8601Time) UnmarshalJSON(b []byte) error {
111111
return nil
112112
}
113113
timeString = strings.Trim(timeString, `"`)
114+
115+
// Handle special cases for non-standard date representations
116+
// Some systems may use text like "长期" (long-term) instead of actual dates
117+
if isNonDateString(timeString) {
118+
jt.Time = time.Time{}
119+
return nil
120+
}
121+
114122
t, err := ConvertStringToTime(timeString)
115123
if err != nil {
116124
return err
@@ -119,6 +127,34 @@ func (jt *Iso8601Time) UnmarshalJSON(b []byte) error {
119127
return nil
120128
}
121129

130+
// isNonDateString checks if a string represents a non-date value like "long-term"
131+
func isNonDateString(s string) bool {
132+
// Handle various representations of "long-term" in different systems
133+
nonDateStrings := []string{
134+
"长期", // Chinese for "long-term"
135+
"\\u957f\\u671f", // Unicode escape sequence for "长期"
136+
"\\\\u957f\\\\u671f", // Double-escaped Unicode sequence
137+
"long-term", // English
138+
"永久", // Chinese for "permanent"
139+
"indefinite", // English
140+
"unlimited", // English
141+
}
142+
143+
for _, nonDate := range nonDateStrings {
144+
if s == nonDate {
145+
return true
146+
}
147+
}
148+
149+
// Also check if the string contains the Unicode escape pattern for "长期"
150+
// This handles cases where escape sequences might be processed differently
151+
if strings.Contains(s, "957f") && strings.Contains(s, "671f") {
152+
return true
153+
}
154+
155+
return false
156+
}
157+
122158
// ToTime FIXME ...
123159
func (jt *Iso8601Time) ToTime() time.Time {
124160
return jt.Time

backend/core/models/common/iso8601time_test.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"database/sql/driver"
2222
"fmt"
2323
"reflect"
24+
"strings"
2425
"testing"
2526
"time"
2627

@@ -162,6 +163,116 @@ func TestConvertStringToTime(t *testing.T) {
162163
}
163164
}
164165

166+
func TestIsNonDateString(t *testing.T) {
167+
testCases := []struct {
168+
name string
169+
input string
170+
output bool
171+
}{
172+
{
173+
name: "ZenTao long-term in Chinese",
174+
input: "长期",
175+
output: true,
176+
},
177+
{
178+
name: "ZenTao long-term in Unicode escape",
179+
input: "\\u957f\\u671f",
180+
output: true,
181+
},
182+
{
183+
name: "ZenTao long-term in double-escaped Unicode",
184+
input: "\\\\u957f\\\\u671f",
185+
output: true,
186+
},
187+
{
188+
name: "English long-term",
189+
input: "long-term",
190+
output: true,
191+
},
192+
{
193+
name: "Chinese permanent",
194+
input: "永久",
195+
output: true,
196+
},
197+
{
198+
name: "English indefinite",
199+
input: "indefinite",
200+
output: true,
201+
},
202+
{
203+
name: "English unlimited",
204+
input: "unlimited",
205+
output: true,
206+
},
207+
{
208+
name: "Valid date string",
209+
input: "2023-03-01",
210+
output: false,
211+
},
212+
{
213+
name: "Valid datetime string",
214+
input: "2023-03-01T12:30:00Z",
215+
output: false,
216+
},
217+
{
218+
name: "Random string",
219+
input: "random",
220+
output: false,
221+
},
222+
}
223+
for _, tc := range testCases {
224+
t.Run(tc.name, func(t *testing.T) {
225+
output := isNonDateString(tc.input)
226+
assert.Equal(t, tc.output, output, "Expected output to be %v, but got %v", tc.output, output)
227+
})
228+
}
229+
}
230+
231+
func TestIso8601Time_UnmarshalJSON_NonDateStrings(t *testing.T) {
232+
testCases := []struct {
233+
name string
234+
input string
235+
shouldErr bool
236+
}{
237+
{
238+
name: "ZenTao long-term in Chinese",
239+
input: `"长期"`,
240+
shouldErr: false,
241+
},
242+
{
243+
name: "ZenTao long-term in Unicode escape",
244+
input: `"\\u957f\\u671f"`,
245+
shouldErr: false,
246+
},
247+
{
248+
name: "English long-term",
249+
input: `"long-term"`,
250+
shouldErr: false,
251+
},
252+
{
253+
name: "Valid date",
254+
input: `"2023-03-01T12:30:00Z"`,
255+
shouldErr: false,
256+
},
257+
}
258+
259+
for _, tc := range testCases {
260+
t.Run(tc.name, func(t *testing.T) {
261+
var iso8601Time Iso8601Time
262+
err := iso8601Time.UnmarshalJSON([]byte(tc.input))
263+
if tc.shouldErr {
264+
assert.Error(t, err)
265+
} else {
266+
assert.NoError(t, err)
267+
// For non-date strings, the time should be zero
268+
if isNonDateString(strings.Trim(tc.input, `"`)) {
269+
assert.True(t, iso8601Time.Time.IsZero(), "Expected zero time for non-date string")
270+
}
271+
}
272+
})
273+
}
274+
}
275+
165276
func TestConvertStringToTimeInLoc(t *testing.T) {
166277
loc, err := time.LoadLocation("Asia/Shanghai")
167278
if err != nil {

backend/plugins/org/api/team.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,8 @@ func (h *Handlers) CreateTeam(input *plugin.ApiResourceInput) (*plugin.ApiResour
8080
if err != nil {
8181
return nil, err
8282
}
83-
var t *team
8483
var items []interface{}
85-
for _, tm := range t.toDomainLayer(tt) {
84+
for _, tm := range (&team{}).toDomainLayer(tt) {
8685
items = append(items, tm)
8786
}
8887
err = h.store.deleteAll(&crossdomain.Team{})

backend/plugins/org/api/user.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,8 @@ func (h *Handlers) CreateUser(input *plugin.ApiResourceInput) (*plugin.ApiResour
7979
if err != nil {
8080
return nil, err
8181
}
82-
var u *user
8382
var items []interface{}
84-
users, teamUsers := u.toDomainLayer(uu)
83+
users, teamUsers := (&user{}).toDomainLayer(uu)
8584
for _, user := range users {
8685
items = append(items, user)
8786
}

0 commit comments

Comments
 (0)