Skip to content

Commit e80ee00

Browse files
shelkenpi-mono
andauthored
fix(drivers/189): support updated 189 time format (#2919)
fix(drivers/189): support updated 189 time format with comma, timezone and unicode spaces 189 API 变更了时间返回格式,现有 Time.Unmarshal 无法解析,导致 189pc/189_tv 驱动所有写操作失败(Put → 500)。 新格式有三种形态,现有两个模板均无法覆盖: 1. "Aug 11, 2026, 10:37:18 PM +08" — 年份后多逗号,且自带时区 2. "Aug 12, 2026, 12:35:41\u202fAM +08" — AM/PM 前为 U+202F 窄不换行空格 3. "Aug 12, 2026, 12:35:41\u00a0AM +08" — AM/PM 前为 U+00A0 不换行空格 修复(189pc/help.go、189_tv/help.go 的 Time.Unmarshal): - 解析前将 U+202F 和 U+00A0 统一替换为普通空格 - 新增模板 "Jan 2, 2006, 3:04:05 PM -07"(带逗号,3 为 12 小时制配 PM) - 对可能不带时区的串,先试原串再试追加 " +08"(向后兼容) 新增 help_test.go 覆盖:数字日期、旧月份格式、新格式带/不带时区、 U+202F/U+00A0 空格、非法输入。 Fixes #2917 Generated-By: pi 0.84.1 Co-authored-by: Advanced <noreply@pi.dev>
1 parent 89077c3 commit e80ee00

4 files changed

Lines changed: 103 additions & 4 deletions

File tree

‎drivers/189_tv/help.go‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"regexp"
1212
"strings"
1313
"time"
14+
15+
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
1416
)
1517

