diff --git a/drivers/189_tv/help.go b/drivers/189_tv/help.go index cfd9e18ab..6d48a3972 100644 --- a/drivers/189_tv/help.go +++ b/drivers/189_tv/help.go @@ -11,6 +11,8 @@ import ( "regexp" "strings" "time" + + "github.com/OpenListTeam/OpenList/v4/pkg/utils" ) func clientSuffix() map[string]string { @@ -72,10 +74,19 @@ func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error { } func (t *Time) Unmarshal(b []byte) error { bs := strings.Trim(string(b), "\"") + // 189 时间串里 AM/PM 前可能使用 U+202F 窄不换行空格或 U+00A0 不换行空格,统一替换为普通空格 + bs = strings.ReplaceAll(bs, "\u202f", " ") + bs = strings.ReplaceAll(bs, "\u00a0", " ") var v time.Time var err error - for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 15:04:05 PM -07"} { - v, err = time.ParseInLocation(f, bs+" +08", time.Local) + // 189 返回的时间可能自带时区(如 "Aug 11, 2026, 10:37:18 PM +08"),也可能不带,分别尝试 + for _, s := range []string{bs, bs + " +08"} { + 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"} { + v, err = time.ParseInLocation(f, s, utils.CNLoc) + if err == nil { + break + } + } if err == nil { break } diff --git a/drivers/189_tv/help_test.go b/drivers/189_tv/help_test.go new file mode 100644 index 000000000..ce7489f2a --- /dev/null +++ b/drivers/189_tv/help_test.go @@ -0,0 +1,39 @@ +package _189_tv + +import ( + "testing" + "time" +) + +func TestTimeUnmarshal(t *testing.T) { + tests := []struct { + name string + input string + want time.Time + }{ + {"numeric date", `"2026-08-11 10:37:18"`, time.Date(2026, 8, 11, 10, 37, 18, 0, time.FixedZone("", 8*3600))}, + {"legacy month date", `"Aug 11, 2026 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))}, + {"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))}, + {"new format no tz", `"Aug 11, 2026, 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))}, + {"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))}, + {"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))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tm Time + if err := tm.Unmarshal([]byte(tt.input)); err != nil { + t.Fatalf("Unmarshal(%s) error: %v", tt.input, err) + } + if !tt.want.Equal(time.Time(tm)) { + t.Fatalf("Unmarshal(%s) = %v, want %v", tt.input, time.Time(tm), tt.want) + } + }) + } +} + +func TestTimeUnmarshalRejectsInvalid(t *testing.T) { + var tm Time + if err := tm.Unmarshal([]byte("Aug 12, 2026, 25:32:44 AM")); err == nil { + t.Fatal("Unmarshal accepted an invalid time") + } +} diff --git a/drivers/189pc/help.go b/drivers/189pc/help.go index 6f6c59f30..a90ee9ee6 100644 --- a/drivers/189pc/help.go +++ b/drivers/189pc/help.go @@ -19,6 +19,7 @@ import ( "time" "github.com/OpenListTeam/OpenList/v4/internal/model" + "github.com/OpenListTeam/OpenList/v4/pkg/utils" "github.com/OpenListTeam/OpenList/v4/pkg/utils/random" ) @@ -116,10 +117,19 @@ func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error { } func (t *Time) Unmarshal(b []byte) error { bs := strings.Trim(string(b), "\"") + // 189 时间串里 AM/PM 前可能使用 U+202F 窄不换行空格或 U+00A0 不换行空格,统一替换为普通空格 + bs = strings.ReplaceAll(bs, "\u202f", " ") + bs = strings.ReplaceAll(bs, "\u00a0", " ") var v time.Time var err error - for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 15:04:05 PM -07"} { - v, err = time.ParseInLocation(f, bs+" +08", time.Local) + // 189 返回的时间可能自带时区(如 "Aug 11, 2026, 10:37:18 PM +08"),也可能不带,分别尝试 + for _, s := range []string{bs, bs + " +08"} { + 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"} { + v, err = time.ParseInLocation(f, s, utils.CNLoc) + if err == nil { + break + } + } if err == nil { break } diff --git a/drivers/189pc/help_test.go b/drivers/189pc/help_test.go new file mode 100644 index 000000000..579978f57 --- /dev/null +++ b/drivers/189pc/help_test.go @@ -0,0 +1,39 @@ +package _189pc + +import ( + "testing" + "time" +) + +func TestTimeUnmarshal(t *testing.T) { + tests := []struct { + name string + input string + want time.Time + }{ + {"numeric date", `"2026-08-11 10:37:18"`, time.Date(2026, 8, 11, 10, 37, 18, 0, time.FixedZone("", 8*3600))}, + {"legacy month date", `"Aug 11, 2026 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))}, + {"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))}, + {"new format no tz", `"Aug 11, 2026, 10:37:18 PM"`, time.Date(2026, 8, 11, 22, 37, 18, 0, time.FixedZone("", 8*3600))}, + {"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))}, + {"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))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tm Time + if err := tm.Unmarshal([]byte(tt.input)); err != nil { + t.Fatalf("Unmarshal(%s) error: %v", tt.input, err) + } + if !tt.want.Equal(time.Time(tm)) { + t.Fatalf("Unmarshal(%s) = %v, want %v", tt.input, time.Time(tm), tt.want) + } + }) + } +} + +func TestTimeUnmarshalRejectsInvalid(t *testing.T) { + var tm Time + if err := tm.Unmarshal([]byte("Aug 12, 2026, 25:32:44 AM")); err == nil { + t.Fatal("Unmarshal accepted an invalid time") + } +}