diff --git a/drivers/189_tv/help.go b/drivers/189_tv/help.go
index 6d48a3972..1f130c560 100644
--- a/drivers/189_tv/help.go
+++ b/drivers/189_tv/help.go
@@ -5,6 +5,7 @@ import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
+ "encoding/json"
"encoding/xml"
"fmt"
"net/http"
@@ -59,7 +60,13 @@ func timestamp() int64 {
type Time time.Time
-func (t *Time) UnmarshalJSON(b []byte) error { return t.Unmarshal(b) }
+func (t *Time) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ return t.Unmarshal([]byte(s))
+}
func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
b, err := e.Token()
if err != nil {
diff --git a/drivers/189_tv/help_test.go b/drivers/189_tv/help_test.go
index ce7489f2a..6643a5aa9 100644
--- a/drivers/189_tv/help_test.go
+++ b/drivers/189_tv/help_test.go
@@ -1,6 +1,8 @@
package _189_tv
import (
+ "encoding/json"
+ "encoding/xml"
"testing"
"time"
)
@@ -17,11 +19,13 @@ func TestTimeUnmarshal(t *testing.T) {
{"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))},
+ {"JSON escaped narrow space", `"Sep 4, 2026, 10:59:33\u202fPM +08"`, time.Date(2026, 9, 4, 22, 59, 33, 0, time.FixedZone("", 8*3600))},
+ {"JSON escaped space without timezone", `"Sep 4, 2026, 12:59:33\u00a0AM"`, time.Date(2026, 9, 4, 0, 59, 33, 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 {
+ if err := json.Unmarshal([]byte(tt.input), &tm); err != nil {
t.Fatalf("Unmarshal(%s) error: %v", tt.input, err)
}
if !tt.want.Equal(time.Time(tm)) {
@@ -37,3 +41,25 @@ func TestTimeUnmarshalRejectsInvalid(t *testing.T) {
t.Fatal("Unmarshal accepted an invalid time")
}
}
+
+func TestTimeUnmarshalJSONRejectsInvalid(t *testing.T) {
+ for _, input := range []string{`"invalid"`, `123`, `null`, `"Sep 4, 2026, 10:59:33\uZZZZPM +08"`} {
+ t.Run(input, func(t *testing.T) {
+ var tm Time
+ if err := tm.UnmarshalJSON([]byte(input)); err == nil {
+ t.Fatalf("UnmarshalJSON(%s) accepted invalid input", input)
+ }
+ })
+ }
+}
+
+func TestTimeUnmarshalXML(t *testing.T) {
+ var tm Time
+ if err := xml.Unmarshal([]byte(``), &tm); err != nil {
+ t.Fatal(err)
+ }
+ want := time.Date(2026, 9, 4, 22, 59, 33, 0, time.FixedZone("", 8*3600))
+ if !want.Equal(time.Time(tm)) {
+ t.Fatalf("UnmarshalXML = %v, want %v", time.Time(tm), want)
+ }
+}
diff --git a/drivers/189pc/help.go b/drivers/189pc/help.go
index a90ee9ee6..5d6959402 100644
--- a/drivers/189pc/help.go
+++ b/drivers/189pc/help.go
@@ -9,6 +9,7 @@ import (
"crypto/sha1"
"crypto/x509"
"encoding/hex"
+ "encoding/json"
"encoding/pem"
"encoding/xml"
"fmt"
@@ -102,7 +103,13 @@ func MustParseTime(str string) *time.Time {
type Time time.Time
-func (t *Time) UnmarshalJSON(b []byte) error { return t.Unmarshal(b) }
+func (t *Time) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ return t.Unmarshal([]byte(s))
+}
func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
b, err := e.Token()
if err != nil {
diff --git a/drivers/189pc/help_test.go b/drivers/189pc/help_test.go
index 579978f57..6c91df126 100644
--- a/drivers/189pc/help_test.go
+++ b/drivers/189pc/help_test.go
@@ -1,6 +1,8 @@
package _189pc
import (
+ "encoding/json"
+ "encoding/xml"
"testing"
"time"
)
@@ -17,11 +19,13 @@ func TestTimeUnmarshal(t *testing.T) {
{"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))},
+ {"JSON escaped narrow space", `"Sep 4, 2026, 10:59:33\u202fPM +08"`, time.Date(2026, 9, 4, 22, 59, 33, 0, time.FixedZone("", 8*3600))},
+ {"JSON escaped space without timezone", `"Sep 4, 2026, 12:59:33\u00a0AM"`, time.Date(2026, 9, 4, 0, 59, 33, 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 {
+ if err := json.Unmarshal([]byte(tt.input), &tm); err != nil {
t.Fatalf("Unmarshal(%s) error: %v", tt.input, err)
}
if !tt.want.Equal(time.Time(tm)) {
@@ -37,3 +41,25 @@ func TestTimeUnmarshalRejectsInvalid(t *testing.T) {
t.Fatal("Unmarshal accepted an invalid time")
}
}
+
+func TestTimeUnmarshalJSONRejectsInvalid(t *testing.T) {
+ for _, input := range []string{`"invalid"`, `123`, `null`, `"Sep 4, 2026, 10:59:33\uZZZZPM +08"`} {
+ t.Run(input, func(t *testing.T) {
+ var tm Time
+ if err := tm.UnmarshalJSON([]byte(input)); err == nil {
+ t.Fatalf("UnmarshalJSON(%s) accepted invalid input", input)
+ }
+ })
+ }
+}
+
+func TestTimeUnmarshalXML(t *testing.T) {
+ var tm Time
+ if err := xml.Unmarshal([]byte(``), &tm); err != nil {
+ t.Fatal(err)
+ }
+ want := time.Date(2026, 9, 4, 22, 59, 33, 0, time.FixedZone("", 8*3600))
+ if !want.Equal(time.Time(tm)) {
+ t.Fatalf("UnmarshalXML = %v, want %v", time.Time(tm), want)
+ }
+}