1618
func clientSuffix() map[string]string {
@@ -72,10 +74,19 @@ func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
7274
}
7375
func (t *Time) Unmarshal(b []byte) error {
7476
bs := strings.Trim(string(b), "\"")
77+
// 189 时间串里 AM/PM 前可能使用 U+202F 窄不换行空格或 U+00A0 不换行空格,统一替换为普通空格
78+
bs = strings.ReplaceAll(bs, "\u202f", " ")
79+
bs = strings.ReplaceAll(bs, "\u00a0", " ")
7580
var v time.Time
7681
var err error
77-
for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 15:04:05 PM -07"} {
78-
v, err = time.ParseInLocation(f, bs+" +08", time.Local)
82+
// 189 返回的时间可能自带时区(如 "Aug 11, 2026, 10:37:18 PM +08"),也可能不带,分别尝试
83+
for _, s := range []string{bs, bs + " +08"} {
84+
for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 3:04:05 PM -07", "Jan 2, 2006, 3:04:05 PM -07"} {
85+
v, err = time.ParseInLocation(f, s, utils.CNLoc)
86+
if err == nil {
87+
break
88+
}
89+
}
7990
if err == nil {
8091
break
8192
}

‎drivers/189_tv/help_test.go‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package _189_tv
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestTimeUnmarshal(t *testing.T) {
9+
tests := []struct {
10+
name string
11+
input string
12+
want time.Time
13+
}{
14+
{"numeric date", `"2026-08-11 10:37:18"`, time.Date(2026, 8, 11, 10, 37, 18, 0, time.FixedZone("", 8*3600))},
15+
{"legacy month date", `"Aug 11, 2026 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))},
16+
{"new format with tz", `"Aug 11, 2026, 10:37:18 PM +08"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))},
17+
{"new format no tz", `"Aug 11, 2026, 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))},
18+
{"narrow no-break space (U+202F)", "\"Aug 12, 2026, 12:35:41\u202fAM +08\"", time.Date(2026, 8, 12, 0, 35, 41, 0, time.FixedZone("", 8*3600))},
19+
{"no-break space (U+00A0)", "\"Aug 12, 2026, 12:35:41\u00a0AM +08\"", time.Date(2026, 8, 12, 0, 35, 41, 0, time.FixedZone("", 8*3600))},
20+
}
21+
for _, tt := range tests {
22+
t.Run(tt.name, func(t *testing.T) {
23+
var tm Time
24+
if err := tm.Unmarshal([]byte(tt.input)); err != nil {
25+
t.Fatalf("Unmarshal(%s) error: %v", tt.input, err)
26+
}
27+
if !tt.want.Equal(time.Time(tm)) {
28+
t.Fatalf("Unmarshal(%s) = %v, want %v", tt.input, time.Time(tm), tt.want)
29+
}
30+
})
31+
}
32+
}
33+
34+
func TestTimeUnmarshalRejectsInvalid(t *testing.T) {
35+
var tm Time
36+
if err := tm.Unmarshal([]byte("Aug 12, 2026, 25:32:44 AM")); err == nil {
37+
t.Fatal("Unmarshal accepted an invalid time")
38+
}
39+
}

‎drivers/189pc/help.go‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"time"
2020

2121
"github.com/OpenListTeam/OpenList/v4/internal/model"
22+
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
2223
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
2324
)
2425

@@ -116,10 +117,19 @@ func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
116117
}
117118
func (t *Time) Unmarshal(b []byte) error {
118119
bs := strings.Trim(string(b), "\"")
120+
// 189 时间串里 AM/PM 前可能使用 U+202F 窄不换行空格或 U+00A0 不换行空格,统一替换为普通空格
121+
bs = strings.ReplaceAll(bs, "\u202f", " ")
122+
bs = strings.ReplaceAll(bs, "\u00a0", " ")
119123
var v time.Time
120124
var err error
121-
for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 15:04:05 PM -07"} {
122-
v, err = time.ParseInLocation(f, bs+" +08", time.Local)
125+
// 189 返回的时间可能自带时区(如 "Aug 11, 2026, 10:37:18 PM +08"),也可能不带,分别尝试
126+
for _, s := range []string{bs, bs + " +08"} {
127+
for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 3:04:05 PM -07", "Jan 2, 2006, 3:04:05 PM -07"} {
128+
v, err = time.ParseInLocation(f, s, utils.CNLoc)
129+
if err == nil {
130+
break
131+
}
132+
}
123133
if err == nil {
124134
break
125135
}

‎drivers/189pc/help_test.go‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package _189pc
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestTimeUnmarshal(t *testing.T) {
9+
tests := []struct {
10+
name string
11+
input string
12+
want time.Time
13+
}{
14+
{"numeric date", `"2026-08-11 10:37:18"`, time.Date(2026, 8, 11, 10, 37, 18, 0, time.FixedZone("", 8*3600))},
15+
{"legacy month date", `"Aug 11, 2026 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))},
16+
{"new format with tz", `"Aug 11, 2026, 10:37:18 PM +08"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))},
17+
{"new format no tz", `"Aug 11, 2026, 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))},
18+
{"narrow no-break space (U+202F)", "\"Aug 12, 2026, 12:35:41\u202fAM +08\"", time.Date(2026, 8, 12, 0, 35, 41, 0, time.FixedZone("", 8*3600))},
19+
{"no-break space (U+00A0)", "\"Aug 12, 2026, 12:35:41\u00a0AM +08\"", time.Date(2026, 8, 12, 0, 35, 41, 0, time.FixedZone("", 8*3600))},
20+
}
21+
for _, tt := range tests {
22+
t.Run(tt.name, func(t *testing.T) {
23+
var tm Time
24+
if err := tm.Unmarshal([]byte(tt.input)); err != nil {
25+
t.Fatalf("Unmarshal(%s) error: %v", tt.input, err)
26+
}
27+
if !tt.want.Equal(time.Time(tm)) {
28+
t.Fatalf("Unmarshal(%s) = %v, want %v", tt.input, time.Time(tm), tt.want)
29+
}
30+
})
31+
}
32+
}
33+
34+
func TestTimeUnmarshalRejectsInvalid(t *testing.T) {
35+
var tm Time
36+
if err := tm.Unmarshal([]byte("Aug 12, 2026, 25:32:44 AM")); err == nil {
37+
t.Fatal("Unmarshal accepted an invalid time")
38+
}
39+
}

0 commit comments

Comments
 (0)