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) + } +}